From 6e63e1c29657415725f4497dfff9a19c4fe5aa44 Mon Sep 17 00:00:00 2001 From: dehnert <dehnert@cs.rwth-aachen.de> Date: Mon, 3 Feb 2014 15:41:02 +0100 Subject: [PATCH 1/5] Minor bugfix. Former-commit-id: d53be4f673dc346f222d2df38393d59f8dacd481 --- src/counterexamples/MILPMinimalLabelSetGenerator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/counterexamples/MILPMinimalLabelSetGenerator.h b/src/counterexamples/MILPMinimalLabelSetGenerator.h index 004baa5b0..3ec8256ed 100644 --- a/src/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/counterexamples/MILPMinimalLabelSetGenerator.h @@ -1021,7 +1021,7 @@ namespace storm { LOG4CPLUS_ERROR(logger, "Illegal comparison operator in formula " << probBoundFormula->toString() << ". Only upper bounds are supported for counterexample generation."); throw storm::exceptions::InvalidPropertyException() << "Illegal comparison operator in formula " << probBoundFormula->toString() << ". Only upper bounds are supported for counterexample generation."; } - bool strictBound = probBoundFormula->getComparisonOperator() == storm::property::ComparisonType::LESS; + bool strictBound = !probBoundFormula->getComparisonOperator() == storm::property::ComparisonType::LESS; // Now derive the probability threshold we need to exceed as well as the phi and psi states. Simultaneously, check whether the formula is of a valid shape. double bound = probBoundFormula->getBound(); From e452d58ed01d721964898dd412ae61720600b8eb Mon Sep 17 00:00:00 2001 From: fp893004 <fp893004@rwth-aachen.de> Date: Wed, 26 Feb 2014 14:38:44 +0100 Subject: [PATCH 2/5] Fixed wrong parameter name for unix systems. Former-commit-id: 7cab693ae6c211d3fdeff78b4c158612a163f33e --- src/utility/ErrorHandling.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility/ErrorHandling.h b/src/utility/ErrorHandling.h index 0872757b6..5b9b50bdc 100644 --- a/src/utility/ErrorHandling.h +++ b/src/utility/ErrorHandling.h @@ -164,7 +164,7 @@ VOID CALLBACK stormWindowsSetTimerCallBack( void stormSetAlarm(uint_fast64_t timeoutSeconds) { #ifndef WINDOWS - alarm(timeout); + alarm(timeoutSeconds); #else // This needs more research (http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx) UINT_PTR retVal = SetTimer(NULL, 0, static_cast<UINT>(timeoutSeconds * 1000), static_cast<TIMERPROC>(&stormWindowsSetTimerCallBack)); From f0aa54823ea57a619e3adc5680ac665861b9dfde Mon Sep 17 00:00:00 2001 From: PBerger <philipp.berger@rwth-aachen.de> Date: Thu, 27 Feb 2014 18:10:18 +0100 Subject: [PATCH 3/5] Added glpk to resources. Wrote a CMakeLists.txt file for GLPK that works with MSVC, GCC and Clang. Former-commit-id: a9884f373682bc5d1dfc4bd3339b1dda41d7d515 --- CMakeLists.txt | 21 +- resources/3rdparty/glpk-4.53/AUTHORS | 33 + resources/3rdparty/glpk-4.53/CMakeLists.txt | 279 + resources/3rdparty/glpk-4.53/COPYING | 674 + resources/3rdparty/glpk-4.53/ChangeLog | 2747 +++ resources/3rdparty/glpk-4.53/INSTALL | 209 + resources/3rdparty/glpk-4.53/Makefile.am | 7 + resources/3rdparty/glpk-4.53/Makefile.in | 759 + resources/3rdparty/glpk-4.53/NEWS | 1741 ++ resources/3rdparty/glpk-4.53/README | 39 + resources/3rdparty/glpk-4.53/THANKS | 204 + resources/3rdparty/glpk-4.53/aclocal.m4 | 949 ++ resources/3rdparty/glpk-4.53/config.guess | 1537 ++ .../3rdparty/glpk-4.53/config.h.cmake.in | 27 + resources/3rdparty/glpk-4.53/config.h.in | 27 + resources/3rdparty/glpk-4.53/config.sub | 1789 ++ resources/3rdparty/glpk-4.53/configure | 13839 ++++++++++++++++ resources/3rdparty/glpk-4.53/configure.ac | 147 + resources/3rdparty/glpk-4.53/depcomp | 787 + resources/3rdparty/glpk-4.53/doc/cnfsat.pdf | Bin 0 -> 59926 bytes resources/3rdparty/glpk-4.53/doc/cnfsat.tex | 413 + resources/3rdparty/glpk-4.53/doc/glpk.pdf | Bin 0 -> 478088 bytes resources/3rdparty/glpk-4.53/doc/glpk.tex | 167 + resources/3rdparty/glpk-4.53/doc/glpk01.tex | 343 + resources/3rdparty/glpk-4.53/doc/glpk02.tex | 3428 ++++ resources/3rdparty/glpk-4.53/doc/glpk03.tex | 1572 ++ resources/3rdparty/glpk-4.53/doc/glpk04.tex | 1385 ++ resources/3rdparty/glpk-4.53/doc/glpk05.tex | 1090 ++ resources/3rdparty/glpk-4.53/doc/glpk06.tex | 441 + resources/3rdparty/glpk-4.53/doc/glpk07.tex | 258 + resources/3rdparty/glpk-4.53/doc/glpk08.tex | 738 + resources/3rdparty/glpk-4.53/doc/glpk09.tex | 424 + resources/3rdparty/glpk-4.53/doc/glpk10.tex | 166 + resources/3rdparty/glpk-4.53/doc/glpk11.tex | 203 + resources/3rdparty/glpk-4.53/doc/glpk12.tex | 707 + resources/3rdparty/glpk-4.53/doc/gmpl.pdf | Bin 0 -> 216026 bytes resources/3rdparty/glpk-4.53/doc/gmpl.tex | 4295 +++++ resources/3rdparty/glpk-4.53/doc/graphs.pdf | Bin 0 -> 214470 bytes resources/3rdparty/glpk-4.53/doc/graphs.tex | 4150 +++++ resources/3rdparty/glpk-4.53/doc/miplib2.txt | 135 + resources/3rdparty/glpk-4.53/doc/miplib3.txt | 143 + resources/3rdparty/glpk-4.53/doc/netlib.txt | 103 + .../3rdparty/glpk-4.53/doc/notes/dfeas.pdf | Bin 0 -> 63866 bytes .../3rdparty/glpk-4.53/doc/notes/gomory.pdf | Bin 0 -> 75445 bytes .../3rdparty/glpk-4.53/doc/notes/keller.pdf | Bin 0 -> 85985 bytes .../3rdparty/glpk-4.53/doc/notes/scaling.pdf | Bin 0 -> 42382 bytes .../3rdparty/glpk-4.53/doc/notes/updating.pdf | Bin 0 -> 41817 bytes resources/3rdparty/glpk-4.53/examples/INDEX | 52 + .../3rdparty/glpk-4.53/examples/Makefile.am | 15 + .../3rdparty/glpk-4.53/examples/Makefile.in | 558 + .../3rdparty/glpk-4.53/examples/assign.mod | 77 + resources/3rdparty/glpk-4.53/examples/bpp.mod | 83 + resources/3rdparty/glpk-4.53/examples/cal.mod | 49 + .../3rdparty/glpk-4.53/examples/cf12a.mod | 81 + .../3rdparty/glpk-4.53/examples/cf12b.mod | 88 + .../3rdparty/glpk-4.53/examples/cflsq.mod | 51 + .../3rdparty/glpk-4.53/examples/color.mod | 113 + .../3rdparty/glpk-4.53/examples/cplex/README | 44 + .../glpk-4.53/examples/cplex/concorde.txt | 121 + .../3rdparty/glpk-4.53/examples/cplex/cplex.c | 2130 +++ .../3rdparty/glpk-4.53/examples/cplex/cplex.h | 301 + resources/3rdparty/glpk-4.53/examples/cpp.mod | 67 + .../3rdparty/glpk-4.53/examples/crypto.mod | 84 + .../glpk-4.53/examples/csv/distances.csv | 7 + .../glpk-4.53/examples/csv/markets.csv | 4 + .../glpk-4.53/examples/csv/parameters.csv | 2 + .../glpk-4.53/examples/csv/plants.csv | 3 + .../glpk-4.53/examples/csv/transp_csv.mod | 70 + .../dbf/ForestMgt_Model_I_GIS_dbf.mod | 226 + .../glpk-4.53/examples/dbf/Forest_Cost.dbf | Bin 0 -> 1458 bytes .../glpk-4.53/examples/dbf/NetRev_Table.dbf | Bin 0 -> 11786 bytes .../3rdparty/glpk-4.53/examples/dbf/README | 2 + .../glpk-4.53/examples/dbf/TCost_Table.dbf | Bin 0 -> 11786 bytes .../examples/dbf/Yield_Table_Vol.dbf | Bin 0 -> 11786 bytes .../glpk-4.53/examples/dbf/cultural_pres.dbf | Bin 0 -> 96 bytes .../glpk-4.53/examples/dbf/mgt_year.dbf | Bin 0 -> 106 bytes .../glpk-4.53/examples/dbf/stands.dbf | Bin 0 -> 4323 bytes .../glpk-4.53/examples/dbf/standtype.dbf | Bin 0 -> 96 bytes resources/3rdparty/glpk-4.53/examples/dea.mod | 222 + .../3rdparty/glpk-4.53/examples/diet.mod | 99 + .../3rdparty/glpk-4.53/examples/dist.mod | 565 + .../3rdparty/glpk-4.53/examples/egypt.mod | 519 + .../3rdparty/glpk-4.53/examples/fctp.mod | 93 + .../3rdparty/glpk-4.53/examples/food.mod | 127 + .../3rdparty/glpk-4.53/examples/food2.mod | 150 + resources/3rdparty/glpk-4.53/examples/gap.mod | 79 + .../3rdparty/glpk-4.53/examples/glpsol.c | 10 + .../3rdparty/glpk-4.53/examples/graph.mod | 98 + .../3rdparty/glpk-4.53/examples/hashi.mod | 168 + .../3rdparty/glpk-4.53/examples/huge.mod | 25 + .../3rdparty/glpk-4.53/examples/iptsamp.c | 17 + .../3rdparty/glpk-4.53/examples/jssp.mod | 114 + .../3rdparty/glpk-4.53/examples/magic.mod | 54 + .../3rdparty/glpk-4.53/examples/maxcut.mod | 85 + .../3rdparty/glpk-4.53/examples/maxflow.mod | 83 + .../3rdparty/glpk-4.53/examples/mfasp.mod | 62 + .../3rdparty/glpk-4.53/examples/mfvsp.mod | 62 + .../3rdparty/glpk-4.53/examples/min01ks.mod | 111 + .../3rdparty/glpk-4.53/examples/misp.mod | 665 + .../3rdparty/glpk-4.53/examples/misp1.dat | 1489 ++ .../3rdparty/glpk-4.53/examples/misp2.dat | 3857 +++++ .../3rdparty/glpk-4.53/examples/money.mod | 62 + .../3rdparty/glpk-4.53/examples/mplsamp1.c | 32 + .../3rdparty/glpk-4.53/examples/mplsamp2.c | 39 + .../3rdparty/glpk-4.53/examples/murtagh.mps | 600 + .../3rdparty/glpk-4.53/examples/mvcp.mod | 43 + .../3rdparty/glpk-4.53/examples/netgen.c | 141 + .../3rdparty/glpk-4.53/examples/numbrix.mod | 84 + .../3rdparty/glpk-4.53/examples/oldapi/README | 11 + .../3rdparty/glpk-4.53/examples/oldapi/lpx.c | 1505 ++ .../3rdparty/glpk-4.53/examples/oldapi/lpx.h | 565 + .../glpk-4.53/examples/oldapi/lpxsamp.c | 51 + .../3rdparty/glpk-4.53/examples/pbn/9dom.dat | 65 + .../3rdparty/glpk-4.53/examples/pbn/README | 6 + .../3rdparty/glpk-4.53/examples/pbn/bucks.dat | 77 + .../3rdparty/glpk-4.53/examples/pbn/cat.dat | 67 + .../glpk-4.53/examples/pbn/dancer.dat | 42 + .../glpk-4.53/examples/pbn/dragon.dat | 61 + .../3rdparty/glpk-4.53/examples/pbn/edge.dat | 48 + .../glpk-4.53/examples/pbn/forever.dat | 77 + .../3rdparty/glpk-4.53/examples/pbn/knot.dat | 95 + .../3rdparty/glpk-4.53/examples/pbn/light.dat | 122 + .../3rdparty/glpk-4.53/examples/pbn/mum.dat | 101 + .../3rdparty/glpk-4.53/examples/pbn/pbn.mod | 268 + .../3rdparty/glpk-4.53/examples/pbn/pbn.pdf | Bin 0 -> 43620 bytes .../3rdparty/glpk-4.53/examples/pbn/pbn.tex | 279 + .../3rdparty/glpk-4.53/examples/pbn/petro.dat | 102 + .../3rdparty/glpk-4.53/examples/pbn/skid.dat | 66 + .../3rdparty/glpk-4.53/examples/pbn/swing.dat | 117 + resources/3rdparty/glpk-4.53/examples/plan.lp | 39 + .../3rdparty/glpk-4.53/examples/plan.mod | 39 + .../3rdparty/glpk-4.53/examples/plan.mps | 54 + .../3rdparty/glpk-4.53/examples/prod.mod | 331 + .../3rdparty/glpk-4.53/examples/qfit.mod | 49 + .../3rdparty/glpk-4.53/examples/queens.mod | 41 + .../3rdparty/glpk-4.53/examples/samp1.mps | 29 + .../3rdparty/glpk-4.53/examples/samp2.mps | 27 + .../3rdparty/glpk-4.53/examples/sample.asn | 40 + .../3rdparty/glpk-4.53/examples/sample.c | 52 + .../3rdparty/glpk-4.53/examples/sample.clq | 30 + .../3rdparty/glpk-4.53/examples/sample.cnf | 12 + .../3rdparty/glpk-4.53/examples/sample.col | 30 + .../3rdparty/glpk-4.53/examples/sample.max | 26 + .../3rdparty/glpk-4.53/examples/sample.min | 26 + resources/3rdparty/glpk-4.53/examples/sat.mod | 201 + .../glpk-4.53/examples/shiftcover.mod | 244 + .../3rdparty/glpk-4.53/examples/shikaku.mod | 107 + .../3rdparty/glpk-4.53/examples/sorting.mod | 67 + resources/3rdparty/glpk-4.53/examples/spp.mod | 67 + .../3rdparty/glpk-4.53/examples/spxsamp1.c | 18 + .../3rdparty/glpk-4.53/examples/spxsamp2.c | 20 + .../3rdparty/glpk-4.53/examples/sql/README | 5 + .../glpk-4.53/examples/sql/mysql_setup.sh | 6 + .../glpk-4.53/examples/sql/sudoku.sql | 101 + .../glpk-4.53/examples/sql/sudoku_mysql.mod | 113 + .../glpk-4.53/examples/sql/sudoku_odbc.mod | 111 + .../glpk-4.53/examples/sql/transp.sql | 45 + .../glpk-4.53/examples/sql/transp_mysql.mod | 71 + .../glpk-4.53/examples/sql/transp_odbc.mod | 72 + .../3rdparty/glpk-4.53/examples/stigler.mod | 411 + .../3rdparty/glpk-4.53/examples/sudoku.dat | 16 + .../3rdparty/glpk-4.53/examples/sudoku.mod | 84 + resources/3rdparty/glpk-4.53/examples/t1.cs | 99 + resources/3rdparty/glpk-4.53/examples/tas.mod | 486 + .../3rdparty/glpk-4.53/examples/todd.mod | 36 + .../3rdparty/glpk-4.53/examples/train.mod | 281 + .../3rdparty/glpk-4.53/examples/transp.mod | 63 + .../3rdparty/glpk-4.53/examples/trick.mod | 72 + resources/3rdparty/glpk-4.53/examples/tsp.mod | 335 + .../3rdparty/glpk-4.53/examples/xyacfs.mod | 56 + .../3rdparty/glpk-4.53/examples/yacfs.mod | 48 + .../3rdparty/glpk-4.53/examples/zebra.mod | 151 + resources/3rdparty/glpk-4.53/install-sh | 527 + resources/3rdparty/glpk-4.53/ltmain.sh | 9687 +++++++++++ resources/3rdparty/glpk-4.53/m4/libtool.m4 | 7831 +++++++++ resources/3rdparty/glpk-4.53/m4/ltoptions.m4 | 369 + resources/3rdparty/glpk-4.53/m4/ltsugar.m4 | 123 + resources/3rdparty/glpk-4.53/m4/ltversion.m4 | 23 + .../3rdparty/glpk-4.53/m4/lt~obsolete.m4 | 98 + resources/3rdparty/glpk-4.53/missing | 330 + .../glpk-4.53/resources/FindMySQL.cmake | 47 + .../glpk-4.53/resources/FindODBC.cmake | 60 + resources/3rdparty/glpk-4.53/src/Makefile.am | 167 + resources/3rdparty/glpk-4.53/src/Makefile.in | 1949 +++ resources/3rdparty/glpk-4.53/src/amd/COPYING | 502 + resources/3rdparty/glpk-4.53/src/amd/README | 58 + resources/3rdparty/glpk-4.53/src/amd/amd.h | 67 + resources/3rdparty/glpk-4.53/src/amd/amd_1.c | 181 + resources/3rdparty/glpk-4.53/src/amd/amd_2.c | 1842 ++ .../3rdparty/glpk-4.53/src/amd/amd_aat.c | 185 + .../3rdparty/glpk-4.53/src/amd/amd_control.c | 64 + .../3rdparty/glpk-4.53/src/amd/amd_defaults.c | 38 + .../3rdparty/glpk-4.53/src/amd/amd_dump.c | 180 + .../3rdparty/glpk-4.53/src/amd/amd_info.c | 120 + .../3rdparty/glpk-4.53/src/amd/amd_internal.h | 117 + .../3rdparty/glpk-4.53/src/amd/amd_order.c | 200 + .../glpk-4.53/src/amd/amd_post_tree.c | 121 + .../glpk-4.53/src/amd/amd_postorder.c | 207 + .../glpk-4.53/src/amd/amd_preprocess.c | 119 + .../3rdparty/glpk-4.53/src/amd/amd_valid.c | 93 + resources/3rdparty/glpk-4.53/src/avl.c | 406 + resources/3rdparty/glpk-4.53/src/avl.h | 74 + resources/3rdparty/glpk-4.53/src/bfd.c | 576 + resources/3rdparty/glpk-4.53/src/bfd.h | 73 + resources/3rdparty/glpk-4.53/src/bflib/fhv.c | 586 + resources/3rdparty/glpk-4.53/src/bflib/fhv.h | 114 + .../3rdparty/glpk-4.53/src/bflib/fhvint.c | 181 + .../3rdparty/glpk-4.53/src/bflib/fhvint.h | 74 + resources/3rdparty/glpk-4.53/src/bflib/ifu.c | 392 + resources/3rdparty/glpk-4.53/src/bflib/ifu.h | 99 + resources/3rdparty/glpk-4.53/src/bflib/luf.c | 575 + resources/3rdparty/glpk-4.53/src/bflib/luf.h | 213 + .../3rdparty/glpk-4.53/src/bflib/lufint.c | 218 + .../3rdparty/glpk-4.53/src/bflib/lufint.h | 73 + resources/3rdparty/glpk-4.53/src/bflib/sgf.c | 1407 ++ resources/3rdparty/glpk-4.53/src/bflib/sgf.h | 203 + resources/3rdparty/glpk-4.53/src/bflib/sva.c | 568 + resources/3rdparty/glpk-4.53/src/bflib/sva.h | 161 + resources/3rdparty/glpk-4.53/src/bfx.c | 89 + resources/3rdparty/glpk-4.53/src/bfx.h | 67 + resources/3rdparty/glpk-4.53/src/cglib/cfg.c | 409 + resources/3rdparty/glpk-4.53/src/cglib/cfg.h | 130 + resources/3rdparty/glpk-4.53/src/cglib/cfg1.c | 703 + .../3rdparty/glpk-4.53/src/colamd/COPYING | 502 + .../3rdparty/glpk-4.53/src/colamd/README | 98 + .../3rdparty/glpk-4.53/src/colamd/colamd.c | 3622 ++++ .../3rdparty/glpk-4.53/src/colamd/colamd.h | 69 + resources/3rdparty/glpk-4.53/src/draft.h | 32 + resources/3rdparty/glpk-4.53/src/env/alloc.c | 252 + resources/3rdparty/glpk-4.53/src/env/dlsup.c | 167 + resources/3rdparty/glpk-4.53/src/env/env.c | 237 + resources/3rdparty/glpk-4.53/src/env/env.h | 258 + resources/3rdparty/glpk-4.53/src/env/error.c | 170 + resources/3rdparty/glpk-4.53/src/env/stdc.h | 42 + resources/3rdparty/glpk-4.53/src/env/stdout.c | 262 + resources/3rdparty/glpk-4.53/src/env/stream.c | 475 + resources/3rdparty/glpk-4.53/src/env/time.c | 159 + resources/3rdparty/glpk-4.53/src/env/tls.c | 72 + resources/3rdparty/glpk-4.53/src/glpapi01.c | 1571 ++ resources/3rdparty/glpk-4.53/src/glpapi02.c | 492 + resources/3rdparty/glpk-4.53/src/glpapi03.c | 167 + resources/3rdparty/glpk-4.53/src/glpapi04.c | 157 + resources/3rdparty/glpk-4.53/src/glpapi05.c | 169 + resources/3rdparty/glpk-4.53/src/glpapi06.c | 822 + resources/3rdparty/glpk-4.53/src/glpapi07.c | 456 + resources/3rdparty/glpk-4.53/src/glpapi08.c | 388 + resources/3rdparty/glpk-4.53/src/glpapi09.c | 786 + resources/3rdparty/glpk-4.53/src/glpapi10.c | 305 + resources/3rdparty/glpk-4.53/src/glpapi11.c | 1235 ++ resources/3rdparty/glpk-4.53/src/glpapi12.c | 2237 +++ resources/3rdparty/glpk-4.53/src/glpapi13.c | 706 + resources/3rdparty/glpk-4.53/src/glpapi14.c | 272 + resources/3rdparty/glpk-4.53/src/glpapi15.c | 615 + resources/3rdparty/glpk-4.53/src/glpapi16.c | 330 + resources/3rdparty/glpk-4.53/src/glpapi17.c | 1269 ++ resources/3rdparty/glpk-4.53/src/glpapi18.c | 123 + resources/3rdparty/glpk-4.53/src/glpapi19.c | 133 + resources/3rdparty/glpk-4.53/src/glpapi20.c | 257 + resources/3rdparty/glpk-4.53/src/glpapi21.c | 1428 ++ resources/3rdparty/glpk-4.53/src/glpcpx.c | 1262 ++ resources/3rdparty/glpk-4.53/src/glpdmx.c | 1693 ++ resources/3rdparty/glpk-4.53/src/glpgmp.c | 1116 ++ resources/3rdparty/glpk-4.53/src/glpgmp.h | 190 + resources/3rdparty/glpk-4.53/src/glphbm.c | 529 + resources/3rdparty/glpk-4.53/src/glphbm.h | 127 + resources/3rdparty/glpk-4.53/src/glpini01.c | 155 + resources/3rdparty/glpk-4.53/src/glpini02.c | 270 + resources/3rdparty/glpk-4.53/src/glpios.h | 620 + resources/3rdparty/glpk-4.53/src/glpios01.c | 1602 ++ resources/3rdparty/glpk-4.53/src/glpios02.c | 826 + resources/3rdparty/glpk-4.53/src/glpios03.c | 1438 ++ resources/3rdparty/glpk-4.53/src/glpios04.c | 304 + resources/3rdparty/glpk-4.53/src/glpios05.c | 282 + resources/3rdparty/glpk-4.53/src/glpios06.c | 1448 ++ resources/3rdparty/glpk-4.53/src/glpios07.c | 551 + resources/3rdparty/glpk-4.53/src/glpios08.c | 147 + resources/3rdparty/glpk-4.53/src/glpios09.c | 664 + resources/3rdparty/glpk-4.53/src/glpios10.c | 355 + resources/3rdparty/glpk-4.53/src/glpios11.c | 282 + resources/3rdparty/glpk-4.53/src/glpios12.c | 177 + resources/3rdparty/glpk-4.53/src/glpipm.c | 1144 ++ resources/3rdparty/glpk-4.53/src/glpipm.h | 36 + resources/3rdparty/glpk-4.53/src/glpk.h | 1076 ++ resources/3rdparty/glpk-4.53/src/glplpf.c | 1097 ++ resources/3rdparty/glpk-4.53/src/glplpf.h | 216 + resources/3rdparty/glpk-4.53/src/glpmat.c | 924 ++ resources/3rdparty/glpk-4.53/src/glpmat.h | 198 + resources/3rdparty/glpk-4.53/src/glpmpl.h | 2594 +++ resources/3rdparty/glpk-4.53/src/glpmpl01.c | 4715 ++++++ resources/3rdparty/glpk-4.53/src/glpmpl02.c | 1203 ++ resources/3rdparty/glpk-4.53/src/glpmpl03.c | 6085 +++++++ resources/3rdparty/glpk-4.53/src/glpmpl04.c | 1427 ++ resources/3rdparty/glpk-4.53/src/glpmpl05.c | 563 + resources/3rdparty/glpk-4.53/src/glpmpl06.c | 1000 ++ resources/3rdparty/glpk-4.53/src/glpmps.c | 1433 ++ resources/3rdparty/glpk-4.53/src/glpnet03.c | 1020 ++ resources/3rdparty/glpk-4.53/src/glpnet04.c | 769 + resources/3rdparty/glpk-4.53/src/glpnet05.c | 368 + resources/3rdparty/glpk-4.53/src/glpnpp.h | 638 + resources/3rdparty/glpk-4.53/src/glpnpp01.c | 938 ++ resources/3rdparty/glpk-4.53/src/glpnpp02.c | 1434 ++ resources/3rdparty/glpk-4.53/src/glpnpp03.c | 2862 ++++ resources/3rdparty/glpk-4.53/src/glpnpp04.c | 1415 ++ resources/3rdparty/glpk-4.53/src/glpnpp05.c | 810 + resources/3rdparty/glpk-4.53/src/glpnpp06.c | 1501 ++ resources/3rdparty/glpk-4.53/src/glprgr.c | 165 + resources/3rdparty/glpk-4.53/src/glprgr.h | 34 + resources/3rdparty/glpk-4.53/src/glpscl.c | 478 + resources/3rdparty/glpk-4.53/src/glpsdf.c | 259 + resources/3rdparty/glpk-4.53/src/glpsdf.h | 63 + resources/3rdparty/glpk-4.53/src/glpspm.c | 847 + resources/3rdparty/glpk-4.53/src/glpspm.h | 165 + resources/3rdparty/glpk-4.53/src/glpspx.h | 40 + resources/3rdparty/glpk-4.53/src/glpspx01.c | 2971 ++++ resources/3rdparty/glpk-4.53/src/glpspx02.c | 3118 ++++ resources/3rdparty/glpk-4.53/src/glpsql.c | 1644 ++ resources/3rdparty/glpk-4.53/src/glpsql.h | 64 + resources/3rdparty/glpk-4.53/src/glpssx.h | 426 + resources/3rdparty/glpk-4.53/src/glpssx01.c | 839 + resources/3rdparty/glpk-4.53/src/glpssx02.c | 479 + resources/3rdparty/glpk-4.53/src/glptsp.c | 667 + resources/3rdparty/glpk-4.53/src/glptsp.h | 104 + resources/3rdparty/glpk-4.53/src/lux.c | 1030 ++ resources/3rdparty/glpk-4.53/src/lux.h | 220 + .../3rdparty/glpk-4.53/src/minisat/LICENSE | 20 + .../3rdparty/glpk-4.53/src/minisat/README | 22 + .../3rdparty/glpk-4.53/src/minisat/minisat.c | 1299 ++ .../3rdparty/glpk-4.53/src/minisat/minisat.h | 230 + .../3rdparty/glpk-4.53/src/misc/bignum.c | 286 + .../3rdparty/glpk-4.53/src/misc/bignum.h | 37 + resources/3rdparty/glpk-4.53/src/misc/dmp.c | 243 + resources/3rdparty/glpk-4.53/src/misc/dmp.h | 63 + resources/3rdparty/glpk-4.53/src/misc/ffalg.c | 221 + resources/3rdparty/glpk-4.53/src/misc/ffalg.h | 34 + .../3rdparty/glpk-4.53/src/misc/fp2rat.c | 164 + resources/3rdparty/glpk-4.53/src/misc/gcd.c | 102 + resources/3rdparty/glpk-4.53/src/misc/jd.c | 152 + resources/3rdparty/glpk-4.53/src/misc/jd.h | 32 + .../3rdparty/glpk-4.53/src/misc/keller.c | 235 + .../3rdparty/glpk-4.53/src/misc/keller.h | 34 + resources/3rdparty/glpk-4.53/src/misc/mc13d.c | 314 + resources/3rdparty/glpk-4.53/src/misc/mc13d.h | 34 + resources/3rdparty/glpk-4.53/src/misc/mc21a.c | 301 + resources/3rdparty/glpk-4.53/src/misc/mc21a.h | 34 + resources/3rdparty/glpk-4.53/src/misc/misc.h | 61 + resources/3rdparty/glpk-4.53/src/misc/okalg.c | 382 + resources/3rdparty/glpk-4.53/src/misc/okalg.h | 35 + resources/3rdparty/glpk-4.53/src/misc/qmd.c | 584 + resources/3rdparty/glpk-4.53/src/misc/qmd.h | 58 + .../3rdparty/glpk-4.53/src/misc/relax4.c | 2850 ++++ .../3rdparty/glpk-4.53/src/misc/relax4.h | 102 + resources/3rdparty/glpk-4.53/src/misc/rng.c | 227 + resources/3rdparty/glpk-4.53/src/misc/rng.h | 67 + resources/3rdparty/glpk-4.53/src/misc/rng1.c | 73 + .../3rdparty/glpk-4.53/src/misc/round2n.c | 64 + .../3rdparty/glpk-4.53/src/misc/str2int.c | 92 + .../3rdparty/glpk-4.53/src/misc/str2num.c | 110 + .../3rdparty/glpk-4.53/src/misc/strspx.c | 60 + .../3rdparty/glpk-4.53/src/misc/strtrim.c | 62 + .../3rdparty/glpk-4.53/src/misc/triang.c | 311 + .../3rdparty/glpk-4.53/src/misc/triang.h | 34 + .../3rdparty/glpk-4.53/src/misc/wclique.c | 242 + .../3rdparty/glpk-4.53/src/misc/wclique.h | 33 + .../3rdparty/glpk-4.53/src/misc/wclique1.c | 317 + .../3rdparty/glpk-4.53/src/misc/wclique1.h | 34 + resources/3rdparty/glpk-4.53/src/prob.h | 276 + resources/3rdparty/glpk-4.53/src/proxy/main.c | 87 + .../3rdparty/glpk-4.53/src/proxy/proxy.c | 1061 ++ .../3rdparty/glpk-4.53/src/proxy/proxy.h | 36 + .../3rdparty/glpk-4.53/src/proxy/proxy1.c | 39 + resources/3rdparty/glpk-4.53/src/zlib/README | 45 + .../3rdparty/glpk-4.53/src/zlib/adler32.c | 169 + .../3rdparty/glpk-4.53/src/zlib/compress.c | 80 + resources/3rdparty/glpk-4.53/src/zlib/crc32.c | 442 + resources/3rdparty/glpk-4.53/src/zlib/crc32.h | 441 + .../3rdparty/glpk-4.53/src/zlib/deflate.c | 1834 ++ .../3rdparty/glpk-4.53/src/zlib/deflate.h | 342 + .../3rdparty/glpk-4.53/src/zlib/gzclose.c | 25 + .../3rdparty/glpk-4.53/src/zlib/gzguts.h | 74 + resources/3rdparty/glpk-4.53/src/zlib/gzlib.c | 537 + .../3rdparty/glpk-4.53/src/zlib/gzread.c | 653 + .../3rdparty/glpk-4.53/src/zlib/gzwrite.c | 531 + .../3rdparty/glpk-4.53/src/zlib/inffast.c | 340 + .../3rdparty/glpk-4.53/src/zlib/inffast.h | 11 + .../3rdparty/glpk-4.53/src/zlib/inffixed.h | 94 + .../3rdparty/glpk-4.53/src/zlib/inflate.c | 1480 ++ .../3rdparty/glpk-4.53/src/zlib/inflate.h | 122 + .../3rdparty/glpk-4.53/src/zlib/inftrees.c | 330 + .../3rdparty/glpk-4.53/src/zlib/inftrees.h | 62 + resources/3rdparty/glpk-4.53/src/zlib/trees.c | 1244 ++ resources/3rdparty/glpk-4.53/src/zlib/trees.h | 128 + .../3rdparty/glpk-4.53/src/zlib/uncompr.c | 59 + resources/3rdparty/glpk-4.53/src/zlib/zconf.h | 168 + resources/3rdparty/glpk-4.53/src/zlib/zio.c | 92 + resources/3rdparty/glpk-4.53/src/zlib/zio.h | 37 + resources/3rdparty/glpk-4.53/src/zlib/zlib.h | 1613 ++ resources/3rdparty/glpk-4.53/src/zlib/zutil.c | 318 + resources/3rdparty/glpk-4.53/src/zlib/zutil.h | 93 + .../glpk-4.53/w32/Build_GLPK_with_VC10.bat | 11 + .../w32/Build_GLPK_with_VC10_DLL.bat | 11 + .../glpk-4.53/w32/Build_GLPK_with_VC9.bat | 11 + .../glpk-4.53/w32/Build_GLPK_with_VC9_DLL.bat | 11 + resources/3rdparty/glpk-4.53/w32/Makefile_VC | 191 + .../3rdparty/glpk-4.53/w32/Makefile_VC_DLL | 192 + resources/3rdparty/glpk-4.53/w32/config_VC | 13 + .../3rdparty/glpk-4.53/w32/glpk_4_53.def | 223 + resources/3rdparty/glpk-4.53/w32/readme.txt | 24 + .../glpk-4.53/w64/Build_GLPK_with_VC10.bat | 11 + .../w64/Build_GLPK_with_VC10_DLL.bat | 11 + .../glpk-4.53/w64/Build_GLPK_with_VC9.bat | 11 + .../glpk-4.53/w64/Build_GLPK_with_VC9_DLL.bat | 11 + resources/3rdparty/glpk-4.53/w64/config_VC | 13 + .../3rdparty/glpk-4.53/w64/glpk_4_53.def | 223 + resources/3rdparty/glpk-4.53/w64/makefile_VC | 191 + .../3rdparty/glpk-4.53/w64/makefile_VC_DLL | 192 + resources/3rdparty/glpk-4.53/w64/readme.txt | 24 + 416 files changed, 207922 insertions(+), 13 deletions(-) create mode 100644 resources/3rdparty/glpk-4.53/AUTHORS create mode 100644 resources/3rdparty/glpk-4.53/CMakeLists.txt create mode 100644 resources/3rdparty/glpk-4.53/COPYING create mode 100644 resources/3rdparty/glpk-4.53/ChangeLog create mode 100644 resources/3rdparty/glpk-4.53/INSTALL create mode 100644 resources/3rdparty/glpk-4.53/Makefile.am create mode 100644 resources/3rdparty/glpk-4.53/Makefile.in create mode 100644 resources/3rdparty/glpk-4.53/NEWS create mode 100644 resources/3rdparty/glpk-4.53/README create mode 100644 resources/3rdparty/glpk-4.53/THANKS create mode 100644 resources/3rdparty/glpk-4.53/aclocal.m4 create mode 100644 resources/3rdparty/glpk-4.53/config.guess create mode 100644 resources/3rdparty/glpk-4.53/config.h.cmake.in create mode 100644 resources/3rdparty/glpk-4.53/config.h.in create mode 100644 resources/3rdparty/glpk-4.53/config.sub create mode 100644 resources/3rdparty/glpk-4.53/configure create mode 100644 resources/3rdparty/glpk-4.53/configure.ac create mode 100644 resources/3rdparty/glpk-4.53/depcomp create mode 100644 resources/3rdparty/glpk-4.53/doc/cnfsat.pdf create mode 100644 resources/3rdparty/glpk-4.53/doc/cnfsat.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk.pdf create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk01.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk02.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk03.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk04.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk05.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk06.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk07.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk08.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk09.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk10.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk11.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/glpk12.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/gmpl.pdf create mode 100644 resources/3rdparty/glpk-4.53/doc/gmpl.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/graphs.pdf create mode 100644 resources/3rdparty/glpk-4.53/doc/graphs.tex create mode 100644 resources/3rdparty/glpk-4.53/doc/miplib2.txt create mode 100644 resources/3rdparty/glpk-4.53/doc/miplib3.txt create mode 100644 resources/3rdparty/glpk-4.53/doc/netlib.txt create mode 100644 resources/3rdparty/glpk-4.53/doc/notes/dfeas.pdf create mode 100644 resources/3rdparty/glpk-4.53/doc/notes/gomory.pdf create mode 100644 resources/3rdparty/glpk-4.53/doc/notes/keller.pdf create mode 100644 resources/3rdparty/glpk-4.53/doc/notes/scaling.pdf create mode 100644 resources/3rdparty/glpk-4.53/doc/notes/updating.pdf create mode 100644 resources/3rdparty/glpk-4.53/examples/INDEX create mode 100644 resources/3rdparty/glpk-4.53/examples/Makefile.am create mode 100644 resources/3rdparty/glpk-4.53/examples/Makefile.in create mode 100644 resources/3rdparty/glpk-4.53/examples/assign.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/bpp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/cal.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/cf12a.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/cf12b.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/cflsq.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/color.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/cplex/README create mode 100644 resources/3rdparty/glpk-4.53/examples/cplex/concorde.txt create mode 100644 resources/3rdparty/glpk-4.53/examples/cplex/cplex.c create mode 100644 resources/3rdparty/glpk-4.53/examples/cplex/cplex.h create mode 100644 resources/3rdparty/glpk-4.53/examples/cpp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/crypto.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/csv/distances.csv create mode 100644 resources/3rdparty/glpk-4.53/examples/csv/markets.csv create mode 100644 resources/3rdparty/glpk-4.53/examples/csv/parameters.csv create mode 100644 resources/3rdparty/glpk-4.53/examples/csv/plants.csv create mode 100644 resources/3rdparty/glpk-4.53/examples/csv/transp_csv.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/dbf/Forest_Cost.dbf create mode 100644 resources/3rdparty/glpk-4.53/examples/dbf/NetRev_Table.dbf create mode 100644 resources/3rdparty/glpk-4.53/examples/dbf/README create mode 100644 resources/3rdparty/glpk-4.53/examples/dbf/TCost_Table.dbf create mode 100644 resources/3rdparty/glpk-4.53/examples/dbf/Yield_Table_Vol.dbf create mode 100644 resources/3rdparty/glpk-4.53/examples/dbf/cultural_pres.dbf create mode 100644 resources/3rdparty/glpk-4.53/examples/dbf/mgt_year.dbf create mode 100644 resources/3rdparty/glpk-4.53/examples/dbf/stands.dbf create mode 100644 resources/3rdparty/glpk-4.53/examples/dbf/standtype.dbf create mode 100644 resources/3rdparty/glpk-4.53/examples/dea.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/diet.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/dist.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/egypt.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/fctp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/food.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/food2.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/gap.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/glpsol.c create mode 100644 resources/3rdparty/glpk-4.53/examples/graph.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/hashi.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/huge.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/iptsamp.c create mode 100644 resources/3rdparty/glpk-4.53/examples/jssp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/magic.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/maxcut.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/maxflow.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/mfasp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/mfvsp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/min01ks.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/misp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/misp1.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/misp2.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/money.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/mplsamp1.c create mode 100644 resources/3rdparty/glpk-4.53/examples/mplsamp2.c create mode 100644 resources/3rdparty/glpk-4.53/examples/murtagh.mps create mode 100644 resources/3rdparty/glpk-4.53/examples/mvcp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/netgen.c create mode 100644 resources/3rdparty/glpk-4.53/examples/numbrix.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/oldapi/README create mode 100644 resources/3rdparty/glpk-4.53/examples/oldapi/lpx.c create mode 100644 resources/3rdparty/glpk-4.53/examples/oldapi/lpx.h create mode 100644 resources/3rdparty/glpk-4.53/examples/oldapi/lpxsamp.c create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/9dom.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/README create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/bucks.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/cat.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/dancer.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/dragon.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/edge.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/forever.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/knot.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/light.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/mum.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/pbn.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/pbn.pdf create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/pbn.tex create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/petro.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/skid.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/pbn/swing.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/plan.lp create mode 100644 resources/3rdparty/glpk-4.53/examples/plan.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/plan.mps create mode 100644 resources/3rdparty/glpk-4.53/examples/prod.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/qfit.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/queens.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/samp1.mps create mode 100644 resources/3rdparty/glpk-4.53/examples/samp2.mps create mode 100644 resources/3rdparty/glpk-4.53/examples/sample.asn create mode 100644 resources/3rdparty/glpk-4.53/examples/sample.c create mode 100644 resources/3rdparty/glpk-4.53/examples/sample.clq create mode 100644 resources/3rdparty/glpk-4.53/examples/sample.cnf create mode 100644 resources/3rdparty/glpk-4.53/examples/sample.col create mode 100644 resources/3rdparty/glpk-4.53/examples/sample.max create mode 100644 resources/3rdparty/glpk-4.53/examples/sample.min create mode 100644 resources/3rdparty/glpk-4.53/examples/sat.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/shiftcover.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/shikaku.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/sorting.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/spp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/spxsamp1.c create mode 100644 resources/3rdparty/glpk-4.53/examples/spxsamp2.c create mode 100644 resources/3rdparty/glpk-4.53/examples/sql/README create mode 100644 resources/3rdparty/glpk-4.53/examples/sql/mysql_setup.sh create mode 100644 resources/3rdparty/glpk-4.53/examples/sql/sudoku.sql create mode 100644 resources/3rdparty/glpk-4.53/examples/sql/sudoku_mysql.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/sql/sudoku_odbc.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/sql/transp.sql create mode 100644 resources/3rdparty/glpk-4.53/examples/sql/transp_mysql.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/sql/transp_odbc.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/stigler.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/sudoku.dat create mode 100644 resources/3rdparty/glpk-4.53/examples/sudoku.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/t1.cs create mode 100644 resources/3rdparty/glpk-4.53/examples/tas.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/todd.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/train.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/transp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/trick.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/tsp.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/xyacfs.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/yacfs.mod create mode 100644 resources/3rdparty/glpk-4.53/examples/zebra.mod create mode 100644 resources/3rdparty/glpk-4.53/install-sh create mode 100644 resources/3rdparty/glpk-4.53/ltmain.sh create mode 100644 resources/3rdparty/glpk-4.53/m4/libtool.m4 create mode 100644 resources/3rdparty/glpk-4.53/m4/ltoptions.m4 create mode 100644 resources/3rdparty/glpk-4.53/m4/ltsugar.m4 create mode 100644 resources/3rdparty/glpk-4.53/m4/ltversion.m4 create mode 100644 resources/3rdparty/glpk-4.53/m4/lt~obsolete.m4 create mode 100644 resources/3rdparty/glpk-4.53/missing create mode 100644 resources/3rdparty/glpk-4.53/resources/FindMySQL.cmake create mode 100644 resources/3rdparty/glpk-4.53/resources/FindODBC.cmake create mode 100644 resources/3rdparty/glpk-4.53/src/Makefile.am create mode 100644 resources/3rdparty/glpk-4.53/src/Makefile.in create mode 100644 resources/3rdparty/glpk-4.53/src/amd/COPYING create mode 100644 resources/3rdparty/glpk-4.53/src/amd/README create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd.h create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_1.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_2.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_aat.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_control.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_defaults.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_dump.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_info.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_internal.h create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_order.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_post_tree.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_postorder.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_preprocess.c create mode 100644 resources/3rdparty/glpk-4.53/src/amd/amd_valid.c create mode 100644 resources/3rdparty/glpk-4.53/src/avl.c create mode 100644 resources/3rdparty/glpk-4.53/src/avl.h create mode 100644 resources/3rdparty/glpk-4.53/src/bfd.c create mode 100644 resources/3rdparty/glpk-4.53/src/bfd.h create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/fhv.c create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/fhv.h create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/fhvint.c create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/fhvint.h create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/ifu.c create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/ifu.h create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/luf.c create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/luf.h create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/lufint.c create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/lufint.h create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/sgf.c create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/sgf.h create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/sva.c create mode 100644 resources/3rdparty/glpk-4.53/src/bflib/sva.h create mode 100644 resources/3rdparty/glpk-4.53/src/bfx.c create mode 100644 resources/3rdparty/glpk-4.53/src/bfx.h create mode 100644 resources/3rdparty/glpk-4.53/src/cglib/cfg.c create mode 100644 resources/3rdparty/glpk-4.53/src/cglib/cfg.h create mode 100644 resources/3rdparty/glpk-4.53/src/cglib/cfg1.c create mode 100644 resources/3rdparty/glpk-4.53/src/colamd/COPYING create mode 100644 resources/3rdparty/glpk-4.53/src/colamd/README create mode 100644 resources/3rdparty/glpk-4.53/src/colamd/colamd.c create mode 100644 resources/3rdparty/glpk-4.53/src/colamd/colamd.h create mode 100644 resources/3rdparty/glpk-4.53/src/draft.h create mode 100644 resources/3rdparty/glpk-4.53/src/env/alloc.c create mode 100644 resources/3rdparty/glpk-4.53/src/env/dlsup.c create mode 100644 resources/3rdparty/glpk-4.53/src/env/env.c create mode 100644 resources/3rdparty/glpk-4.53/src/env/env.h create mode 100644 resources/3rdparty/glpk-4.53/src/env/error.c create mode 100644 resources/3rdparty/glpk-4.53/src/env/stdc.h create mode 100644 resources/3rdparty/glpk-4.53/src/env/stdout.c create mode 100644 resources/3rdparty/glpk-4.53/src/env/stream.c create mode 100644 resources/3rdparty/glpk-4.53/src/env/time.c create mode 100644 resources/3rdparty/glpk-4.53/src/env/tls.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi01.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi02.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi03.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi04.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi05.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi06.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi07.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi08.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi09.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi10.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi11.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi12.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi13.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi14.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi15.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi16.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi17.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi18.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi19.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi20.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpapi21.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpcpx.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpdmx.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpgmp.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpgmp.h create mode 100644 resources/3rdparty/glpk-4.53/src/glphbm.c create mode 100644 resources/3rdparty/glpk-4.53/src/glphbm.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpini01.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpini02.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpios01.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios02.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios03.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios04.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios05.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios06.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios07.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios08.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios09.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios10.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios11.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpios12.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpipm.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpipm.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpk.h create mode 100644 resources/3rdparty/glpk-4.53/src/glplpf.c create mode 100644 resources/3rdparty/glpk-4.53/src/glplpf.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpmat.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpmat.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpmpl.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpmpl01.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpmpl02.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpmpl03.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpmpl04.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpmpl05.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpmpl06.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpmps.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpnet03.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpnet04.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpnet05.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpnpp.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpnpp01.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpnpp02.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpnpp03.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpnpp04.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpnpp05.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpnpp06.c create mode 100644 resources/3rdparty/glpk-4.53/src/glprgr.c create mode 100644 resources/3rdparty/glpk-4.53/src/glprgr.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpscl.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpsdf.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpsdf.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpspm.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpspm.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpspx.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpspx01.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpspx02.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpsql.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpsql.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpssx.h create mode 100644 resources/3rdparty/glpk-4.53/src/glpssx01.c create mode 100644 resources/3rdparty/glpk-4.53/src/glpssx02.c create mode 100644 resources/3rdparty/glpk-4.53/src/glptsp.c create mode 100644 resources/3rdparty/glpk-4.53/src/glptsp.h create mode 100644 resources/3rdparty/glpk-4.53/src/lux.c create mode 100644 resources/3rdparty/glpk-4.53/src/lux.h create mode 100644 resources/3rdparty/glpk-4.53/src/minisat/LICENSE create mode 100644 resources/3rdparty/glpk-4.53/src/minisat/README create mode 100644 resources/3rdparty/glpk-4.53/src/minisat/minisat.c create mode 100644 resources/3rdparty/glpk-4.53/src/minisat/minisat.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/bignum.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/bignum.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/dmp.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/dmp.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/ffalg.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/ffalg.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/fp2rat.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/gcd.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/jd.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/jd.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/keller.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/keller.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/mc13d.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/mc13d.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/mc21a.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/mc21a.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/misc.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/okalg.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/okalg.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/qmd.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/qmd.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/relax4.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/relax4.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/rng.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/rng.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/rng1.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/round2n.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/str2int.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/str2num.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/strspx.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/strtrim.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/triang.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/triang.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/wclique.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/wclique.h create mode 100644 resources/3rdparty/glpk-4.53/src/misc/wclique1.c create mode 100644 resources/3rdparty/glpk-4.53/src/misc/wclique1.h create mode 100644 resources/3rdparty/glpk-4.53/src/prob.h create mode 100644 resources/3rdparty/glpk-4.53/src/proxy/main.c create mode 100644 resources/3rdparty/glpk-4.53/src/proxy/proxy.c create mode 100644 resources/3rdparty/glpk-4.53/src/proxy/proxy.h create mode 100644 resources/3rdparty/glpk-4.53/src/proxy/proxy1.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/README create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/adler32.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/compress.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/crc32.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/crc32.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/deflate.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/deflate.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/gzclose.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/gzguts.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/gzlib.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/gzread.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/gzwrite.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/inffast.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/inffast.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/inffixed.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/inflate.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/inflate.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/inftrees.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/inftrees.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/trees.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/trees.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/uncompr.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/zconf.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/zio.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/zio.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/zlib.h create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/zutil.c create mode 100644 resources/3rdparty/glpk-4.53/src/zlib/zutil.h create mode 100644 resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10.bat create mode 100644 resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10_DLL.bat create mode 100644 resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9.bat create mode 100644 resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9_DLL.bat create mode 100644 resources/3rdparty/glpk-4.53/w32/Makefile_VC create mode 100644 resources/3rdparty/glpk-4.53/w32/Makefile_VC_DLL create mode 100644 resources/3rdparty/glpk-4.53/w32/config_VC create mode 100644 resources/3rdparty/glpk-4.53/w32/glpk_4_53.def create mode 100644 resources/3rdparty/glpk-4.53/w32/readme.txt create mode 100644 resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10.bat create mode 100644 resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10_DLL.bat create mode 100644 resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9.bat create mode 100644 resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9_DLL.bat create mode 100644 resources/3rdparty/glpk-4.53/w64/config_VC create mode 100644 resources/3rdparty/glpk-4.53/w64/glpk_4_53.def create mode 100644 resources/3rdparty/glpk-4.53/w64/makefile_VC create mode 100644 resources/3rdparty/glpk-4.53/w64/makefile_VC_DLL create mode 100644 resources/3rdparty/glpk-4.53/w64/readme.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fbc351e4..addcb7a90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,6 @@ option(ENABLE_INTELTBB "Sets whether the Intel TBB is available." OFF) option(STORM_USE_COTIRE "Sets whether Cotire should be used (for building precompiled headers)." OFF) option(LINK_LIBCXXABI "Sets whether libc++abi should be linked." OFF) option(USE_LIBCXX "Sets whether the standard library is libc++." OFF) -option(ENABLE_GLPK "Sets whether StoRM is built with support for glpk." OFF) set(GUROBI_ROOT "" CACHE STRING "The root directory of Gurobi (if available).") set(Z3_ROOT "" CACHE STRING "The root directory of Z3 (if available).") set(ADDITIONAL_INCLUDE_DIRS "" CACHE STRING "Additional directories added to the include directories.") @@ -177,11 +176,7 @@ else() endif() # glpk defines -if (ENABLE_GLPK) - set(STORM_CPP_GLPK_DEF "define") -else() - set(STORM_CPP_GLPK_DEF "undef") -endif() +set(STORM_CPP_GLPK_DEF "define") # Z3 Defines if (ENABLE_Z3) @@ -360,15 +355,15 @@ endif(ENABLE_GUROBI) ############################################################# ## -## glpk (optional) +## glpk ## ############################################################# -if (ENABLE_GLPK) - message (STATUS "StoRM - Linking with glpk") - target_link_libraries(storm "glpk") - target_link_libraries(storm-functional-tests "glpk") - target_link_libraries(storm-performance-tests "glpk") -endif(ENABLE_GLPK) +message (STATUS "StoRM - Linking with glpk") +add_subdirectory("${PROJECT_SOURCE_DIR}/resources/3rdparty/glpk-4.53") +include_directories("${PROJECT_SOURCE_DIR}/resources/3rdparty/glpk-4.53/src") +target_link_libraries(storm "glpk") +target_link_libraries(storm-functional-tests "glpk") +target_link_libraries(storm-performance-tests "glpk") ############################################################# ## diff --git a/resources/3rdparty/glpk-4.53/AUTHORS b/resources/3rdparty/glpk-4.53/AUTHORS new file mode 100644 index 000000000..8771f0d86 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/AUTHORS @@ -0,0 +1,33 @@ +The GLPK package was developed and programmed by Andrew Makhorin, +Department for Applied Informatics, Moscow Aviation Institute, Moscow, +Russia. + +E-mail: <mao@gnu.org> + +Paper mail: 125871, Russia, Moscow, Volokolamskoye sh., 4, + Moscow Aviation Institute, Andrew O. Makhorin + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.2 (MingW32) + +mQGiBD8UdT8RBAC6yWYxoa1b7U973J0jBuQpgZnhXlGJJpMZgAW9efDBD17vhkJm +hPVOQBKRUeOOLcW3/a7NMoNLMdmF1Rgz1FPVy3RgBDsYj4Sp4RBCsX/o0xXh+jxe +gncr4bdN0Ruk03pezVtLi9oYygdxfI51SsjZ2vwYP6BhMwv+xrIgcnc4qwCgoCit +26mTd0FoGOmsQuipo6X5LaUD/1l7NqFIjiGdWthyG3TqsiK5Ew7xF3fLEABXKPjb +PMRTMucX8XXHmW8RUD1vP1uGDnEn6s+fjc3/RtaqKjqGMdLt4XgHQkImaVguNpSS +IxN3LaK600BgAbwSd1bomRqWNlczAM7469VvGG9ASpCBveUUrqwerHZcUbvngL62 +pIcqA/41dO0xYrOTqMRhuguYMgHL2xbwB2Aj2TqRwBm697DIS25B9nE+8UsbjGRx +q3EmeuHeZ5kN5RbESXkGUB8whIcYxvH16HRNmM1ZjmFoBVL2Z6S2gpa2ZUqsq7BZ +s+hriElm3dfOQCt79/o852uKWu5bSjw2yiemVA2T8tG4OoN6DrQjQW5kcmV3IE1h +a2hvcmluIDxtYW9AbWFpMi5yY25ldC5ydT6IWwQTEQIAGwUCPxR1PwYLCQgHAwID +FQIDAxYCAQIeAQIXgAAKCRDRe/IwWYHoGKpHAJ44MmzWKr8OiTc0Bb6/RD56aekp +3wCdGznQMCfWFkehQPbeNaB5yFIs+8a5AQ0EPxR1UBAEAO3U3H5M0iYv06C4kKty +6ReWyYH4CzMAfp2lPVUKzRSjPtoAJ6SkrBSKMT+U+DahxZ4K4HbinvHq3uvlwWax +xw0wKxJl4oY6EGE1Jqn3B//Ak47RaNMnrs9V739WT1YNRpQvh4wOCeMekBzksf43 +hm4dSV4PMQkLmrEeG2+BYaZnAAMFA/4tVHhjGRkxzcTcfHCB+Yo3PXeIQMuIs00c +VKCrNReLni/3BWZC0w9tFzZSdz+URXefPWDGuAC16vLCVOD06NcIQGutPe189dUn +Kf9Bl6qc9DyWsxSTdF/PbLqcLfEe9g7fHhIwdY+w/hSq2n3NEURMzHiMT1U3CvHd +As5IzV/yD4hGBBgRAgAGBQI/FHVQAAoJENF78jBZgegYRZEAmwReJkMSrbs0EQs2 +wjyTCMd5KDh3AKCR2/RvVad9RT3ShYnUiPPYTL2/Nw== +=OfLQ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/resources/3rdparty/glpk-4.53/CMakeLists.txt b/resources/3rdparty/glpk-4.53/CMakeLists.txt new file mode 100644 index 000000000..b09ec9e1c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/CMakeLists.txt @@ -0,0 +1,279 @@ +cmake_minimum_required (VERSION 2.8.6) + +# Set project name +project (glpk CXX C) + +# Add the resources/cmake folder to Module Search Path for FindMySQL.cmake +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/resources/") + +# Add base folder for better inclusion paths +include_directories("${PROJECT_SOURCE_DIR}") +include_directories("${PROJECT_SOURCE_DIR}/src") +include_directories("${PROJECT_SOURCE_DIR}/src/amd") +include_directories("${PROJECT_SOURCE_DIR}/src/bflib") +include_directories("${PROJECT_SOURCE_DIR}/src/cglib") +include_directories("${PROJECT_SOURCE_DIR}/src/colamd") +include_directories("${PROJECT_SOURCE_DIR}/src/env") +include_directories("${PROJECT_SOURCE_DIR}/src/minisat") +include_directories("${PROJECT_SOURCE_DIR}/src/misc") +include_directories("${PROJECT_SOURCE_DIR}/src/proxy") +include_directories("${PROJECT_SOURCE_DIR}/src/zlib") + +############################################################# +## +## CMake options of GLPK +## +############################################################# +option(WITH_GLPK_EXAMPLES "Also build examples and standalone executables" OFF) +option(WITH_GMP "Use GNU MO bignum library" OFF) +option(ENABLE_DL "Enable shared library support" OFF) +option(ENABLE_ODBC "Enable MathProg ODBC support" OFF) +option(ENABLE_MYSQL "Enable MathProg MySQL support" OFF) +option(DEBUG "Sets whether the DEBUG mode is used" OFF) +set(ADDITIONAL_INCLUDE_DIRS "" CACHE STRING "Additional directories added to the include directories.") +set(ADDITIONAL_LINK_DIRS "" CACHE STRING "Additional directories added to the link directories.") + +# If the DEBUG option was turned on, we will target a debug version and a release version otherwise +if (DEBUG) + set (CMAKE_BUILD_TYPE "DEBUG") +else() + set (CMAKE_BUILD_TYPE "RELEASE") +endif() +message(STATUS "GLPK - Building ${CMAKE_BUILD_TYPE} version.") +message(STATUS "GLPK - CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") +message(STATUS "GLPK - CMAKE_BUILD_TYPE (ENV): $ENV{CMAKE_BUILD_TYPE}") + + +############################################################# +## +## Compiler specific settings and definitions +## +############################################################# + +if(CMAKE_COMPILER_IS_GNUCC) + message(STATUS "GLPK - Using Compiler Configuration: GCC") + # Set standard flags for GCC + set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type") + add_definitions(-DHAVE_CONFIG_H=1) +elseif(MSVC) + message(STATUS "GLPK - Using Compiler Configuration: MSVC") + add_definitions(/D_SCL_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS) + add_definitions(/D_VARIADIC_MAX=10) + add_definitions(/DNOMINMAX) + add_definitions(/DHAVE_CONFIG_H=1) +else(CLANG) + message(STATUS "GLPK - Using Compiler Configuration: Clang (LLVM)") + # As CLANG is not set as a variable, we need to set it in case we have not matched another compiler. + set (CLANG ON) + # Set standard flags for clang + set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -funroll-loops -O3") + + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-return-type -Wno-return-type-c-linkage -Wno-unused-variable") + + set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") + add_definitions(-DHAVE_CONFIG_H=1) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -version-info=37:0:1 -export-symbols-regex='^glp_*'") +endif() + +############################################################# +## +## CMake-generated Config File for GLPK +## +############################################################# +include(CheckIncludeFiles) +include(CheckFunctionExists) +CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H) +CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY) +CHECK_INCLUDE_FILES(ltdl.h HAVE_LTDL) +CHECK_INCLUDE_FILES(dlfcn.h HAVE_DLFCN) +if(WITH_GMP) + message(STATUS "GLPK - Building with GMP Support") + CHECK_INCLUDE_FILE(gmp.h HAVE_GMP_H) + if (NOT HAVE_GMP_H) + message(SEND_ERROR "Could not find gmp.h!") + endif() + set(GLPK_HAVE_GMP "define") +else() + set(GLPK_HAVE_GMP "undef") +endif() + +if (UNIX AND NOT APPLE) + set(LIBIODBC "libiodbc.so") + set(LIBODBC "libodbc.so") + set(LIBMYSQL "libmysqlclient.so") +elseif(UNIX AND APPLE) + set(LIBIODBC "libiodbc.dylib") + set(LIBODBC "libodbc.dylib") + set(LIBMYSQL "libmysqlclient.dylib") +elseif(MSVC) + set(LIBIODBC "odbc32.lib") + set(LIBODBC "odbc32.lib") + set(LIBMYSQL "mysqlclient.lib") +endif() + +if(ENABLE_ODBC) + message(STATUS "GLPK - Building with ODBC Support") + find_package(ODBC REQUIRED) + if (NOT ENABLE_DL) + message(SEND_ERROR "ENABLE_ODBC required ENABLE_DL") + endif() + include_directories(ODBC_INCLUDE_DIRECTORIES) + set(GLPK_HAVE_ODBC "define") + set(GLPK_ODBC_DLNAME "${ODBC_LIBRARIES}") +else() + set(GLPK_HAVE_ODBC "undef") + set(GLPK_ODBC_DLNAME "") +endif() + +if(ENABLE_MYSQL) + message(STATUS "GLPK - Building with MySQL Support") + find_package(MySQL REQUIRED) + if (NOT ENABLE_DL) + message(SEND_ERROR "ENABLE_MYSQL required ENABLE_DL") + endif() + include_directories(MYSQL_INCLUDE_DIR) + set(GLPK_HAVE_MYSQL "define") + set(GLPK_MYSQL_DLNAME "${MYSQL_LIBRARIES}") +else() + set(GLPK_HAVE_MYSQL "undef") + set(GLPK_MYSQL_DLNAME "") +endif() + +# Convert to CMake Variables to be used in the Config File +if(HAVE_SYS_TIME_H) + set(GLPK_HAVE_SYS_TIME_H "define") +else() + set (GLPK_HAVE_SYS_TIME_H "undef") +endif() +if(HAVE_GETTIMEOFDAY) + set(GLPK_HAVE_GETTIMEOFDAY "define") +else() + set (GLPK_HAVE_GETTIMEOFDAY "undef") +endif() +if(HAVE_LTDL) + set(GLPK_HAVE_LTDL "define") +else() + set (GLPK_HAVE_LTDL "undef") +endif() +if(HAVE_DLFCN) + set(GLPK_HAVE_DLFCN "define") +else() + set (GLPK_HAVE_DLFCN "undef") +endif() + + +# Configure a header file to pass some of the CMake settings to the source code +configure_file ( + "${PROJECT_SOURCE_DIR}/config.h.cmake.in" + "${PROJECT_BINARY_DIR}/include/config.h" +) +# Add the binary dir include directory for config.h +include_directories("${PROJECT_BINARY_DIR}/include") + +############################################################# +## +## Source file aggregation and clustering +## +############################################################# +file(GLOB_RECURSE GLPK_LIB_HEADERS ${PROJECT_SOURCE_DIR}/src/*.h) +file(GLOB_RECURSE GLPK_LIB_SOURCES ${PROJECT_SOURCE_DIR}/src/*.c) + +file(GLOB_RECURSE GLPK_LIB_DEF ${PROJECT_SOURCE_DIR}/w64/*.def) + +set(GLPK_EXAMPLE_GLPSOL_SOURCES ${PROJECT_SOURCE_DIR}/examples/glpsol.c) +set(GLPK_EXAMPLE_IPTSAMP_SOURCES ${PROJECT_SOURCE_DIR}/examples/iptsamp.c) +set(GLPK_EXAMPLE_MPLSAMP1_SOURCES ${PROJECT_SOURCE_DIR}/examples/mplsamp1.c) +set(GLPK_EXAMPLE_MPLSAMP2_SOURCES ${PROJECT_SOURCE_DIR}/examples/mplsamp2.c) +set(GLPK_EXAMPLE_SAMPLE_SOURCES ${PROJECT_SOURCE_DIR}/examples/sample.c) +set(GLPK_EXAMPLE_SPXSAMP1_SOURCES ${PROJECT_SOURCE_DIR}/examples/spxsamp1.c) +set(GLPK_EXAMPLE_SPXSAMP2_SOURCES ${PROJECT_SOURCE_DIR}/examples/spxsamp2.c) +set(GLPK_EXAMPLE_NETGEN_SOURCES ${PROJECT_SOURCE_DIR}/examples/netgen.c) + +# Additional include files like the storm-config.h +file(GLOB_RECURSE GLPK_BUILD_HEADERS ${PROJECT_BINARY_DIR}/include/*.h) + +# Add custom additional include or link directories +if (ADDITIONAL_INCLUDE_DIRS) + message(STATUS "GLPK - Using additional include directories ${ADDITIONAL_INCLUDE_DIRS}") + include_directories(${ADDITIONAL_INCLUDE_DIRS}) +endif(ADDITIONAL_INCLUDE_DIRS) +if (ADDITIONAL_LINK_DIRS) + message(STATUS "GLPK - Using additional link directories ${ADDITIONAL_LINK_DIRS}") + link_directories(${ADDITIONAL_LINK_DIRS}) +endif(ADDITIONAL_LINK_DIRS) + +############################################################################### +## # +## Executable Creation # +## # +## All link_directories() calls MUST be made before this point # +## # +############################################################################### +if(WITH_GLPK_EXAMPLES) + add_executable(glpsol ${GLPK_EXAMPLE_GLPSOL_SOURCES}) + add_executable(iptsamp ${GLPK_EXAMPLE_IPTSAMP_SOURCES}) + add_executable(mplsamp1 ${GLPK_EXAMPLE_MPLSAMP1_SOURCES}) + add_executable(mplsamp2 ${GLPK_EXAMPLE_MPLSAMP2_SOURCES}) + add_executable(spxsamp1 ${GLPK_EXAMPLE_SPXSAMP1_SOURCES}) + add_executable(spxsamp2 ${GLPK_EXAMPLE_SPXSAMP2_SOURCES}) + add_executable(netgen ${GLPK_EXAMPLE_NETGEN_SOURCES}) + add_executable(sample ${GLPK_EXAMPLE_SAMPLE_SOURCES}) +endif() + +if(ENABLE_DL) + set(GLPK_BUILD_TYPE SHARED) +else() + set(GLPK_BUILD_TYPE STATIC) +endif() +if (NOT MSVC) + set(GLPK_LIB_DEF "") +endif() + +add_library(glpk ${GLPK_BUILD_TYPE} ${GLPK_LIB_SOURCES} ${GLPK_LIB_HEADERS} ${GLPK_LIB_DEF}) +IF(UNIX) + target_link_libraries(glpk m) +ENDIF(UNIX) +if(HAVE_LTDL) + target_link_libraries(glpk ltdl) +endif(HAVE_LTDL) +if(HAVE_DLFCN) + target_link_libraries(glpk dl) +endif(HAVE_DLFCN) + +if(WITH_GLPK_EXAMPLES) + # Dependency for the Executable + add_dependencies(glpsol glpk) + add_dependencies(iptsamp glpk) + add_dependencies(mplsamp1 glpk) + add_dependencies(mplsamp2 glpk) + add_dependencies(spxsamp1 glpk) + add_dependencies(spxsamp2 glpk) + add_dependencies(netgen glpk) + add_dependencies(sample glpk) + target_link_libraries(glpsol glpk) + target_link_libraries(iptsamp glpk) + target_link_libraries(mplsamp1 glpk) + target_link_libraries(mplsamp2 glpk) + target_link_libraries(spxsamp1 glpk) + target_link_libraries(spxsamp2 glpk) + target_link_libraries(netgen glpk) + target_link_libraries(sample glpk) +endif() + +############################################################# +## +## ODBC +## +############################################################# +if(ODBC_FOUND) + target_link_libraries(glpk ${ODBC_LIBRARIES}) +endif() + +############################################################# +## +## MySQL +## +############################################################# +if(MYSQL_FOUND) + target_link_libraries(glpk ${MYSQL_LIBRARIES}) +endif() diff --git a/resources/3rdparty/glpk-4.53/COPYING b/resources/3rdparty/glpk-4.53/COPYING new file mode 100644 index 000000000..94a9ed024 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 3 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, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/resources/3rdparty/glpk-4.53/ChangeLog b/resources/3rdparty/glpk-4.53/ChangeLog new file mode 100644 index 000000000..1200edce6 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/ChangeLog @@ -0,0 +1,2747 @@ +Thu Feb 13 12:00:00 2014 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.53 (37:0:1) has been released. + + * src/glpmps.c (glp_read_mps) + The code was changed to remove free rows at the end. + + * src/glpcpx.c (glp_read_lp) + A bug was fixed (explicit bounds for binaries not set). Thanks + to Gabriel Hackebeil <gabehack@gmail.com> for bug report. + + * src/glpenv07.c (z_fgetc) + A bug was fixed (Z_STREAM_END -> Z_OK). Thanks to Achim Gaedke + <achim.gaedke@gmail.com> for bug report. + + * src/glpenv07.c + Replaced by src/env/stream.c. + + * src/glpenv08.c + Replaced by src/env/dlsup.c. + + * src/bflib/ifu.h, src/bflib/ifu.c + Re-implemented. + + * src/glpscf.h, src/glpscf.c + Replaced by IFU. + + * src/glplpf.h, src/glplpf.c + Changed due to IFU. + + * src/glpbfd.c + Changed due to LPF. + + * src/glpapi06.c + Two API routines glp_get_it_cnt and glp_set_it_cnt were added. + Thanks to Joey Rios <joeylrios@hotmail.com> for suggestion. + + * src/glplpx.h, src/glplpx01.c, src/glplpx02.c, src/glplpx03.c + All obsolete API routines were completely removed. + + * examples/oldapi/lpx.h, examples/oldapi/lpx.c + A set of routines that simulate the old GLPK API (as defined + in 4.48) were added. Thanks to Jan Engelhardt <jengelh@inai.de> + for suggestion. + + * src/zlib/* + zlib 1.2.7 was downgraded to zlib 1.2.5 (from glpk 4.50) due to + bugs detected in zlib 1.2.7 on some 64-bit platforms. Thanks to + Carlo Baldassi <carlobaldassi@gmail.com> for bug report. + + * src/glpsql.c + Alignment bug was fixed. Thanks to Xypron <xypron.glpk@gmx.de> + for suggestion. + + * src/glpsql.c + #include <my_global.h> and #include <my_sys.h> were commented + out to fix a namespace bug on compiling with MariaDB. Thanks to + Xypron <xypron.glpk@gmx.de> for suggestion. + +Sun Jul 28 12:00:00 2013 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.52.1 (36:1:0) has been released. + + * src/Makefile.am + Version information bug was fixed. Thanks to Sebastien Villemot + <sebastien@debian.org> for bug report. + + * src/proxy/proxy.c + A minor bug (incorrect use of glp_term_out) was fixed. + + * src/glpios03.c + The simple rounding heuristic routine was changed to check only + global constraints. + + * src/glpcpx.c + The code was changed to issue the warning message 'lower/upper + bound redefined' only once. + +Thu Jul 18 12:00:00 2013 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.52 (36:0:1) has been released. + + * src/misc/wclique1.h, src/misc/wclique1.c + Greedy heuristic to find maximum weight clique was implemented. + + * src/cglib/cfg.h, src/cglib/cfg.c, src/cglib/cfg1.c + Conflict graph routines (used to generate clique cuts) were + implemented. + + * src/glpios08.c + New version of the clique cut generator was implemented. Now it + is able to efficiently process very large and/or dense conflict + graphs. Old rudimentary version was removed from the package. + + * examples/misp1.dat, examples/misp2.dat + Two data files for the maximum independent set problem (MISP) + were added to illustrate efficiency of using the clique cuts. + + * src/glpios03.c + Simple rounding heuristic applied for every node subproblem was + implemented. + + * proxy/proxy.c + Some bugs were fixed in the proximity search heuristic routine. + Thanks to Giorgio Sartor <0gioker0@gmail.com>. + + * src/glpapi21.c + New command-line option '--proxy [nnn]' was added to glpsol to + enable using the proximity search heuristic. + + * src/glpspx02.c + A feature was added to switch to the primal simplex in case of + stalling due to dual degeneracy (for GLP_DUALP only). + + * src/glpmps.c + A bug (incorrect processing of LI column indicator) was fixed + in the mps format reading routine. Thanks to Charles Brixko for + bug report. + +Wed Jun 19 12:00:00 2013 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.51 (36:0:0) has been released. + + * src/bflib/sgf.c, src/bflib/sgf.h + Singleton and dense phases of sparse Gaussian factorizer were + implemented. + + * src/bflib/lufint.c, src/bflib/lufint.h + Interface routines to LU-factorization were added. + + * src/bflib/fhvint.c, src/bflib/fhvint.h + Interface routines to FHV-factorization were changed to use + lufint.c routines. + + * src/glplpf.c, src/glplpf.h + Routines implementing Schur-complement version of the LP basis + factorization were changed to use lufint.c routines. + + * src/glpbfd.c, src/glpbfd.h + Interface routines to the LP basis factorization were changed + due to changes in glplpf.c routines. + + * src/glpluf.c, src/glpluf.c + Old version of LU-factorization was removed from the package. + (This old version was used for 10 years since 3.0.6.) + + * src/misc/triang.c, src/misc/triang.h + Routine to find maximal triangular part of rectangular matrix + was added. + + * src/glpini01.c + The API routine glp_adv_basis that constructs advanced initial + LP basis was replaced by an improved version, which (unlike the + old version) takes into account numerical values of constraint + coefficients. + + * src/proxy/* + Routines that implement the proximity search heuristic for MIP + were added. Thanks to Giorgio Sartor <0gioker0@gmail.com> for + contribution. + + * src/glpk.h + iocp.ps_heur was added to enable/disable proxy heuristic. + + * glpsol + --proxy command-line option was added. + + * src/zlib/*.* + zlib general purpose compression library, version 1.2.7, + was ANSIfied and modified according to GLPK requirements and + included in the distribution as an external software module. + This version replaced the old one (1.2.5). For details please + see src/zlib/README. + + * src/glpk.h, src/env/time.c + The API routine glp_time was changed to return double rather + than glp_long. + + * src/glplib02.c + Routines that implement glp_long type (64-bit arithmetic) were + removed from the package. + + * src/glpk.h, src/env/alloc.c + New API routine glp_alloc was added. It makes obsolete two + API routines glp_malloc and glp_calloc which were replaced by + macros to use glp_alloc (hence 36:0:0). + + * src/glpios10.c + A bug was fixed that caused numerical instability in the FPUMP + heuristic (the bug was introduced in glpk 4.40). + +Fri May 24 12:00:00 2013 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.50 (35:0:0) has been released + + * src/Makefile.am + Though API was not changed since 4.49, symbols _glp_lpx_* were + removed from the export list, hence 35:0:0. + + * src/glpfhv.h, src/glpfhv.c + Old routines for FHV-factorization were removed. + + * src/bflib/*.h, src/bflib/*.c + New version of basis factorization routines, including routines + for FHV-factorization, were added. + + * src/glpbfd.c + LP basis factorization driver was changed according to the new + routines for FHV-factorization. + + * doc/glpk.tex + Some clarifications about using the name index routines were + added. Thanks to Xypron <xypron.glpk@gmx.de> for suggestion. + + * doc/gmpl.tex + Some typos were corrected. + Thanks to Jeffrey Kantor <Kantor.1@nd.edu> for report. + + * src/glprlx.c + A serious bug was *tentatively* fixed. This bug is inherited + from the original Fortran version of the RELAX-IV code. + Unfortunately, the code is very intricate, so this bug is still + under investigation. Thanks to Sylvain Fournier for bug report. + + RELAX-IV bug details + -------------------- + In the original RELAX-IV code there are four similar fragments + in subroutines ascnt1 and ascnt2 like this: + + C + C DECREASE THE PRICES OF THE SCANNED NODES BY DELPRC. + C ADJUST FLOW TO MAINTAIN COMPLEMENTARY SLACKNESS WITH + C THE PRICES. + C + NB = 0 + DO 6 I=1,NSAVE + . . . + IF (RC(ARC).EQ.0) THEN + DELX=DELX+U(ARC) + NB = NB + 1 + PRDCSR(NB) = ARC + END IF + . . . + + On some instances the variable NB becomes greater than N (the + number of nodes) that leads to indexing error, because the + array PRDCSR is declared as array of N elements (more + precisely, as array of MAXNN elements, however, NB becomes even + much greater than MAXNN). + +Tue Apr 16 12:00:00 2013 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.49 (34:0:0) has been released + + * glprlx.c, glprlx.h + C version of the Fortran code RELAX-IV (relaxation method of + Bertsekas and Tseng) was added. + + * glpapi17.c + API routine glp_mincost_relax4, which is a driver to RELAX-IV + code, was added and documented. + + * glpnet03.c + API routine glp_netgen_prob (Klingman's standard network + problems) was added and documented. + + * glpapi12.c + A bug (wrong dual feasibility test) was fixed in API routine + glp_warm_up. Thanks to David T. Price <dtprice@speakeasy.net> + for bug report. + + * glpapi10.c + Obsolete API routine lpx_check_kkt was replaced by API routine + glp_check_kkt. + + * glpk.h + All old API routines whose names begin with 'lpx_' were removed + from API and no more available. + + * glpk.tex, graphs.tex + These documents were essentially reformatted. + +Mon Jan 28 12:00:00 2013 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.48 (33:0:0) has been released + + * src/glpmps.c + A bug in glp_write_mps was fixed. Thanks to Raniere Gaia Costa + da Silva for bug report. + + * glpk.h + glp_prob declaration changed (now it is incomplete struct); + glp_tree declaration changed (now it is incomplete struct); + glp_tran declaration changed (now it is incomplete struct); + glp_long declaration removed; + glp_time declaration removed; + glp_difftime removed from API; + glp_data removed from API; + glp_sdf_* removed from API; + glp_mem_usage declaration changed (glp_long -> size_t); + glp_realloc declaration added (not documented yet). + + * glpenv.h, glpenv05.c + Dynamic memory allocation routines were reimplemented. + + * glpk.h, glpnet03.c + Routine glp_netgen_prob was added (not documented yet). + + * configure.ac + Check for gmp.h was added. Thanks to Heinrich Schuchardt for + suggestion. + + * w32/glpk.def, w64/glpk.def + Changes were made to export only API symbols. + +Fri Sep 09 12:00:00 2011 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.47 (32:0:32) has been released + + * src/glpapi20.c + New API routine glp_infeas1 to solve 0-1 feasibility problem + was added and documented (see doc/cnfsat.pdf). + + * src/glpnpp06.c + Some new preprocessor routines for SAT-CNF encoding, which are + used by the routine glp_intfeas1, were added. + + * src/glpnpp.h + The header was modified due to additions. + + * src/glpapi21.c + The glpsol solver was modified to bypass model postprocessing + if the solution reported is neither optimal nor feasible. + + * src/glpapi21.c + New glpsol options (--minisat and --objbnd) were added. + + * examples/pbn/*.* + The paint-by-numbers puzzle model (pbn.mod) was modified to + print solution in PostScript format and to check for multiple + solutions. Some benchmark examples from <webpbn.com> encoded + in MathProg were included in the distribution. For more details + see examples/pbn/README and examples/pbn/pbn.pdf. + + * examples/Makefile.am + A minor bug was fixed to correctly build glpk in a separate + directory. Thanks to Marco Atzeri <marco.atzeri@gmail.com> for + bug report. + +Tue Aug 09 12:00:00 2011 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.46 (31:0:31) has been released + + * src/glpk.h, src/Makefile + glpk.h was relocated from 'include' to 'src', and 'include' + subdir was removed; src/Makefile.am was changed appropriately. + + * src/zlib/*.* + zlib general purpose compression library, version 1.2.5, + was ANSIfied and modified according to GLPK requirements and + included in the distribution as an external software module. + + For details see src/zlib/README. + + * src/glpdmx.c + The following new API routines were added: + glp_read_cnfsat - read CNF-SAT problem data in DIMACS format + glp_check_cnfsat - check for CNF-SAT problem instance + glp_write_cnfsat - write CNF-SAT problem data in DIMACS format + + * src/minisat/*.* + MiniSat, a CNF-SAT solver, version 1.14.1, was ANSIfied and + modified according to GLPK requirements and included in the + distribution as an external software module. + + For details see minisat/README and minisat/LICENSE. + + * src/glpapi19.c + The API routine glp_minisat1, which is a driver to the MiniSat + solver, was included in the package. + + * doc/satcnf.* + The document "CNF Satisfiability Problem" was included in the + package. It is a supplement to the GLPK Reference Manual. + + * src/glpapi20.c + New glpsol options (--cnf, --wcnf, and --minisat) was added. + + * glpsql.c + Some bugs were fixed. Thanks to Xypron <xypron.glpk@gmx.de>. + +Sun Dec 05 12:00:00 2010 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.45 (30:0:30) has been released + + * glplpx01.c + A bug (it_cnt) in routine reset_parms was fixed. + Thanks to Ali Baharev <ali.baharev@gmail.com> for report. + + * glpmpl03.c + A bug (print "text\") was fixed. + Thanks to Xypron <xypron.glpk@gmx.de> for report. + + * glpsql.c + A precision bug was fixed. + Thanks to Xypron <xypron.glpk@gmx.de>. + + * glpk.tex + Some typos were corrected. + Thanks to Robbie Morrison <robbie@actrix.co.nz>. + +Thu Jun 03 12:00:00 2010 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.44 (29:0:29) has been released + + * glpapi14.c glpmpl.h glpmpl01.c glpmpl03.c glpmpl04.c + Implemented suffixes for variables and constraints. + + * glpmpl06.c + Made changes to allow comment records in CSV files. + + * glpapi17.c + Added and documented new API routine glp_cpp to solve Critical + Path Problem. + +Sat Feb 20 12:00:00 2010 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.43 (28:0:28) has been released + + * glplib.h, glplib.c, glpenv.h, glpenv.c + The module glpenv was split into two modules glpenv and glplib. + + * glpenv01.c, glpenv03.c, glpenv04.c, glpenv06.c + The following new API routines were added and documented: + glp_init_env, glp_free_env, glp_open_tee, glp_close_tee, + glp_error (macro), glp_difftime. + + * glpapi16.c + New API routine glp_top_sort (topological sorting of ayclic + digraph) was added and documented. + + * glpapi17.c + A serious bug was fixed in the routine glp_asn_prob_hall. + + * glpnpp05.c + A bug was fixed in the LP/MIP preprocessor (hidden covering + inequalities). + + * glpsql.c + Some improvements were made in the table driver (NULL data). + Thanks to Xypron <xypron.glpk@gmx.de> for contribution. + + * configure.ac + Changes were made to use .dylib rather than .so under Mac OS. + Thanks to Noli Sicad <nsicad@gmail.com> for testing + +Wed Jan 13 12:00:00 2010 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.42 (27:0:27) has been released + + * glpapi01.c, glpapi11.c, glpapi12.c, glpdmx.c + The following new API routines were added and documented: + glp_check_dup (check for duplicate elements in sparse matrix); + glp_sort_matrix (sort elements of the constraint matrix); + glp_read_prob (read problem data in GLPK format); + glp_write_prob (write problem data in GLPK format); + glp_analyze_bound (analyze active bound of non-basic variable); + glp_analyze_coef (analyze obj. coefficient at basic variable); + glp_print_ranges (print sensitivity analysis report; replaces + lpx_print_sens_bnds). + + * glpapi20.c + New command-line options were added to glpsol: + --glp (read problem data in GLPK format); + --wglp (write problem data in GLPK format); + --lp (replaces --cpxlp); + --wlp (replaces --wcpxlp); + --ranges (print sensitivity analysis report). + + * glpapi06.c + In the routine glp_init_smcp default value of the parameter + out_frq was changed to 500 (it was 200). + + * glpipp.h, glpipp01.c, glpipp02.c + The old MIP preprocessor module was removed. + + * glpapi09.c + Now the MIP solver uses the new MIP preprocessor (NPP). + + * glplpx03.c + lpx_write_opb was disabled due to replacing IPP with NPP. + + * glpnet09.c + Kellerman's heuristic to cover edges by cliques was added. + + * glplib08.c + Recognition of special filenames "/dev/stdin", "/dev/stdout", + and "/dev/stderr" was added. + + * glpk.tex + Chapter "Graph and network routines" was carried out from the + reference manual as a separate document. + +Mon Dec 21 12:00:00 2009 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.41 (26:0:26) has been released + + * glpapi12.c + The following new API routines were added: + glp_transform_row (replaces lpx_transform_row); + glp_transform_col (replaces lpx_transform_col); + glp_prim_rtest (replaces lpx_prim_ratio_test); + glp_dual_rtest (replaces lpx_dual_ratio_test). + Note that values returned by glp_prim_rtest and glp_dual_rtest + differ from the ones retutned by the deprecated routines. + + * glpnpp*.* + The LP/MIP preprocessor was essentially re-implemented. + + * glpios03.c + The feature to remove inactive cuts from the active subproblem + was implemented. + + * glpios11.c + The feature processing cuts stored in the cut pool was improved + (now it uses estimation of objective degradation). + + * glpscg.* + Obsolete implemetation of the conflict graph was removed. + + * glpmpl.h, glpmpl03.c, glpmpl04.c + FILE was replaced by XFILE to allow using GLPK I/O routines. + + * glpsql.c, examples/sql, doc/tables.tex + The SQL table driver was changed to allow multiple arguments + separated by semicolon in SQL statements. Thanks to Xypron + <xypron.glpk@gmx.de>. + + * glpk.h, glpapi14.c + New API routine glp_time was added (not documented yet). + + * glpapi20.c + Two new options were added to glpsol: --seed value (initialize + pseudo-random number generator used in MathProg model with + specified seed value), and --ini filename (use as initial basis + previously saved with -w option). + + * examples/xyacfs.mod + Thanks to Nigel Galloway <nigel_galloway@operamail.com> for + contribution. + + * examples/dbf/*.* + Thanks to Noli Sicad <nsicad@gmail.com> for contribution. + + * w32/*.*, w64/*.* + Scripts to build GLPK with Microsoft Visual Studio 2010 were + added. Thanks to Xypron <xypron.glpk@gmx.de> for contribution + and testing. + +Tue Nov 03 12:00:00 2009 Andrew Makhorin <mao@gnu.org> + + * GLPK 4.40 (25:0:25) has been released + + * glpdmx.c + Two new API routines were added: + glp_read_ccdata (read graph in DIMACS clique/coloring format); + glp_write_ccdata (write graph in DIMACS clique/coloring format). + Also an example file examples/sample.col was added. + + * glpapi19.c, glpnet08.c + New API routine glp_wclique_exact was added. It is intended to + find a maximum weight clique with the exact algorithm developed + by Prof. P. Ostergard. + + * glpnpp02.c + A bug was fixed in the LP preprocessor (routine npp_empty_col). + Thanks to Stefan Vigerske <stefan@math.hu-berlin.de> for the + bug report. + + * glpios10.c + A bug was fixed and some improvements were made in the FPUMP + heuristic module. Thanks to Xypron <xypron.glpk@gmx.de>. + + * glpapi12.c + A bug was fixed in the API routine glp_warm_up (dual + feasibility test was incorrect in maximization case). Thanks to + Uday Venkatadri <Uday.Venkatadri@dal.ca> for the bug report. + + * glpapi16.c + Two new API routines were added: + glp_del_vertices (remove vertices from graph); + glp_del_arc (remove arc from graph). + + * glpios09.c + The hybrid pseudocost branching heuristic was included in the + MIP solver. It is available on API level (iocp.br_tech should + be set to GLP_BR_PCH) and in the stand-alone solver glpsol + (via the command-line option --pcost). This heuristic may be + useful on solving hard MIP instances. + + * glpios03.c + The branching heuristic by Driebeck and Tomlin (used in the + MIP solver by default) was changed to switch to branching on + most fractional variable if an lower bound of degradation of + the objective is close to zero for all branching candidates. + +Sun Jul 26 12:00:00 2009 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.39 (24:0:24) has been released + + * glpsdf.c + New API routines to read plain data files were added. + + * glpcpx.h, glpini.h, glpscl.h + These headers were removed. + + * glpcpx.c + API routines glp_read_lp and glp_write_lp to read/write files + in CPLEX LP format were re-implemented. Now glp_write_lp + correctly writes double-bounded (ranged) rows by introducing + slack variables rather than by duplicating the rows. The data + structure glp_cpxcp and routine glp_init_cpxcp were added. + + * amd/* + The 'xfree(NULL)' bug was fixed in the AMD routines. Thanks to + Niels Klitgord <niels@bu.edu> for the bug report. + + * glpapi16.c + New API routines glp_set_vertex_name, glp_create_v_index, + glp_find_vertex, and glp_delete_v_index were added. + + * glpdmx.c + New API routines glp_read_asnprob, glp_write_asnprob, + glp_read_ccformat, and glp_write_ccformat were added (the two + latter routines are not documented yet). + + * glpapi18.c + New API routines glp_check_asnprob, glp_asnprob_lp, + glp_asnprob_okalg, and glp_asnprob_hall were added. + + * glpini01.c, glpini02.c + The message "Crashing..." was changed to "Constructing initial + basis..." due to suggestion by Thomas Kahle <tom111@gmx.de>. + + * glpapi14.c + New API routines glp_printf, glp_vprintf, glp_malloc, + glp_calloc, glp_free, and glp_assert were added. + + * glplpp.h, glplpp01.c, glplpp02.c + Old LP presolver routines were removed. Now glp_simplex uses + new preprocessing routines (see glpnpp). + + * glpapi12.c + New API routine glp_warm_up was added; it replaces the routine + lpx_warm_up. + +Sat May 02 12:00:00 2009 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.38 (23:0:23) has been released + + * glpmps.c + API routines to read/write MPS files were re-implemented. + + * glpspx02.c + Some improvements were made in the dual simplex routine. + + * glpk.h + New structure glp_iptcp was added. + + * glpnpp.h, glpnpp01.c, glpnpp02.c + New LP/MIP preprocessor. Currently it includes only some basic + routines and used only in the interior-point solver. + + * glpapi08.c + API routine glp_interior was replaced by an improved version + (new LP/MIP preprocessor, new ordering algorithms). + + New API routine glp_init_iptcp was added. + + API routine glp_ipt_status may return two new statuses due to + changes in glp_interior. + + * glpsol.c + New command-line options were added (ordering algorithm used in + the interior-point solver). + + * amd/*.*, colamd/*.* + Two external software modules AMD and COLAMD/SYMAMD used in the + interior-point solver were included in the distribution. + + For details see amd/README and colamd/README. + + * glpnet03.c, glpnet04.c, glpnet05.c + A minor bug was fixed (_G => G_). Thanks to Nelson H. F. Beebe + <beebe@math.utah.edu> for bug report. + +Sun Mar 29 12:00:00 2009 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.37 (22:0:22) has been released + + * glpk.h + iocp.fp_heur was added to enable/disable fpump heuristic. + + * glpios10.c + ios_feas_pump was added (feasibility pump heuristic). + + * glpsol.c + --fpump command-line option was added. + + * glpsds.c + Plain data set routines were added to facilitate reading plain + data in application programs. Currently these routines are not + in API, though declared in glpk.h. + + * glpapi08.c + A bug was fixed in the internal routine restore. (Due to this + bug dual solution components were computed incorrectly if the + problem was scaled.) + + * glpapi10.c, glpapi11.c + The following new API routines were added: + glp_print_sol (replaces lpx_print_sol); + glp_print_ipt (replaces lpx_print_ips); + glp_print_mip (replaces lpx_print_mip); + _glp_check_kkt (replaces lpx_check_kkt, lpx_check_int). + Now the routine lpx_print_prob (deprecated) is equivalent to + the routine glp_write_lp. + + * glpapi18.c, glpapi19.c + The following new API routines were added: + glp_read_graph (read graph from plain text file); + glp_write_graph (write graph to plain text file); + glp_weak_comp (find all weakly connected components); + glp_strong_comp (find all strongly connected components). + + * configure.ac, Makefile.am + Changes were made: (a) to allow using autoreconf/autoheader; + (b) to allow building glpk in a directory other than its source + directory. Thanks to Marco Atzeri <marco_atzeri@yahoo.it> for + bug report. + + * examples/shiftcover.mod + An example model in MathProg was added. + Thanks to Larry D'Agostino <Larry.D'Agostino@gmacrescap.com> + for contribution. + +Fri Feb 06 12:00:00 2009 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.36 (21:0:21) has been released + + * glpnet06.c, glpnet07.c, glpapi19.c + The following new API routines were added: + glp_mincost_okalg find minimum-cost flow with out-of-kilter + algorithm + glp_maxflow_ffalg find maximal flow with Ford-Fulkerson + algorithm + + * glpsol.c + Two new command-line options were added: + --mincost read min-cost flow data in DIMACS format + --maxflow read maximum flow data in DIMACS format + + * doc/glpk.* + New edition of the reference manual was included. + + * glpk.h + Duplicate symbols were removed to allow using swig. + Thanks to Kelly Westbrooks <kellywestbrooks@yahoo.com> and + Nigel Galloway <nigel_galloway@operamail.com> for suggestion. + + * glpcpx.c + A minor defect was fixed in the routine glp_write_lp. + Thanks to Sebastien Briais <sbriais@free.fr> for bug report. + + * glpsql.c + A minor bug was fixed. Thanks to Xypron <xypron.glpk@gmx.de> + for patch. + + * examples/hashi.mod, examples/shikaku.mod + Two example models in MathProg were added. Thanks to Sebastian + Nowozin <nowozin@gmail.com> for contribution. + + * examples/qfit.mod, examples/yacfs.mod + Two example models in MathProg were added. Thanks to Nigel + Galloway <nigel_galloway@operamail.com> for contribution. + +Fri Jan 09 12:00:00 2009 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.35 (20:0:20) has been released + + * glpk.h, glpapi.c, glpnet.c + The following new API routines were added: + glp_create_graph create graph + glp_set_graph_name assign (change) graph name + glp_add_vertices add new vertices to graph + glp_add_arc add new arc to graph + glp_erase_graph erase graph content + glp_delete_graph delete graph + glp_read_mincost read minimum cost flow problem data in + DIMACS format + glp_write_mincost write minimum cost flow problem data in + DIMACS format + glp_mincost_lp convert minimum cost flow problem to LP + glp_netgen Klingman's network problem generator + glp_gridgen grid-like network problem generator + glp_read_maxflow read maximum flow problem data in DIMACS + format + glp_write_maxflow write maximum flow problem data in DIMACS + format + glp_maxflow_lp convert maximum flow problem to LP + glp_rmfgen Goldfarb's maximum flow problem generator + + * doc/glpk.* + New edition of the reference manual was included. + + * examples/sample.min, examples/sample.max + Two example data files in DIMACS format were added. + + * glplib04.c + The statement "if (c = '\n') fflush(stdout)" was added to the + internal routine xputc to provide "real-time" terminal output. + Thanks to Luiz Bettoni <bettoni@cpgei.ct.utfpr.edu.br> for + suggestion. + + * glpmpl05.c + A minor bug was fixed in the internal routine mpl_fn_time2str. + Thanks to Stefan Vigerske <stefan@vigerske.de> for bug report. + + * w32/makefile, w64/makefile + The flag -O2 (/O2) was added to some makefiles. + +Thu Dec 04 12:00:00 2008 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.34 (19:0:19) has been released + + * src/glpios03.c + A bug was fixed in the internal routine branch_on. Thanks to + Nigel Galloway <nigel_galloway@operamail.com> for bug report. + + * src/glpmpl05.c + Three new MathProg functions were included: + gmtime obtaining current calendar time + str2time converting character string to calendar time + time2str converting calendar time to character string + Thanks to Xypron <xypron.glpk@gmx.de>. + + * doc/glpk.*, doc/gmpl.* + A new edition of the GLPK reference manual and GNU MathProg + language description were included. + +Thu Oct 30 12:00:00 2008 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.33 (18:0:18) has been released + + * glpapi*.* + The following new API routines were added: + glp_copy_prob copy problem object content + glp_exact solve LP in exact arithmetic + (makes lpx_exact deprecated) + glp_get_unbnd_ray determine variable causing unboundedness + (makes lpx_get_ray_info deprecated) + glp_interior solve LP with interior-point method + (makes lpx_interior deprecated) + + * glpapi*.* + The following new API routines for processing models written in + the GNU Mathprog language were added to the package: + glp_mpl_alloc_wksp allocate the translator workspace + glp_mpl_read_model read and translate model section + glp_mpl_read_data read and translate data section + glp_mpl_generate generate the model + glp_mpl_build_prob build LP/MIP instance from the model + glp_mpl_postsolve postsolve the model + glp_mpl_free_wksp deallocate the translator workspace + (These routines make lpx_read_model deprecated.) + + * src/glpapi17.c, examples/glpsol.c + The stand-alone solver glpsol was re-implemented with new API + routines. + + * src/glpsql.c + Some bugs were fixed in the SQL table driver. Thanks to Xypron + <xypron.glpk@gmx.de>. + + * examples/cplex/*.* + A crude implementation of CPLEX-like interface to GLPK API was + added to the package. See examples/cplex/README. + +Fri Oct 03 12:00:00 2008 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.32 (17:0:17) has been released + + * glpmpl01.c + A bug was fixed. Due to this bug iterated expressions having + an indexing expression whose dummy indices are bound to some + values, i.e. like sum{(i+1,j,k-1) in E} x[i,j,k] are evaluated + incorrectly. Namely, current value of such expressions is not + invalidated when corresponding dummy indices (like i and k in + the example above) are changed, that erroneously results in the + same value evaluated for the first time. + + * glpios03.c + Euclidean reduction of the local objective bound was added in + the routine glpios03.c. + + * glpapi11.c + The following new branch-and-cut API routines were added: + glp_ios_row_attr determine additional row attributes; + glp_ios_pool_size determine current size of the cut pool; + glp_ios_add_row add constraint to the cut pool; + glp_ios_del_row delete constraint from the cut pool; + glp_ios_clear_pool delete all constraints from the cut pool. + + * glpapi08.c + The following new features were included in the branch-and-cut + solver (the API routine glp_intopt): + MIP presolver; + mixed cover cut generator; + clique cut generator. + Due to the MIP presolver glp_intopt may additionally return + GLP_ENOPFS and GLP_ENODFS, if primal or dual infeasibility of + LP relaxation is detected by the presolver. Also the return + code GLP_EMIPGAP was introduced to correctly indicate that the + mip gap tolerance is reached. + + * glplpx01.c + Now the obsolete API routines lpx_integer and lpx_intopt are + completely superseded by the API routine glp_intopt that makes + them deprecated. + + * glpmpl05.c + Now the table driver name "iODBC" can be specified as "ODBC". + + * glpmpl03.c + A bug fixed in the routine free_dca. + Thanks to Xypron <xypron.glpk@gmx.de>. + + * glpsql.c + A bug was fixed in the SQL table driver. + Thanks to Xypron <xypron.glpk@gmx.de>. + + * examples/glpsol.c + Changes were made to allow multiple MathProg data files. + + * doc/glpk.* + A new edition of the GLPK reference manual was included. + + * doc/tables.* + A new edition of the supplement "Using data tables in the GNU + MathProg language" was included. + +Tue Sep 02 12:00:00 2008 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.31 (16:0:16) has been released + + * glpspx.h, glpspx01.c, glpspx02.c, glpapi06.c + The dual simplex solver (spx_dual_opt) was replaced by a new + implementation of the two-phase dual simplex method (spx_dual). + Old simplex method routines (spx_prim_opt, spx_prim_feas, and + spx_dual_opt) were removed from the package. + + * glpk.h, glpscl.h, glpscl.c, glpapi04.c + New API routine glp_scale_prob was added. It replaces routine + lpx_scale_prob which is deprecated. + + * glpk.h, glpini.h, glpini01.c, glpini02.c, glpapi05.c + New API routines glp_std_basis, glp_adv_basis, glp_cpx_basis + were added. They replace routines lpx_std_basis, lpx_adv_basis, + lpx_cpx_basis which are deprecated. + + * glpdmp.c + 8-byte data alignment was added to the module (sufficient for + both ILP32 and LP64 environments). + + * glplib07.c + 16-byte data alignment was added to the module to provide + compatibility with LP64 environment (8-byte is not sufficient + due to jmp_buf; thanks to Xypron for investigation). + + * glplpx16.c + New version of the routine lpx_write_pb was added. Thanks to + Oscar Gustafsson <oscarg@isy.liu.se> for the contribution. + + * w32/VC9, w64/VC9 + Makefiles and batch files were added to build GLPK under 32- + and 64-bit Windows with Microsoft Visual Studio Express 2008. + Thanks to Heinrich Schuchardt <heinrich.schuchardt@gmx.de> for + the contribution and testing. + + * w32/DM, w32/OWC + Makefiles and batch files were added to build GLPK with Digital + Mars C/C++ 8.50 and Open Watcom C/C++ 1.6 (32-bit Windows). + +Wed Aug 13 12:00:00 2008 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.30 (15:0:15) has been released + + * glpspx.h, glpspx03.c, glpapi06.c + The primal simplex solver (spx_prim_opt, spx_prim_feas) was + replaced by a new implementation (spx_primal), which currently + provides the same features as the old version. + + * glpmpl01.c, glpmpl03.c + Some changes were made in the MathProg translator to allow <, + <=, >=, and > on comparing symbolic values. Thanks to Heinrich + Schuchardt <heinrich.schuchardt@gmx.de> for patches. + + * glplpx10.c + Internal routine set_d_eps in the exact LP solver was changed + to prevent approximation errors in case of integral data. + Thanks to Markus Pilz <pilz@cs.uni-bonn.de> for bug report. + +XXX XXX XX 12:00:00 2008 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.29 (14:0:14) has been released + + * configure.ac + The configure script was changed to disable optional features + by default. For details see file INSTALL. + + * glpipp02.c + A bug was fixed in the internal routine reduce_bounds. Thanks + to Anne-Laurence Putz <anne-laurence.putz@eurodecision.com> for + the bug report. + + * glpapi01.c + New API routine glp_erase_prob was added. + + * glpapi13.c + New API routines glp_read_mps and glp_write_mps were added. + They replace API routines lpx_read_mps, lpx_read_freemps, + lpx_write_mps, and lpx_write_freemps, which are deprecated. + + * glpapi14.c + New API routines glp_read_lp and glp_write_lp were added. They + replace API routines lpx_read_cpxlp and lpx_write_cpxlp, which + are deprecated. + + * glpsql.c + Minor bug was fixed. Thanks to Xypron <xypron.glpk@gmx.de> for + the bug report. + +Tue Mar 25 12:00:00 2008 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.28 (13:0:13) has been released + + * glplib.h, glplib.c + Three wrapper routines xdlopen, xdlsym, and xdlclose, which + provide the shared library support, were added. A particular + version of these routines depends on the option --enable-dl + passed to the configure script (see file INSTALL for details). + Thanks to Rafael Laboissiere <rafael@debian.org> for useful + advices concerning the shared library support. + + * glpsql.c + A static linking to iODBC and MySQL libraries used in the + MathProg table drivers was replaced by a dynamic linking to + corresponding shared libraries. + Many thanks to Heinrich Schuchardt <heinrich.schuchardt@gmx.de> + for the contribution and to Vijay Patil <vijay.patil@gmail.com> + for testing this feature under Windows XP. + + * glpgmp.h, glpgmp.c + A bug (which appeared only on 64-bit platforms) was fixed. + Thanks to Axel Simon <Axel.Simon@ens.fr> for the bug report. + + * glpapi.c + A bug was fixed in the api routine glp_add_cols. (If the basis + is valid, adding column keeps it valid, however, col->bind was + set to -1 rather to 0.) + Thanks to Cedric[FR] <fox2113@wanadoo.fr> for the bug report. + + * glplib.c + 64-bit unsigned int type glp_ulong and corresponding routines + were replaced by 64-bit signed int type xlong_t. + + * glpk.h, glpapi.c + The type glp_ulong was replaced by glp_long. This affects only + the api routine glp_mem_usage. + + * glplib.c + Compressed data file support was added. This feature requires + the zlib data compression libraries and allows compressing and + decompressing .gz files "on the fly". + + * glpcli.h, glpcli.c + Command-line interface routines were added. (This feature is + incomplete so far.) + +Sun Mar 02 12:00:00 2008 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.27 (12:0:12) has been released + + * glpsql.h, glpsql.c + Two MathProg table drivers for iODBC and MySQL contributed by + Heinrich Schuchardt <heinrich.schuchardt@gmx.de> were added to + the package. + + * glpmpl05.c + Mathprog table driver for xBASE was added to the package. + + * glpmpl03.c + A minor was fixed in the MathProg translator (if some field + specified in the table statement is missing in corresponding + input table, the bug causes abnormal termination). Thanks to + Heinrich Schuchardt <heinrich.schuchardt@gmx.de> for the bug + report. + + * glpmpl.h, glpmpl.c + STRING data type was replaced by plain character strings. + +Sun Feb 17 12:00:00 2008 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.26 (11:0:11) has been released + + * glpmpl.h, glpmpl01.c, glpmpl03.c, glpmpl05.c + The table statement was implemented. Description of this new + feature is given in file doc/tables.txt. + + * glpios03.c + A bug causing zero divide error on computing euclidean norm of + the cut coefficient vector was fixed. + +Wed Dec 19 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.25 (10:0:10) has been released + + * glpapi10.c + Routines lpx_eval_tab_row and lpx_eval_tab_col were replaced by + glp_eval_tab_row and glp_eval_tab_col. + + * glpios03.c, glpios05.c + Gomory's mixed integer cuts were implemented. + + * glpscs.h, glpscs.c + Segmented character string routines are no longer used and were + removed from the package. + +Wed Nov 21 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.24 (9:0:9) has been released + + * src/glplpx16.c + A bug was fixed in the routine lpx_write_cpxlp. If a variable + x has upper bound and no lower bound, it should appear in the + bounds section as "-inf <= x <= u", not as "x <= u". Thanks to + Enric Rodriguez <erodri@lsi.upc.edu> for the bug report. + + * src/glpios03.c, src/glpios04.c, src/glpios05.c + MIR (mixed integer rounding) cuts were implemented. + +Sun Oct 28 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.23 (8:0:8) has been released + + * src/glplib05.c, configure.ac + Check for vsnprintf was added. + + * include/glppds.h, src/glppds.c + A module to scan plain data was added. + + * src/glpapi09.c + The following new API routines were added: + glp_read_sol read basic solution from text file; + glp_write_sol write basic solution to text file; + glp_read_ipt read interior-point solution from text file; + glp_write_ipt write interior-point solution to text file; + glp_read_mip read MIP solution from text file; + glp_write_mip write MIP solution to text file. + + * src/glpapi12.c + Advanced API routine glp_free_env was added. + + * examples/glpsol.c + The following three command-line options were added: + --mipgap tol set relative MIP gap tolerance + -r filename read solution from filename + -w filename write solution to filename + +Wed Sep 19 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.22 (7:0:7) has been released + + * src/glpios02.c + A bug was fixed in the MIP preprocessor (ios_preprocess_node). + Thanks to Roberto Bagnara <bagnara@cs.unipr.it> (Department of + Mathematics, University of Parma, Italy) for the bug report. + + * src/glpios02.c + A bug was fixed in the MIP preprocessor (col_implied_bounds), + due to which constraint coefficients with small magnitude could + lead to wrong implied bounds of structural variables. + + * src/glpipp02.c + A similar bug was fixed in the routine reduce_bounds. + + * src/glpapi01.c + A bug was fixed in the routines glp_set_mat_row and + glp_set_mat_col. (The bug appeared due to incorrect removing + zero elements from the row/column lists.) + + * src/glplpx14.c + A bug was fixed in the API routines lpx_read_mps and + lpx_read_freemps, due to which bounds of type LI specified in + BOUNDS section were incorrectly processed. + + * src/glplib05.c + A call to standard function vsprintf was replaced by a call to + vsnprintf for security reasons. Many thanks to Peter T. Breuer + <ptb@inv.it.uc3m.es> and Rafael Laboissiere <rafael@debian.org>. + +Tue Aug 28 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.21 (6:0:6) has been released + + * glpscg.h, glpscg.c + Routines to maintain sparse cliqued graph were added. + + * glpios02.c + MIP preprocessing routines were added. + + * glpk.h, glpios.h, glpios03.c + New reasons for calling the callback routine were introduced + in the MIP solver. + + * glpapi08.c + Default backtracking strategy was changed to best local bound. + + * glpapi11.c + New API routine glp_term_out to enable/disable terminal output + was added. + + * glprng.h, glprng02.c + Two routines to generate uniformly distributed pseudo-random + floating-point numbers were added. + +Thu Jul 26 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.20 (5:0:5) has been released + + * glpk.h, glpapi08.c + The routine lpx_integer was replaced by an equivalent routine + glp_intopt. Also new API routine glp_init_iocp was added. + + * glpiet.h, glpiet.c + Routines implementing the implicit enumeration tree are + no longer used and therefore were removed from the package. + + * glpios.h, glpios01.c, glpios02, glpios03 + Routines implementing the integer optimization suite being + replaced by a new version were removed from the package. + + * glpmip.h, glpmip01.c, glpmip02.c + + Routines implementing the B&B method being replaced by a new + version were removed from the package. + + * glpios.h, glpios01.c, glpios02.c + + Routines implementing a new version of the integer optimization + suite (IOS) based on the B&B method were added to the package. + + * glpk.h, glpapi10.c + Branch-and-bound interface routines were added to the package. + + * examples/tspsol.c + The TSP solver based on old version of the integer optimization + suite is no more supported and was removed from the package. + + * glpipp02.c + An error in the routine reduce_bounds was fixed; thanks to + Graham Rockwell <bionomicron@gmail.com> for the bug report. + + * glpk.latex + A new edition of the reference manual was included. + +Thu Jul 05 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.19 (4:0:4) has been released + + The principal change is upgrading to GPLv3. + + * glpapi01.c + A serious bug in the routine glp_del_cols was fixed; thanks to + Cedric[FR] <fox2113@wanadoo.fr> for the bug report. The bug + appeared because on deleting non-basic columns the basis header + remained valid, however, contained invalid (old) column ordinal + numbers. + + * glpapi10.c + A new advanced API routine glp_mem_limit was added. + + * glplpx01.c + The case GLP_EBOUND was added to the routine lpx_simplex. + Thanks to Cameron Kellough <Cameron.Kellough@sri.com> for the + bug report. + + * glplpx19.c + An API routine lpx_write_pb to write the problem instance in + OPB (pseudo boolean) format format was added. Thanks to Oscar + Gustafsson <oscarg@isy.liu.se> for the contribution. + + * glpsol.c + Two new options --wpb and --wnpb were added to glpsol to write + the problem instance in OPB format. + +Mon Jun 25 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.18 (3:0:3) has been released + + * glplib.h + Type names ulong_t and uldiv_t were changed to glp_ulong and + glp_uldiv to avoid conflicts with standard type names on some + platforms. Thanks to Boris Wirtz <Boris.Wirtz@uni-oldenburg.de> + for the bug report. + + * glpbfd.*, glpfhv.*, glplpf.* + LP basis factorization routines were made tidy. + + * glpk.h, glpapi04.c + The following API routines were added: + glp_set_rii, glp_set_sjj, glp_get_rii, glp_get_sjj. + + * glpk.h, glpapi06.c + The routine lpx_simplex was replaced by an equivalent routine + glp_simplex. Also new API routine glp_init_smcp was added. + + * glpk.h, glpapi09.c + The following advanced API routines were added: + glp_bf_exists, glp_factorize, glp_bf_updated, glp_get_bfcp, + glp_set_bfcp, glp_get_bhead, glp_get_row_bind, glp_get_col_bind, + glp_ftran, glp_btran. + + * glpk.latex + A new edition of the reference manual was included. + + * examples/dea.mod, examples/food.mod, examples/food2.mod + Three examples in the MathProg language were added. + Thanks to Sebastian Nowozin <nowozin@gmail.com>. + +Sat May 26 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.17 (2:0:2) has been released + + * glpdmp.h, glpdmp.c + Memory pool routines were replaced by a new version. + + * glpscs.h, glpscs.c + Segmented string routines were replaced by a new version. + + * glplpx08.c, glplpx09.c + Now the MIP problem may have no integer columns. + + * glpapi01.c + The routines glp_set_mat_row, glp_set_mat_col, and glp_load_mat + were modified to allow zero elements (which are not stored in + the constraint matrix). + + * glpscf.h, glpscf.c + Schur complement factorization routines were implemented. + + * glplpf.h, glplpf.c + LP basis factorization routines based on LU-factorization and + Schur complement were implemented. + + * glplpx02.c, glplpx03.c + New control parameter LPX_K_BFTYPE was introduced to choose the + basis factorization type used by the simplex method routines. + + * glpsol.c + Three new command-line options were added to choose the basis + factorization type used by the simplex method routines: --luf, + --cbg, and --cgr. + + * glpk.latex + A new edition of the reference manual was included. + +Sat May 05 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.16 (1:0:1) has been released + + * glpk.h, glpapi.c, glplpx01.c, glplpx02.c + Names of a number basic api routines were changed and now have + the prefix 'glp_'. To keep backward compatibility these routines + are also available via their old names prefixed with 'lpx_'. + + * glplpx19.c + Three new api routines were added: glp_version, glp_term_hook, + and glp_mem_usage. + + * glpk.latex, gmpl.texi + A new edition of the reference manuals was included. + + * lpglpk40.c + This example program is no longer supported and therefore was + removed from the package. + +Sun Feb 18 12:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.15 (0:0:0) has been released + + * configure.ac, Makefile.am + Autotools specification files were changed to use GNU Libtool + that allows building the static as well as shared GLPK library. + Thanks to Rafael Laboissiere <rafael@debian.org>. + +Mon Feb 05 08:00:00 2007 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.14 has been released + Now GLPK conforms to ILP32, LLP64, and LP64 programming models + (the latter seems to be the ultimate choice regarding 64-bit + architectures). Note that GLPK itself is a 32-bit application, + and the conformity only means that the package works correctly + on all these arenae. Nevertheless, on 64-bit platforms it is + possible to use more than 4GB of memory, if necessary. + + * Makefile + Starting from this release only the header glpk.h is needed to + be installed. + + * glplib01.c + Two routines bigmul and bigdiv which performs multiplication + and division of unsigned integers of arbitrary precision were + added. + + * glplib02.c + A set of 64-bit arithmetic routines were added. + + * glplib04.c + Some low-level library routines were improved and renamed. + + * glpcfg.h + The macro GLP_TM_SPEC were introduced to specify a version of + the time routine depending on the host environment. + +Mon Nov 13 12:00:00 2006 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.13 has been released + + * configure.in + '-lm' bug was fixed. + + * glpbfx.h, glpbfx.c + Basis factorization interface routines based on exact (bignum) + arithmetic were implemented. + + * glpssx.h, glpssx1.c, glpssx2.c + Simplex method routines based on exact (bignum) arithmetic were + implemented. + + * glplpx6e.c + The routine lpx_exact, which is an easy-to-use driver to the + exact simplex method, was added. + + * glpsol.c + Two command-line options were added: '--exact' and '--xcheck'. + +Wed Nov 08 12:00:00 2006 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.12 has been released + + * glpcfg.h + The package configuration file was added. + + * glplib2.c + Alternative version of the routines umalloc, ucalloc, and ufree + was provided. It does not limit the amount of allocated memory + to INT_MAX bytes and therefore can be used on platforms where + sizeof(void *) > sizeof(int). To enable this version one should + define the preprocessor variable GLP_HUGE_MEM. + + * glprng.c + The routine rng_create_rand was changed to initialize the + generator using seed = 1, not 0, to conform ISO C requirements. + + * glpgmp.h, glpgmp.c + A set of bignum arithmetic routines implementing operations on + integers and rationals was added. These routines are compatible + with the GNU MP library. + + NOTE: To attain a much better performance it is recommended to + use, if possible, the original GNU MP library rather than the + GLPK version, by defining the preprocessor variable GLP_USE_GMP. + + * glplux.h, glplux.c + A tentative implementation of sparse LU-factorization based on + exact (bignum) arithmetic was added. + + * glpssx.h, glpssx.c + A tentative implementation of some simplex method routines based + on exact (bignum) arithmetic was added. + + * glplpx6f.c + A preliminary implementation of the routine lpx_exact_check was + added. This routine checks the current basis for primal and dual + feasibility using exact (bignum) arithmetic. + + * examples/glpsol.c + The command-line option '--xcheck' was introduced to check the + current basis for feasibility using exact (bignum) arithmetic. + +Tue Jul 25 12:00:00 2006 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.11 has been released. + + * include/glpbfi.h, src/glpbfi.c + Basis factorization interface routines were added. + + * include/glpluf.h, src/glpluf1.c + Hypersparse solution routines were added. + + * include/glpinv.h, src/glpinv1.c + Hypersparse solution routines (fake version) were added. + + * include/glpmpl.h, src/glpmpl.c + Built-in functions card, length, and substr were implemented. + Output redirection in the printf statement was implemented. + + * examples/graph.mod, examples/crypto.mod + Two example models illustrating new features of the modeling + language were included. + +Thu May 11 12:00:00 2006 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.10 has been released. + + * src/glplpx8a.c + A fragment was added to the routines lpx_read_mps and + lpx_read_freemps to accept LI bound type (it is similar to LO, + however, additionally marks the column as integer). + + * include/glpbfi.h, src/glpbfi.c + The module glpbfi which implements the basis factorization + interface (BFI) was added. + + * src/glplpx7a.c + The routine lpx_cover_cut to generate mixed cover cuts was + added. + + * src/glplpx7b.c + The routine lpx_clique_cut to generate clique cuts and related + routines to maintain the conflict graph were added. + + * include/glplpx.h, src/glplpx5.c + The routine lpx_cpx_basis implementing Bixby's algorithm to + construct an initial LP basis was added. + + * examples/glpsol.c + Command-line option '--bib' was added which allows building + an initial LP basis using Bixby's algorithm. + Default command-line option '--mps' was changed to '--freemps'. + + * examples/cf12a.mod, examples/cf12b.mod + Two examples in MathProg (curve fitting problem) were added. + Thanks to Dr. Harley Mackenzie <hjm@hardsoftware.com>. + +Tue Jan 17 12:00:00 2006 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.9 has been released. + + * glpipp.h, glpipp1.c, glpipp2.c + A MIP presolver were implemented (currently incomplete). It is + used internally in the routine lpx_intopt (see below). + + * glplpx6d.c, glplpx7a.c + An advanced branch-and-bound solver (the routine lpx_intopt) + were implemented. + + * glplpx6c.c + The routine lpx_check_int to check MIP feasibility conditions + was added. + + * glplpx8a.c + The routine lpx_print_mip was changed to print MIP feasibility + conditions. + + * glpmpl.h, glpmpl1.c, glpmpl3.c + The built-in functions sin, cos, atan, and atan2 were added to + the MathProg language. + + * doc/lang.* + Some typos were fixed. + Thanks to Minh Ha Duong <haduong@centre-cired.fr> (CIRED, CNRS). + +Wed Jan 12 12:00:00 2005 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.8 has been released. + + * glpspx.h, glpspx1.c, glpspx2.c, glplpx6a.c + Simplex method routines were changed due to a new format of the + constraint matrix. + + * glpmat.h, glpmat.c + Sparse matrix routines were re-implemented using storage-by-rows + format. + + * glpipm.h, glpipm.c, glplpx6b.c + Interior-point method routines were changed due to a new format + of sparse matrices. + + * glpchol.h, glpchol.c + Old version of Cholesky factorization routines being replaced by + a new one (see glpmat.c) was removed from the package. + + * glplpx8c.c + Minor bug was fixed in api routine lpx_read_cpxlp. + +Mon Aug 23 12:00:00 2004 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.7 has been released. + + * glplpx.h, glplpx1.c + New core API routines were added (but not documented yet): + lpx_order_matrix, lpx_create_index, lpx_find_row, lpx_find_col, + lpx_delete_index. + + * glplpx8a.c + API routine lpx_read_mps was re-implemented, and two new API + routines lpx_read_freemps and lpx_write_freemps were added to + support free MPS format. + + * glplpx8c.c + Two API routines lpx_read_cpxlp and lpx_write_cpxlp (formerly + named lpx_read_lpt and lpx_write_lpt) were re-implemented. + + * glpmps.h, glpmps.c + This module formerly used in lpx_read_mps was removed from the + package. + + * glplpt.h, glplpt.c + This module formerly used in lpx_read_lpt was removed from the + package. + + * glpmip.h, glpmip1.h, glpmip2.h + New MIP routines mip_best_node and mip_relative_gap were added + due to suggestion of Brady Hunsaker <hunsaker@engr.pitt.edu>. + + * glpsol.c + The following new command-options were added: + --freemps to read problem data in free MPS format + --wfreemps to write problem data in free MPS format + --cpxlp to read problem data in CPLEX LP format + --wcpxlp to write problem data in CPLEX LP format + --bas to read LP basis from a text file in MPS format + --wbas to write LP basis to a text file in MPS format + --mostf to use "most fractional" branching heuristic + --bestb to use "best bound" backtracking heuristic + + * contrib/deli/*.* + GLPK Delphi interface module was temporarily removed from the + distribution due to licensing problems. + + * contrib/glpkmex/*.* + GLPK Matlab interface module was temporarily removed from the + distribution due to licensing problems. + + * contrib/jni/*.* + GLPK Java interface module was temporarily removed from the + distribution due to licensing problems. + +Wed Aug 04 12:00:00 2004 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.6 has been released. + + * glpmpl.h, glpmpl1.c, glpmpl2.c, glpmpl3.c, glpmpl4.c + Three new statements were implemented in the GNU MathProg + language: solve, printf, and for. Also some bugs were fixed. + + * glplpx.h, glplpx8e.c + Two API routines were added: lpx_read_prob and lpx_write_prob, + which allow reading and writing problem data in GNU LP format. + + * glpsol.c + Three new command-line options were added: --glp (to read + problem data in GNU LP format), --wglp (to write problem data + in GNU LP format), and --name (to change problem name). + + * glprng.h, glprng.c + A portable pseudo-random number generator was implemented as a + separate module. + + * glplib4.c + The old implementation of a pseudo-random number generator was + removed from the package. + + * doc/lang.*, doc/refman.* + New edition of the GLPK documentation was included. + + * contrib/glpkmex/*.* + A new version of GLPKMEX was included in the distribution. For + more details see contrib/glpkmex/ChangeLog. + +Mon Jul 19 12:00:00 2004 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.5 has been released. + + * glpmip.h, glpmip1.c, glpmip2.c, glplpx6c.c + New implementation of the branch-and-bound method was added. + It replaces the old implementation, which was removed from the + package. + + * glpies.h, glpies1.c, glpies2.c, glpies3.c + Modules used in the old implementation of the branch-and-bound + method were removed from the package. + + * glplib2.c + Now if the preprocessor variable GLPHUGEMEM is defined, other + version of the routines umalloc, ucalloc, and ufree is used on + compiling the package. This allows avoiding memory allocation + problems on platforms where sizeof(void *) > sizeof(int), for + example, where addresses are 64-bit while integers are 32-bit. + The modification was made due to a bug report provided by Karel + Zimmermann <kzimm@diamant.jouy.inra.fr> and Christophe Caron + <caron@diamant.jouy.inra.fr>. + +Sat Jan 17 12:00:00 2004 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.4 has been released. + + * glplpx.h, glplpx*.c + All API routines were re-implemented using new data structures. + Some new API routines were added and some existing API routines + became obsolete as shown below: + + Obsolete API routine Equivalent new API routine + lpx_check_name (no more supported) + lpx_set_obj_c0 lpx_set_obj_coef + lpx_set_row_coef (no more supported) + lpx_set_col_coef lpx_set_obj_coef + lpx_load_mat (no more supported) + lpx_load_mat3 lpx_load_matrix + lpx_unmark_all (no more supported) + lpx_mark_row (no more supported) + lpx_mark_col (no more supported) + lpx_clear_mat (no more supported) + lpx_del_items lpx_del_rows, lpx_del_cols + lpx_get_row_bnds lpx_get_row_type, lpx_get_row_lb, + lpx_get_row_ub + lpx_get_col_bnds lpx_get_col_type, lpx_get_col_lb, + lpx_get_col_ub + lpx_get_obj_c0 lpx_get_obj_coef + lpx_get_row_coef (no more supported) + lpx_get_col_coef lpx_get_obj_coef + lpx_get_row_mark (no more supported) + lpx_get_col_mark (no more supported) + lpx_get_row_info lpx_get_row_stat, lpx_get_row_prim, + lpx_get_row_dual + lpx_get_col_info lpx_get_col_stat, lpx_get_col_prim, + lpx_get_col_dual + lpx_get_ips_stat lpx_ipt_status + lpx_get_ips_row lpx_ipt_row_prim, lpx_ipt_row_dual + lpx_get_ips_col lpx_ipt_col_prim, lpx_ipt_col_dual + lpx_get_ips_obj lpx_ipt_obj_val + lpx_get_mip_stat lpx_mip_status + lpx_get_mip_row lpx_mip_row_val + lpx_get_mip_col lpx_mip_col_val + lpx_get_mip_obj lpx_mip_obj_val + + Obsolete API routines were kept for backward compatibility, + however, they will be removed in the future. + + * doc/refman.* + New edition of the GLPK reference manual containing description + of all new API routines was included. + + * contrib/glpkmex/*.* + GLPKMEX, a Matlab MEX interface to GLPK package, contributed by + Nicolo Giorgetti <giorgetti@dii.unisi.it> was included. + + * doc/GLPK_FAQ.txt + GLPK FAQ contributed by Harley Mackenzie <hjm@bigpond.com> was + included. + +Fri Dec 12 12:00:00 2003 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.3 has been released. + + * configure.in + The bug, due to which the standard math library is not linked on + some platforms, was fixed. + + * glpmpl3.c + The bug (0 ** y) was fixed in the routine fp_power. + + * glpmpl.h, glpmpl1.c, glpmpl3.c + Some new built-in functions (round, trunc, Irand224, Uniform01, + Uniform, Normal01, Normal) were added to the MathProg language. + + * glpmpl1.c + The MathProg syntax was changed to allow writing 'subj to'. + + * glplpx.h, glplpx1.c, glplpx2.c + The new api routine lpx_get_ray_info was added. + + * glplpx8a.c + The api routine lpx_print_sol was changed to print the number of + non-basic variable, which causes primal unboundness. + + * glpmps.c + The code was changed to avoid errors on compiling the package on + Mac OS X. Thanks to Andre Girard <andre@inrs-emt.uquebec.ca> for + the bug report. + + * doc/lang.*, doc/refman.* + Several typos were fixed and some new material was added in the + glpk documentation. + +Fri Nov 14 12:00:00 2003 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.2 has been released. + + * glpiet.h, glpiet.c, glpios.h, glpios1.c, glpios2.c, glpios3.c + A preliminary implementation of the Integer Optimization Suite + (IOS) was included in the package. Eventually IOS will replace + the Implicit Enumeration Suite (IES). + + * glplpx.h, glplpx6d.c + A dummy version of the integer optimization routine lpx_intopt + was included in the package. Later this routine will replace the + routine lpx_integer. + + * examples/glpsol.c + A new command-line option --int-opt was added to the solver to + call lpx_intopt rather than lpx_integer. + + * glpbcs.h, glpbcs1.c, glpbcs2.c + Being replaced by IOS routines (see above) the Branch-and-Cut + Framework (BCS) routines were removed from the package. + + * examples/tspsol.c + Stand-alone Symmetric TSP solver was completely re-programmed + using IOS routines. + + * glplib.h, glplib2.c, glplib4.c + The random-number generator was implemented. It is based on the + module GB_FLIB from the Stanford GraphBase originally developed + by Donald Knuth. + + * glphbsm.c, glplpx8a.c, glpmps.c + All calls to fopen/fclose were replaced by corresponding calls + to ufopen/ufclose due to bug reports provided by Morten Welinder + <terra@gnu.org> and <jpark@sfwmd.gov>. + + * glpmps.c + The code was made re-entrant. + + * glplpx8b.c + API routine lpx_print_sens_bnds for bounds sensitivity analysis + contributed by Brady Hunsaker <hunsaker@engr.pitt.edu> was added + to the package. This feature is also available in glpsol via the + command-line option --bounds. + + * contrib/jni/*.* + New version of GLPK JNI (Java Native Interface) contributed by + Chris Rosebrugh <cpr@pobox.com> was added to the package. + + * contrib/deli/*.* + GLPK DELI (Delphi Interface) contributed by Ivo van Baren + <i.van.baren@freeler.nl> was added to the package. + + * glplpx3.c + Default method to scale the problem was changed to equilibration + scaling (lp->scale = 1 in lpx_reset_parms). + + * glplpx6a.c + Two minor (non-critical) typos were fixed due to report provided + by Andrew Hamilton-Wright <andrewhw@ieee.org>. + + * glplpp2.c + An untested case (line 941) had been tested due to bug report + provided by Jiri Spitz <jiri.spitz@telecom.cz>. + + * w32bc5.mak, w32vc6.mak, w32vc6d.mak, d32dmc.mak + Several makefiles were added to allow building GLPK library for + some non-GNU 32-bit platforms. + +Sat Aug 23 12:00:00 2003 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.1 has been released. + + * glpmpl1.c, glpmpl3.c + Some bugs were fixed in the MathProg translator due to the bug + reports provided by Giles Thompson <gwpt1@cus.cam.ac.uk>: + conditional set expressions were incorrectly parsed; + dimen attribute was not set by default when a set was used + recursively in its own declaration; + logical expressions ... in if ... then ... else ... did not + work; + displaying set expressions did not free memory allocated for + temporary results. + + * glpmpl3.c (reduce_terms) + Implementation of summation of linear forms over domain was + improved to reduce complexity of that operation from O(n*n) to + O(n*log n). The improvement was made due to a report provided + by Sebastien de Menten <sdementen@hotmail.com>. + + * glplpx6a.c (line 1056), glpmip1.c (line 641) + Two minor bugs were fixed due to the bug report provided by + Kendall Demaree <kendal.demaree@verizon.net>. + + * glplpx.h, glplpx6a.c + The method of one artificial variable implemented in the routine + lpx_prim_art and used on the phase I in the glpk simplex solver + has a serious defect: for some lp instances it erroneously + reports that the problem has no primal feasible solution. This + error appears when the column of the artificial variable, which + enters the basis to make it primal feasible, has large + constraint coefficients, that leads to small reduced costs of + non-basic variables and premature termination of the search, + i.e. to wrong conclusion that the problem has no primal feasible + solution. To avoid this defect the routine lpx_prim_feas was + included. It implements the method of implicit artifical + variables (based on minimization of the sum of infeasibilities), + which is a bit slower but much more robust. The routine + lpx_prim_feas having the same functionality now is used instead + the routine lpx_prim_art. + + * glpinv.h, glpinv.c + The test used in the routine inv_update to detect low accuracy + after updating LU-factorization of the basis matrix was replaced + by a new, more robust test. + + * glplpx6c.c + Selecting an active node to be solved next in the routine + btrack_bestp was changed. Now, if any integer feasible solution + has not been found yet, the routine chooses an active node which + has the minimal sum of integer infeasibilities. + + * glpmip.h, glpmip1.c + The additional flag int_obj was included in the structure + MIPTREE used by the branch-and-bound. This flag is set in the + routine mip_create_tree and used in the routine is_better. It + means that the objective is integral, i.e. depends only on + integer variables with integer objective coefficients. The test + used in the routine check_integrality was also replaced by a + new, more reasonable one. + + * glplpx1.c + A minor bug was fixed in the routine lpx_check_name. + + * glpmpl.h, glpmpl4.c, glplpx8d.c + The flag skip_data was added to the parameter list of the + routine mpl_read_model. If this flag is set, the data section + in the model file is ignored. Corresponding change was made in + the routine lpx_read_model. Now, if both model and data files + are specified, the data section in the model file is ignored. + + * glplpx8c.c + A minor bug (wrong format used for writing free columns) in the + routine lpx_write_lpt was fixed due to the bug report provided + by Bernhard Schmidt <schmidt@math.uni-augsburg.de> + + * sample/glpsol.c + The command-line parameter --tmlim, which allows limiting the + solution time, was added. + + * doc/lang.*, doc/refman.* + New edition of the GLPK documentation was included. + + * java-binding/*.* + New version of the GLPK JNI (Java Native Interface) package was + included in the distribution. + + * sample/lpglpk40.c + A non-trivial example was added. It allows using GLPK as a base + LP solver for Concorde, a program for solving Traveling Salesman + Problem (TSP). For details see comments in lpglpk40.c. + + * sample/*.mod + Some examples of LP and MIP models written in GNU MathProg were + added. + +Tue May 06 12:00:00 2003 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 4.0 has been released. + + * glpmpl.h, glpmpl1.c, glpmpl2.c, glpmpl3.c, glpmpl4.c + The model translator for the GNU MathProg modeling language was + implemented and included in the package. + + * glplpx.h, glplpx8d.c + The api routine lpx_read_model, which is an interface to the + MathProg translator, was included in the package. + + * glplpx.h, glplpx8a.c + The api routine lpx_print_prob for writing LP/MIP problem data + in plain text format was included in the package. + + * sample/glpsol.c + New version of the GLPK stand-alone LP/MIP solver that supports + the GNU MathProg modeling language was implemented. + + * doc/lang.latex, doc/lang.dvi, doc/lang.ps + The document "GLPK: Modeling Language GNU MathProg" was included + in the package. + + * doc/refman.latex, doc/refman.dvi, doc/refman.ps + New edition of the GLPK Reference Manual was included in the + package. + + * glplpx8c.c + A bug in the api routine lpx_write_lpt was fixed. Due to that + bug an addressing error occured in the routine if the objective + function has the non-zero constant term. + + * glplan.h, glplan1.c, glplan2.c, glplan3.c, glplan4.c, + * glplan5.c, glplan6.c, glplan7.c, glplan8.c, glplpx8b.c + All modules of the translator for the GLPK/L modeling language + were removed from the package, because GLPK/L being completely + superseded by GNU MathProg is no more supported. + +Tue Mar 25 12:00:00 2003 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.3 has been released. + + * glplpp.h, glplpp1.c, glplpp2.c + An implementation of the built-in LP presolver was added to the + package. + + * glplpx.h + The flag presol was added to the structure LPX. This flag tells + the lpx_simplex whether the built-in LP presolver should be used + or not. By default this flag is off. Also three macros (namely + LPX_E_NOPFS, LPX_E_NODFS, and LPX_K_PRESOL) that concern using + the LP presolver were introduced. + + * glplpx3.c, glplpx6a.c + These modules was changed to use the built-in LP presolver. + + * sample/glpsol.c + Command line options --presol and --nopresol that concern using + the LP presolver were added to the stand-alone LP/MIP solver. + + * glplan1.c + This module was changed to allow declaring sets like A[1:10] in + the models written in the GLPK/L modeling language. + + * doc/refman.latex, doc/lang.latex + New editions of the documents "GLPK User's Guide" and "GLPK/L + Modeling Language" were included in the distribution. + + * java-binding/*.* + The package GLPK JNI (Java Native Interface) implementing Java + binding for GLPK was included in the distribution. This package + was developed and programmed by Yuri Victorovich <yuri@gjt.org>. + +Tue Feb 18 12:00:00 2003 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.2.4 has been released. + + * glplpx6b.c + The code was changed to allow auxiliary variables have non-zero + objective coefficients. + + Also a minor bug was fixed (the constant term was not considered + on displaying the objective function value). + + * sample/glpsol.c + The code was changed to fix a bug (the command-line option 'bfs' + was not recognized). The bug was fixed due to report provided by + Olivier <odwl@skynet.be>. + + * glplpt.c + The code was changed to fix a bug (binary variables were treated + erroneously as integer ones). + + * glplpx6b.c + The code was changed to fix a bug (variables that have no lower + bounds were incorrectly processed on converting to the standard + formulation). The bug was fixed due to report kindly provided by + Kjell Eikland <kjell.eikland@broadpark.no>. + +Mon Nov 11 12:00:00 2002 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.2.3 has been released. + + * glpmip.h, glpmip1.c + A preliminary implementation of the branch-and-bound driver + based on the implicit enumeration suite (glpies) was added to + the package. This module is not documented yet. + + * glplpx6c.c + A new implementation of the api routine lpx_integer which now + is based on the b&b driver (see glpmip above) was included in + the package. This new implementation has exactly the same + functionality as the old version and therefore all changes are + transparent to the api user. + + * glpbbm.h, glpbbm.c + * glprsm.h, glprsm1.c, glprsm2.c + * glplp.h, glplp.c + These modules were removed from the package, because they were + used only in the old version of the routine lpx_integer, which + was replaced by the new version (see glplpx6c above). + + * glplpx.h, glplpx6a.c + The api routine lpx_check_kkt was included in the package and + its description was added in the reference manual. This routine + allows checking Karush-Kuhn-Tucker optimality conditions for an + LP solution. + + * glplpx.h, glplpx8a.c + Now the api routine lpx_print_sol also prints information about + "solution quality" obtained via the api routine lpx_check_kkt. + + * glplpx.h, glplpx8a.c + New api routines lpx_read_bas and lpx_write_bas were included + in the package and documented. The routine lpx_write_bas allows + writing a current basis from an LP object to a text file in the + MPS format. The routine lpx_read_bas allows reading a basis + prepared in the MPS format from a text file into an LP object. + + * glplpt.c + The parsing routine which reads LP problem data prepared in the + CPLEX LP format was modified to allow specifying lower bounds + of variables also in the form 'variable >= lower bound' (in the + bounds section). This modification was made due to a notice + provided by Ivan Luzzi <iluzzi@libero.it>. + + * glplpx.h, glplpx8c.c + The api routine lpx_write_lpt which allows writing LP problem + data from an LP object to a text file using the CPLEX LP format + was included in the package and documented. + + * glplpx.h, glplpx3.c + The control parameter LPX_K_LPTORIG that affects the behavior + of the api routine lpx_write_lpt was introduced. + + * glplan6.c + The semantics of the language GLPK/L was changed to allow + selection in case when not all mute letters of a predicate (the + operand that follows the keyword 'where') are presented in a + parameter (the operand that precedes the keyword 'where'), i.e. + to allow writing something like this: + y[j] := sum(i, x[i] where p[i,j]); + The paragraph "Selection" in the langauge description (page 25) + was also correspondingly changed. This change of the language + semantics was undertaken due to a notice provided by Peter Lee + <plee@kinggee.com.au>. + + * sample/hwd.lpm + A nice example of LP model written in GLPK/L and contributed by + Peter Lee <plee@kinggee.com.au> was included in the package. + + * glplpx6b.c + The api routine lpx_interior was modified: a) to compute dual + values for all structural as well as auxiliary variables; b) to + allow specifying non-zero objective coefficients at auxiliary + variables. + + * sample/glpsol.c + Three new command-line options were added to the solver, which + are: --plain, --orig, and --wrlpt. + +Mon Oct 14 12:00:00 2002 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.2.2 has been released. + + * glplpt.h, glplpt.c + A module that reads LP/MIP problem data in CPLEX LP format was + implemented. + + * glplpx8c.c + An api routine lpx_read_lpt that reads LP/MIP problem data in + CPLEX LP format was implemented. + + * sample/glpsol.c, sample/plan.lpt + A new command-line option '--lpt' that allows reading LP/MIP + problem data in CPLEX LP format was added to the solver. + + * doc/refman.latex, doc/refman.dvi, doc/refman.ps + A new edition of the Reference Manual was included. + + * source/*.c + Casting to (unsigned char) was added in some calls to the + classification functions (isalpha, etc.). The bug was fixed due + to report provided by Morten Welinder <terra@diku.dk>. + + * glplpx8a.c + The local routine mps_numb used in the routine lpx_write_mps + was modified to correctly format floating-point numbers that + have two digits in the decimal exponent. The bug was fixed due + to report provided by Vlahos Kiriakos <Kiriakos.Vlahos@gs.com>. + + * glplan.h, glplan1.c, ..., glplan8.c + Several serious bugs were fixed in the language processor due + to reports provided by <NORBERT.PIOTROWSKI@LHSYSTEMS.COM>: + (a) a static search tree used to find sparse array elements was + sometimes overwritten that caused the message 'assertion failed' + to appear; the bug was fixed by creating separate search trees + in parsing routines; (b) a variable declared using the + predicate-controlled variable declaration statement had wrong + order of domain sets, because the variable array was built as + a copy of the predicate array; the bug was fixed by using the + internal routine transpose that coordinates mute letters (and + therefore domain sets) on copying sparse arrays; (c) sometimes + assignment statements like x[#a,#b,#c] := ... was incorrectly + processed; the bug was fixed by including an appropriate check + into the internal routine assign_stmt. + + * glp_simplex.c + An additional check to see if all lower bounds are not greater + than corresponding upper bounds was included in the routine to + prevent wrong results to appear. Such incorrectness sometimes + was not detected, namely, when variables with such bounds were + non-basic and never entered the basis. + + * glpspx1.c + Maximal number of simplex iterations before reinversion was + decreased from 100 to 50. This allowed to improve accuracy and, + that is more important, to reduce the solution time for many + serial lp problems approximately 1.5--2 times. + + * glpspx2.c + A check to see if all elements in the column chosen to enter + the basis are close to zero in the routine spx_prim_chuzr was + temporarily removed because this check gave wrong conclusion in + case when the corresponding non-basic variable had zero column + in the constraint matrix. An analogous check to see if all + elements in the row chosen to leave the basis are close to zero + in the routine spx_dual_chuzc was also temporarily removed on + the same reason. The bug was fixed due to reports provided by + Flavio Keidi Miyazawa <fkm@ic.unicamp.br> and Vlahos Kiriakos + <Kiriakos.Vlahos@gs.com>. + +Mon Aug 12 12:00:00 2002 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.2.1 has been released. + + * glpbcs.h, glpbcs1.c, glpbcs2.c + * glpies.h, glpies1.c, glpies2.c, glpies3.c + A preliminary implementation of the branch-and-cut framework + was included in the package. + + * doc/brcut.txt + The document "GLPK: A Preliminary Implementation of the + Branch-And-Cut Framework" was included in the distribution. + + * sample/tspsol.c + An illustrative program for solving symmetric TSP based on the + branch-and-cut method was included in the package. + + * glpdmp.h, glpdmp.c + A new, re-enterable version of routines for managing dynamic + memory pools was included in the package. + + * glpavl.h, glpavl.c + A new, re-enterable version of routines for managing AVL search + trees was included in the package. + + * glplib.h, glplib2.c + Two new low-level routines ufopen and ufclose were included in + the package. + + * glplpx.h, glplpx7.c + The following new api routines were added: lpx_eval_activity, + lpx_eval_red_cost, lpx_reduce_form, lpx_mixed_gomory. + + * glptsp.h, glptsp.c + A module for reading TSP data using TSPLIB format was included + in the package. + +Mon Jul 15 12:00:00 2002 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.2 has been released. + + * glplpx.h, glplpx1.c, glplpx2.c + The identifier 'class' (used as a member name in the structure + LPX and as an argument name in the routine lpx_set_class) was + changed to 'clss' in order to avoid conflicts with C++ reserved + words. + + * glpk.h, glplpx.h, glplpx1.c, glplpx2.c, glplpx6a.c, + * glplpx6b.c, glplpx6c.c, glplpx7.c, glplpx8.c + The following new api routines were added: lpx_set_obj_name, + lpx_get_obj_name, lpx_get_row_mark, lpx_get_col_mark, + lpx_transform_row, lpx_transform_col, lpx_prim_ratio_test, + lpx_dual_ratio_test, lpx_interior, lpx_get_ips_stat, + lpx_get_ips_row, lpx_get_ips_col, lpx_get_ips_obj, lpx_read_lpm, + lpx_write_mps, lpx_print_ips. + + * glpsol.c + The solver was completely re-programmed using new api routines. + + * lang.latex, lang.dvi, lang.ps + New edition of the document "GLPK: Modeling Language GLPK/L" + was included in the distribution. + + * refman.latex, refman.dvi, refman.ps + New edition of the document "GLPK: Reference Manual" (which + contains descriptions of all new api routines) was included in + the distribution. + + * glpapi.h, glpapi1.c, glpapi2.c, glpapi3.c, glpapi4.c + These files (which contain old api routines) were removed from + the package. + + * glpipm1.c, glpipm2.c + The file glpipm1.c was renamed to glpipm.c. The file glpipm2.c + was used only by old api routines and therefore was removed from + the package. + + * language.texinfo + Old version of the document "GLPK: Modeling Language GLPK/L" was + removed from the distribution. + +Mon May 27 12:00:00 2002 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.1 has been released. + + * glplpx.h, glplpx1.c, glplpx2.c, glplpx3.c, glplpx4.c, + * glplpx5.c, glplpx6.c, glplpx7.c, glplpx8.c + A preliminary implementation of new API routines was completed. + + * refman.latex, refman.dvi, refman.ps + A draft edition of the document "GLPK Reference Manual", which + describes new API routines, was included. + + * glplib3.c + A bug in measuring long time intervals was fixed up. + + * glprsm3.c + This module contains some obsolete routines not longer used and + therefore it was removed from the package (into the subdirectory + 'oldsrc'). + + * glprsm.h + Some declarations related to the module 'glprsm3.c' (see above) + were removed. + + * guide.texinfo + The document "GLPK User's Guide" describing old API routines was + removed from the package (into the subdirectory 'oldsrc'). + + * newapi.txt + The document "New GLPK API Routines" was removed at all, because + it is superseded by the new reference manual (see above). + +Mon May 13 12:00:00 2002 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.0.8 has been released. + + * glplpx.h, glplpx1.c, glplpx2.c, glplpx3.c, glplpx4.c, + * glplpx5.c, glplpx6.c, glplpx7.c + A preliminary (currently incomplete) implementation of new api + routines was included. + + * sample/newsamp.c + A sample program for the new api routines was included. + + * newapi.txt + A draft of the document "New GLPK API Routines" was included. + + * glpapi2.c, glpapi5.c, glpapi6.c + These modules (which contain the api routines glp_call_rsm1, + glp_simplex1, glp_pivot_in, glp_pivot_out) were removed from the + package (to the subdirectory 'oldsrc') since these routines are + functionally superseded by the new api routines. + + * glpk.h, glpapi2.c, glpapi3.c, glpapi4.c + The api routines glp_simplex2, glp_call_ipm1, glp_call_bbm1 were + renamed to glp_simplex, glp_interior, glp_integer, respectively. + + * sample/glpsol.c + Some command-line options (which got obsolete due to the recent + changes in api) were excluded. + + * doc/guide.texinfo + New edition of the document "GLPK User's Guide" was included in + the distribution to reflect the changes in some api routines. + + * doc/libref.texinfo + This document was removed from the package (to the subdirectory + 'oldsrc') since it describes the library routines, most of which + got obsolete and no longer used. + + * Makefile.in + A minor bug was fixed up due to bug report from Hans Schwengeler + <Hans.Schwengeler@unibas.ch>. + +Mon Apr 22 12:00:00 2002 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.0.7 has been released. + + * glpduff.h, glpduff.c, glpspx.h, glpspx1.c, glpspx2.c, + * glpapi7.c + These modules were replaced by a new implementation of the + simplex method and therefore they were removed from the package + (however they still can be found in the subdirectory 'oldsrc'). + + * glprsm1.c + The routine crash_aa was replaced by a new implementation and + therefore it was removed from the file 'glprsm1.c'. + + * glplpx.h, glplpx.c, glpspx.h, glpspx1.c, glpspx2.c, glpspx3.c, + * glpspx4.c, glpapi7.c + New (currently incomplete) implementation of the simplex method + components was included in the package. + +Thu Mar 28 12:00:00 2002 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.0.6 has been released. + + * glpluf.h, glpluf.c, glpinv.h, glpinv.c + New version of LU-factorization and basis maintenance routines + (based on Forrest-Tomlin updating technique) was implemented. + + * glpeta.h, glpeta.c, glpfhv.h, glpfhv.c, glpgel.h, glpgel.c, + * glppfi.h, glppfi.c, glprfi.h, glprfi.c + These routines implement some other forms of the basis matrix. + Now they became obsolete being functionally superseded by the + new version of basis maintenance routines (see above) and were + removed from the package (however they still can be found in the + subdirectory 'oldsrc'). + + * glpbbm.c, glprsm.h, glprsm1.h, glprsm2.h, glpspx.h, glpspx2.c, + * glprsm2.c, glpsol.c + Necessary changes were made in order to use the new version of + basis maintenance routines. + +Tue Jan 29 12:00:00 2002 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.0.5 has been released. + Structure of the package was re-organized in order to simplify + its maintenance. + + * doc/guide.texinfo + New edition of the document "GLPK User's Guide" was included in + the distribution. Now the document includes descriptions of some + additional API routines recently added to the package. + + * doc/newapi.txt + The document "Additional GLPK API Routines" was removed from the + distribution, because the corresponding material was included in + the user's guide (see above). + +Mon Dec 10 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.0.4 has been released. + + * glpspx.h, glpspx1.c, glpspx2.c, glpapi/glp_simplex2.h + A new, more efficient version of the two-phase primal simplex + method was implemented (advanced initial basis, projected + steepest edge, recursive computations of solution components). + + * glpapi/glp_call_bbm1.c + Now LP relaxation can be solved either using rsm1_driver(), or + using glp_simplex2(). The choice is controlled by the parameter + 'meth' (a member of struct bbm1). + + * sample/glpsol.c + The new implementation of the simplex method is now used by + default. The old version is available via --old-sim option. + + * glpmat/gm_scaling.c + Now this routine displays only two lines: an initial "quality" + and a final "quality". + + * glplp/prepro_lp.c + Identifiers 'fmin' and 'fmax' renamed to 'f_min' and 'f_max' in + order to avoid conflict with <math.h>. The bug was fixed due to + report provided by Sami Farin <sfarin@ratol.fi>. + +Wed Oct 03 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.0.3 has been released. + + * glprsm/harris_row.c, glprsm/harris_col.c + The relative tolerance used on the first pass of the two-pass + ratio test was replaced by the absolute tolerance. + + * glprsm/rsm_primal.c, glprsm/rsm_feas.c, glprsm/rsm_dual.c + The absolute tolerance passed to the two-pass ratio test routine + was decaresed (for both primal and dual simplex). + + These changes were made in order to improve numerical stability + of the simplex method. + + * glprsm/glp_call_rsm1.c, glprsm/glp_call_bbm1.c, + * glprsm/glp_simplex1, glprsm/glp_pivoting.c + Default form of the inverse was changed from RFI to AFI. + +Mon Sep 24 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.0.2 has been released. + + * glpfhv.h, glpfhv.c + New version of the basis maintaining routines was implemented. + These routines, which are based on so called FHV-factorization + (a variety of LU-factorization) and Gustavson's data structures, + perform the main operations on the basis matrix faster at the + expense of some worsening numerical accuracy. + + * glprsm.h, glprsm/afi.c + The routines, which implement AFI (Advanced Form of the + Inverse) based on FHV-factorization, were added to the package. + This new form is available via the parameter form = 3 (on API + level) or via the option --afi (in GLPSOL solver). + + * EFI was renamed to PFI + In order to correct terminology the acronym EFI (Elimination + Form of the Inverse) was replaced by PFI (Product Form of the + Inverse) everywhere in the source code and the documentation. + + * glpset/umalloc.c, glpset/ucalloc.c + * glpset/get_atom.c, glpset/get_atomv.c + These memory management routines were changed in order *not* to + clear allocated memory blocks by binary zeros. + +Wed Aug 01 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.0.1 has been released. + + * glpapi/old_api.c, glplp/extract_lp.c, store_lpsol.c + Old API routines were deleted from the package. + + * include/glpk.h, include/glpapi.h, include/glplp.h + Specifications of old API routines and data structures were + removed from the headers. + + * sample/glpsol.c + New version of the stand-alone solver GLPSOL that now uses new + API routines was implemented. + + * glpapi/glp_set_row_fctr.c, glpapi/glp_set_col_fctr.c, + * glpapi/glp_get_row_fctr.c, glpapi/glp_get_col_fctr.c, + * glpapi/glp_scale_prob.c + Scaling routines were added. + + * glpapi/glp_write_mps.c + The routine for writing problem data in MPS format was added. + + * glpapi/glp_simplex1.c + Comprehensive driver to the simplex method was added. + + * glpapi/glp_pivoting.c + The routines glp_pivot_in() and glp_pivot_out() intended for + basis maintaining were added. + + * glprsm/create_rsm.c, glprsm/delete_rsm.c, glprsm/scale_rsm.c, + * glprsm/build_basis.c + Additional low level routines related to the simplex method + were added. + + * glpk.h, glpapi.h, glprsm.h + Additional specifications for new routines and data structures + were added. + + * sample/lpglpk30.c + A non-trivial example was added. It allows using GLPK as a base + LP solver for Concorde, a program for solving Traveling Salesman + Problem (TSP). For details see comments in 'lpglpk30.c'. + + * doc/newapi.txt + The document "Additional GLPK API Routines" that describes some + new API routines was included. + +Thu Jul 19 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 3.0 has been released. + + Now GLPK is provided with new API, which is intended for using + the package in more complex algorithmic schemes. + + * glpapi/old_api.c + All routines related to old API were gathered in one file named + 'old_api.c'. + + * glpapi/*.c + These routines that implement new API were added to the package. + + * include/glpk.h, include/glpapi.h + Specifications of new API routines and data structures were + added to these headers. Specifications of old API routines and + data structures were locked by #ifdef GLP_OLD_API directive. + + * doc/guide.texinfo + New edition of the document "GLPK User's Guide" that correspond + to new API was included. + +Thu Jun 14 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 2.4.1 has been released. + + * doc/glpk_ml.texinfo + The new document "Modeling Language GLPK/L" was included. + + * doc/glpk_ug.texinfo + New edition of the document "GLPK User's Guide" was included. + + * doc/language.txt + The preliminary document "GLPK/L Modeling Language: A Brief + description" was removed from the distribution, because it has + been replaced by the new document "Modeling Language GLPK/L". + + * glplang/l_spar.c + The routine comparison() was re-programmed in order to + implement the relation operation as specified in the language + description. + + * glpmip.h, glpmip/*.c + The partition 'glpmip' was renamed to 'glpbbm'. + +Thu May 10 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 2.4 has been released. + + Now GLPK includes an implementation of a preliminary version of + the GLPK/L modeling language. + + * glplang.h, glplang/*.c + The header 'glplang.h' and a set of routines that implements + the GLPK/L language processor (the partition 'glplang') were + added to the package. + + * doc/language.txt + The document "GLPK/L Modeling Language: A Brief Description + (Supplement to GLPK User's Guide)" in plain text format was + included in the package (see the file 'language.txt' in the + subdirectory 'doc' of the distribution). + + * ex/model1.lpm, ex/model2.lpm + Two examples of model descriptions written in GLPK/L were added + to the package. + + * sample/glpsol.c + This program was modified in order: a) to allow processing + model description written in GLPK/L; b) to allow solving pure + LP problem using the interior point method. + + * sample/glpipm.c + This program was removed from the package, because its function + was passed to the GLPSOL solver. + + * Makefile.in + This file was changed in order to install the GLPSOL solver + executable. + +Mon Apr 09 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 2.3 has been released. + + * glpmip.h, glpmip/*.c + These routines (that implement the branch-and-bound method) were + re-programmed in order to improve robustness of implementation. + In particular, heuristic routines were carried out from the main + driver routine. + + Additional GLPK API routines were documented. + + New edition of the document "GLPK User's Guide" was included in + the package. + + The preliminary document "Mixed Integer Programming Using GLPK + Version 2.2 (Supplement to GLPK User's Guide)" was removed from + the package, because this material was included in GLPK User's + Guide. + +Thu Mar 15 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 2.2 has been released. + + Now GLPK includes a tentative implementation of the + branch-and-bound procedure based on the dual simplex method for + mixed integer linear programming (MIP). + + The preliminary document "Mixed Integer Programming Using GLPK + Version 2.2 (Supplement to GLPK User's Guide)" was included into + the package in plain text format (see the file 'mip.txt' in the + subdirectory 'doc' of the distribution). + + * glpmip.h, glpmip/*.c, glpapi/glp_integer.c + These routines (that implement the branch-and-bound method) were + added to the package. + + * sample/glpsol.c + This program was modified in order to allow solving LP and MIP + problems. + + * glprsm/rsm_primal.c, glprsm/rsm_dual.c, glprsm/rsm_feas.c, + * glprsm/rsm1_driver.c + These routines (which are drivers to basic components of the + revised simplex method) were added to the package. + +Mon Feb 19 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 2.1 has been released. + + * glprsm.h, glprsm/*.c + These routines (that implement components of the revised simplex + method) were re-programmed and documented. + + The document "GLPK Implementation of the Revised Simplex Method" + was included into the package. + +Thu Jan 25 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 2.0 has been released. + + Now GLPK includes a tentative implementation of the primal-dual + interior point method for large-scale linear programming (for + more details see the file `NEWS' in the distribution). A number + of routines related to the interior point method were added to + the package. + + * insist.c + The routine `insist' and the macro of the same name were + introduced into the package in order to replace the standard + macro `assert'. Some routines require the expression specified + in the `assert' macro to be evaluated, but compiling the package + with NDEBUG option prevents from that. This bug was fixed due to + bug report provided by Peter A. Huegler <phuegler@bsco.com>. + + * Makefile.in + Minor bug was fixed due to a patch provided by Alexandre Oliva + <oliva@lsd.ic.unicamp.br>. + +Wed Jan 10 12:00:00 2001 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 1.1.2 has been released. + + * umalloc.c, ufree.c, create_pool.c, get_atom.c, get_atomv.c + These routines were changed in order to fix a bug due to + report provided by Andrew Hood <ajhood@fl.net.au>. Because of + this bug data alignment error occured on the Sparc computer. + +Tue Dec 14 12:00:00 2000 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 1.1.1 has been released. + + Minor bug was fixed in `Makefile.in'. + + GLPK Library Reference was included. + +Mon Nov 27 12:00:00 2000 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 1.1 has been released. + + Minor changes were made in order to co-ordinate GLPK routines + and their descriptions. + + GLPK User's Guide was included. + +Fri Oct 20 12:00:00 2000 Andrew Makhorin <mao@mai2.rcnet.ru> + + * GLPK 1.0 has been released. diff --git a/resources/3rdparty/glpk-4.53/INSTALL b/resources/3rdparty/glpk-4.53/INSTALL new file mode 100644 index 000000000..749f33d0a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/INSTALL @@ -0,0 +1,209 @@ +INSTALLING GLPK ON YOUR COMPUTER +******************************** + +Unpacking the distribution file +------------------------------- +The GLPK package (like all other GNU software) is distributed in the +form of a packed archive. It is one file named `glpk-X.Y.tar.gz', where +`X' is the major version number and `Y' is the minor version number; +for example, the archive name might be `glpk-4.15.tar.gz'. + +In order to prepare the distribution for installation you should: + +1. Copy the GLPK distribution file to a working directory. + +2. Unpack the distribution file with the following command: + + gzip -d glpk-X.Y.tar.gz + + After unpacking the distribution file is automatically renamed to + `glpk-X.Y.tar'. + +3. Unarchive the distribution file with the following command: + + tar -x < glpk-X.Y.tar + + It automatically creates the subdirectory `glpk-X.Y' containing the + GLPK distribution. + +Configuring the package +----------------------- +After unpacking and unarchiving the GLPK distribution you should +configure the package, i.e. automatically tune it for your platform. + +Normally, you should just `cd' to the directory `glpk-X.Y' and run the +`configure' script, e.g. + + ./configure + +The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It also creates file `config.h' containing platform-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + +Running `configure' takes about a few seconds. While it is running, it +displays some messages that tell you what it is doing. If you don't want +to see the messages, run `configure' with its standard output redirected +to `dev/null'; for example, `./configure > /dev/null'. + +By default both static and shared versions of the GLPK library will be +compiled. Compilation of the shared librariy can be turned off by +specifying the `--disable-shared' option to `configure', e.g. + + ./configure --disable-shared + +If you encounter problems building the library try using the above +option, because some platforms do not support shared libraries. + +The GLPK package has some optional features listed below. By default +all these features are disabled. To enable a feature the corresponding +option should be passed to the configure script. + +--with-gmp Enable using the GNU MP bignum library + + This feature allows the exact simplex solver to use the GNU MP + bignum library. If it is disabled, the exact simplex solver uses the + GLPK bignum module, which provides the same functionality as GNU MP, + however, it is much less efficient. + + For details about the GNU MP bignum library see its web page at + <http://gmplib.org/>. + +--with-zlib Enable using the zlib data compression library + + This feature allows GLPK API routines and the stand-alone solver to + read and write compressed data files performing compression and + decompression "on the fly" (compressed data files are recognized by + suffix `.gz' in the file name). It may be useful in case of large + MPS files to save the disk space. + + For details about the zlib compression library see its web page at + <http://www.zlib.net/>. + +--enable-dl The same as --enable-dl=ltdl +--enable-dl=ltdl Enable shared library support (GNU) +--enable-dl=dlfcn Enable shared library support (POSIX) + + Currently this feature is only needed to provide dynamic linking to + ODBC and MySQL shared libraries (see below). + + For details about the GNU shared library support see the manual at + <http://www.gnu.org/software/libtool/manual/>. + +--enable-odbc Enable using ODBC table driver (libiodbc) +--enable-odbc=unix Enable using ODBC table driver (libodbc) + + This feature allows transmitting data between MathProg model objects + and relational databases accessed through ODBC. + + For more details about this feature see the supplement "Using Data + Tables in the GNU MathProg Modeling Language" (doc/tables.*). + +--enable-mysql Enable using MySQL table driver (libmysql) + + This feature allows transmitting data between MathProg model objects + and MySQL relational databases. + + For more details about this feature see the supplement "Using Data + Tables in the GNU MathProg Modeling Language" (doc/tables.*). + +Compiling the package +--------------------- +Normally, you can compile (build) the package by typing the command: + + make + +It reads `Makefile' generated by `configure' and performs all necessary +jobs. + +If you want, you can override the `make' variables CFLAGS and LDFLAGS +like this: + + make CFLAGS=-O2 LDFLAGS=-s + +To compile the package in a different directory from the one containing +the source code, you must use a version of `make' that supports `VPATH' +variable, such as GNU `make'. `cd' to the directory where you want the +object files and executables to go and run the `configure' script. +`configure' automatically checks for the source code in the directory +that `configure' is in and in `..'. If for some reason `configure' is +not in the source code directory that you are configuring, then it will +report that it can't find the source code. In that case, run `configure' +with the option `--srcdir=DIR', where DIR is the directory that contains +the source code. + +Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Here are the `make' variables that you might want to override with +environment variables when running `configure'. + +For these variables, any value given in the environment overrides the +value that `configure' would choose: + +CC: C compiler program. The default is `cc'. + +INSTALL: Program used to install files. The default value is `install' + if you have it, otherwise `cp'. + +For these variables, any value given in the environment is added to the +value that `configure' chooses: + +DEFS: Configuration options, in the form `-Dfoo -Dbar ...'. + +LIBS: Libraries to link with, in the form `-lfoo -lbar ...'. + +Checking the package +-------------------- +To check the package, i.e. to run some tests included in the package, +you can use the following command: + + make check + +Installing the package +---------------------- +Normally, to install the GLPK package you should type the following +command: + + make install + +By default, `make install' will install the package's files in +`usr/local/bin', `usr/local/lib', etc. You can specify an installation +prefix other than `/usr/local' by giving `configure' the option +`--prefix=PATH'. Alternately, you can do so by consistently giving a +value for the `prefix' variable when you run `make', e.g. + + make prefix=/usr/gnu + make prefix=/usr/gnu install + +After installing you can remove the program binaries and object files +from the source directory by typing `make clean'. To remove all files +that `configure' created (`Makefile', `config.status', etc.), just type +`make distclean'. + +The file `configure.ac' is used to create `configure' by a program +called `autoconf'. You only need it if you want to remake `configure' +using a newer version of `autoconf'. + +Uninstalling the package +------------------------ +To uninstall the GLPK package, i.e. to remove all the package's files +from the system places, you can use the following command: + + make uninstall + +======================================================================== diff --git a/resources/3rdparty/glpk-4.53/Makefile.am b/resources/3rdparty/glpk-4.53/Makefile.am new file mode 100644 index 000000000..5a040f49a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/Makefile.am @@ -0,0 +1,7 @@ +## Process this file with automake to produce Makefile.in ## + +ACLOCAL_AMFLAGS=-I m4 + +SUBDIRS = src examples + +## eof ## diff --git a/resources/3rdparty/glpk-4.53/Makefile.in b/resources/3rdparty/glpk-4.53/Makefile.in new file mode 100644 index 000000000..5ae9553c6 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/Makefile.in @@ -0,0 +1,759 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 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@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +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 = . +DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ + THANKS config.guess config.sub install-sh ltmain.sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.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 config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + cscope distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +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@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I m4 +SUBDIRS = src examples +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu 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: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then rm -f stamp-h1; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# 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) $(RECURSIVE_CLEAN_TARGETS): + @fail= 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//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + 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; \ + ($(am__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" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + 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 || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) + +clean-cscope: + -rm -f cscope.files + +cscope.files: clean-cscope cscopelist-recursive cscopelist + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$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 \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -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 $(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__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_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) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(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 \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { 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 config.h +installdirs: installdirs-recursive +installdirs-am: +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +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: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-cscope \ + clean-generic clean-libtool cscope cscopelist \ + cscopelist-recursive ctags ctags-recursive dist dist-all \ + dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ dist-xz \ + dist-zip distcheck distclean distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am + + +# 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: diff --git a/resources/3rdparty/glpk-4.53/NEWS b/resources/3rdparty/glpk-4.53/NEWS new file mode 100644 index 000000000..5bbadf21a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/NEWS @@ -0,0 +1,1741 @@ +GLPK 4.53 (release date: Feb 13, 2014) + + The API routine glp_read_mps was changed to remove free rows. + + A bug was fixed in the API routine glp_read_lp. Thanks to + Gabriel Hackebeil <gabehack@gmail.com> for bug report. + + The zlib compression library used by some GLPK routines and + included in the package was downgraded from 1.2.7 to 1.2.5 (as + in GLPK 4.50) because of addressability bugs on some 64-bit + platforms. Thanks to Carlo Baldassi <carlobaldassi@gmail.com> + for bug report. + + A bug was fixed in a routine that reads gzipped files. Thanks + to Achim Gaedke <achim.gaedke@gmail.com> for bug report. + + Two API routines glp_get_it_cnt and glp_set_it_cnt were added. + Thanks to Joey Rios <joeylrios@hotmail.com> for suggestion. + + All obsolete GLPK API routines (prefixed with lpx) were removed + from the package. + + A set of routines that simulate the old GLPK API (as defined + in 4.48) were added; see examples/oldapi/api/lpx.c. Thanks to + Jan Engelhardt <jengelh@inai.de> for suggestion. + + A namespace bug was fixed in the SQL table drive module. Thanks + to Dennis Schridde <devurandom@gmx.net> for bug report. + +GLPK 4.52.1 (release date: Jul 28, 2013) + + This is a bug-fix release. + + A version information bug in Makefile.am was fixed. Thanks to + Sebastien Villemot <sebastien@debian.org> for bug report. + +GLPK 4.52 (release date: Jul 18, 2013) + + The clique cut generator was essentially reimplemented, and now + it is able to process very large and/or dense conflict graphs. + + A simple rounding heuristic was added to the MIP optimizer. + + Some bugs were fixed in the proximity search heuristic routine. + Thanks to Giorgio Sartor <0gioker0@gmail.com>. + + New command-line option '--proxy [nnn]' was added to glpsol to + enable using the proximity search heuristic. + + A bug (incorrect processing of LI column indicator) was fixed + in the mps format reading routine. Thanks to Charles Brixko for + bug report. + +GLPK 4.51 (release date: Jun 19, 2013) + + Singleton and dense phases were implemented on computing + LU-factorization with Gaussian elimination. The singleton phase + is a feature that allows processing row and column singletons + on initial elimination steps more efficiently. The dense phase + is a feature used on final elimination steps when the active + submatrix becomes relatively dense. It significantly reduces + the time needed, especially if the active submatrix fits in CPU + cache, and improves numerical accuracy due to full pivoting. + + The API routine glp_adv_basis that constructs advanced initial + LP basis was replaced by an improved version, which (unlike the + old version) takes into account numerical values of constraint + coefficients. + + The proximity search heuristic for MIP was included in the GLPK + integer optimizer glp_intopt. On API level the heuristic can be + enabled by setting the parameter ps_heur in glp_iocp to GLP_ON. + This feature is also available in the solver glpsol through + command-line option '--proxy'. Many thanks to Giorgio Sartor + <0gioker0@gmail.com> for contribution. + + A bug was fixed that caused numerical instability in the FPUMP + heuristic. + +GLPK 4.50 (release date: May 24, 2013) + + A new version of LU-factorization routines were added. + Currently this version provides the same functionality as the + old one, however, the new version allows further improving. + + Old routines for FHV-factorization used to update the basis + factorization were replaced by a new version conforming to the + new version of LU-factorization. + + Some clarifications about using the name index routines were + added. Thanks to Xypron <xypron.glpk@gmx.de> for suggestion. + + Some typos were corrected in the MathProg language reference. + Thanks to Jeffrey Kantor <Kantor.1@nd.edu> for report. + + A serious bug (out-of-range indexing error) was *tentatively* + fixed in the routine glp_relax4. Unfortunatly, this bug is + inherited from the original Fortran version of the RELAX-IV + code (for details please see ChangeLog), and since the code is + very intricate, the bug is still under investigation. Thanks to + Sylvain Fournier for bug report. + +GLPK 4.49 (release date: Apr 16, 2013) + + The new API routine glp_mincost_relax4, which is a driver to + relaxation method of Bertsekas and Tseng (RELAX-IV), was added + to the package. RELAX-IV is a code for solving minimum cost + flow problems. On large instances it is 100-1000 times faster + than the standard primal simplex method. Prof. Bertsekas, the + author of the original RELAX-IV Fortran code, kindly permitted + to include a C translation of his code in GLPK under GPLv3. + + A bug (wrong dual feasibility test) was fixed in API routine + glp_warm_up. Thanks to David T. Price <dtprice@speakeasy.net> + for bug report. + + Obsolete API routine lpx_check_kkt was replaced by new routine + glp_check_kkt. + + IMPORTANT: All old API routines whose names begin with 'lpx_' + were removed from API level and NO MORE AVAILABLE. + +GLPK 4.48 (release date: Jan 28, 2013) + + This is a maintainer release. + + Some minor changes in API (glpk.h) were made. For details + please see ChangeLog. + + Some bugs/typos were fixed. Thanks to + Raniere Gaia Costa da Silva, + Heinrich Schuchardt <xypron.glpk@gmx.de>, and + Robbie Morrison <robbie@actrix.co.nz> for reports. + +GLPK 4.47 (release date: Sep 09, 2011) + + The new API routine glp_intfeas1 was added to the package. + This routine is a tentative implementation of the integer (0-1) + feasibility solver based on the CNF-SAT solver (which currently + is MiniSat). It may be used in the same way as glp_intopt to + find either any integer feasible solution or a solution, for + which the objective function is not worse than the specified + value. Detailed description of this routine can be found in the + document "CNF Satisfiability Problem", which is included in the + distribution (see doc/cnfsat.pdf). + + The following two options were added to glpsol: + + --minisat translate 0-1 feasibility problem to CNF-SAT + problem and solve it with glp_intfeas1/MiniSat + (if the problem instance is already in CNF-SAT + format, no translation is performed) + + --objbnd bound add inequality obj <= bound (minimization) or + obj >= bound (maximization) to 0-1 feasibility + problem (this option assumes --minisat) + + The paint-by-numbers puzzle model (pbn.mod) included in the + distribution is a nice example of the 0-1 feasibility problem, + which can be efficiently solved with glp_intfeas1/MiniSat. This + model along with a brief instruction (pbn.pdf) and benchmark + examples from <webpbn.com> encoded in GNU MathProg (*.dat) can + be found in subdirectory examples/pbn/. + + The glpsol lp/mip solver was modified to bypass postprocessing + of MathProg models if the solution reported is neither optimal + nor feasible. + + A minor bug in examples/Makefile.am was fixed to correctly + build glpk in a separate directory. Thanks to Marco Atzeri + <marco.atzeri@gmail.com> for bug report and patch. + +GLPK 4.46 (release date: Aug 09, 2011) + + The following new API routines were added: + + glp_read_cnfsat read CNF-SAT problem data in DIMACS format + glp_check_cnfsat check for CNF-SAT problem instance + glp_write_cnfsat write CNF-SAT problem data in DIMACS format + glp_minisat1 solve CNF-SAT problem instance with MiniSat + + The routine glp_minisat1 is a driver to MiniSat, a CNF-SAT + solver developed by Niklas Een and Niklas Sorensson, Chalmers + University of Technology, Sweden. This routine is similar to + the routine glp_intopt, however, it is intended to solve a 0-1 + programming problem instance, which is the MIP translation of + a CNF-SAT problem instance. + + Detailed description of these new API routines can be found in + the document "CNF Satisfiability Problem", which is included in + the distribution (see files doc/cnfsat.tex and doc/cnfsat.pdf). + + The following new glpsol command-line options were added: + + --cnf filename read CNF-SAT problem instance in DIMACS + format from filename and translate it to MIP + --wcnf filename write CNF-SAT problem instance in DIMACS + format to filename + --minisat solve CNF-SAT problem instance with MiniSat + solver + + The zlib compression library (version 1.2.5) was ANSIfied, + modified according to GLPK requirements and included in the + distribution as an external software module. Thus, now this + feature is platform independent. + + Some bugs were fixed in the SQL table driver. Thanks to Xypron + <xypron.glpk@gmx.de>. + +GLPK 4.45 (release date: Dec 05, 2010) + + This is a bug-fix release. + + Several bugs/typos were fixed. Thanks to + Xypron <xypron.glpk@gmx.de>, + Robbie Morrison <robbie@actrix.co.nz>, and + Ali Baharev <ali.baharev@gmail.com> for reports. + + Some glpk documents was re-formatted and merged into a single + document. Now the glpk documentation consists of the following + three main documents (all included in the distribution): + + GLPK: Reference Manual + + GLPK: Graph and Network Routines + + Modeling Language GNU MathProg: Language Reference + +GLPK 4.44 (release date: Jun 03, 2010) + + The following suffixes for variables and constraints were + implemented in the MathProg language: + + .lb (lower bound), + .ub (upper bound), + .status (status in the solution), + .val (primal value), and + .dual (dual value). + + Thanks to Xypron <xypron.glpk@gmx.de> for draft implementation + and testing. + + Now the MathProg language allows comment records (marked by + '#' in the very first position) in CSV data files read with the + table statements. Note that the comment records may appear only + in the beginning of a CSV data file. + + The API routine glp_cpp to solve the Critical Path Problem was + added and documented. + +GLPK 4.43 (release date: Feb 20, 2010) + + This is a maintainer release. + + `configure.ac' was changed to allow building the package under + Mac OS and Darwin with ODBC support. + Thanks to Xypron <xypron.glpk@gmx.de> for suggestions and Noli + Sicad <nsicad@gmail.com> for testing. + + The SQL table driver was improved to process NULL data. Thanks + to Xypron <xypron.glpk@gmx.de>. + + Some bugs were fixed in the LP/MIP preprocessor. + +GLPK 4.42 (release date: Jan 13, 2010) + + The following new API routines were added: + + glp_check_dup check for duplicate elements in sparse + matrix + glp_sort_matrix sort elements of the constraint matrix + glp_read_prob read problem data in GLPK format + glp_write_prob write problem data in GLPK format + glp_analyze_bound analyze active bound of non-basic variable + glp_analyze_coef analyze objective coefficient at basic + variable + glp_print_ranges print sensitivity analysis report (this + routine replaces lpx_print_sens_bnds and + makes it deprecated) + + For description of these new routines and the GLPK LP/MIP + format see a new edition of the reference manual included in + the distribution. (Chapter "Graph and network API routines" was + carried out from the main reference manual and included in the + distribution as a separate document.) + + The following new command-line options were added to the stand- + alone solver glpsol: + --glp filename read problem data in GLPK format + --wglp filename write problem data in GLPK format + --ranges filename print sensitivity analysis report (this + option replaces --bounds) + + Now all GLPK routines performing file I/O support special + filenames "/dev/stdin", "/dev/stdout", and "/dev/stderr", which + can be specified in the same way as regular filenames. This + feature is plaform-independent. + +GLPK 4.41 (release date: Dec 21, 2009) + + The following new API routies were added: + + glp_transform_row transform explicitly specified row + glp_transform_col transform explicitly specified column + glp_prim_rtest perform primal ratio test + glp_dual_rtest perform dual ratio test + + For description of these new routines see a new edition of the + reference manual included in the distribution. + + The following API routines are deprecated: lpx_transform_row, + lpx_transform_col, lpx_prim_ratio_test, lpx_dual_ratio_test. + + Some improvements were made in the MIP solver (glp_intopt). + + The SQL table driver used to read/write data in MathProg models + was changed to allow multiple arguments separated by semicolon + in SQL statements. Thanks to Xypron <xypron.glpk@gmx.de>. + + Two new options were added to the glpsol stand-alone solver: + --seed value (to initialize the pseudo-random number generator + used in MathProg models with specified value), and + --ini filename (to use a basis previously saved with -w option + as an initial basis on solving similar LP's). + + Two new MathProg example models were included. Thanks to + Nigel Galloway <nigel_galloway@operamail.com> and Noli Sicad + <nsicad@gmail.com> for contribution. + + Scripts to build GLPK with Microsoft Visual Studio 2010 for + both 32-bit and 64-bit Windows were included. Thanks to Xypron + <xypron.glpk@gmx.de> for contribution and testing. + +GLPK 4.40 (release date: Nov 03, 2009) + + The following new API routines were added: + + glp_del_vertices remove vertices from graph + glp_del_arc remove arc from graph + glp_wclique_exact find maximum weight clique with the exact + algorithm developed by Prof. P. Ostergard + glp_read_ccdata read graph in DIMACS clique/coloring + format + glp_write_ccdata write graph in DIMACS clique/coloring + format + + For description of these new routines see a new edition of the + reference manual included in the distribution. + + The hybrid pseudocost branching heuristic was included in the + MIP solver. It is available on API level (iocp.br_tech should + be set to GLP_BR_PCH) and in the stand-alone solver glpsol + (via the command-line option --pcost). This heuristic may be + useful on solving hard MIP instances. + + The branching heuristic by Driebeck and Tomlin (used in the + MIP solver by default) was changed to switch to branching on + most fractional variable if an lower bound of degradation of + the objective is close to zero for all branching candidates. + + A bug was fixed in the LP preprocessor (routine npp_empty_col). + Thanks to Stefan Vigerske <stefan@math.hu-berlin.de> for the + bug report. + + A bug was fixed and some improvements were made in the FPUMP + heuristic module. Thanks to Xypron <xypron.glpk@gmx.de>. + + A bug was fixed in the API routine glp_warm_up (dual + feasibility test was incorrect in maximization case). Thanks to + Uday Venkatadri <Uday.Venkatadri@dal.ca> for the bug report. + +GLPK 4.39 (release date: Jul 26, 2009) + + The following new API routines were added: + + glp_warm_up "warm up" LP basis + glp_set_vertex_name assign (change) vertex name + glp_create_v_index create vertex name index + glp_find_vertex find vertex by its name + glp_delete_v_index delete vertex name index + glp_read_asnprob read assignment problem data in DIMACS + format + glp_write_asnprob write assignment problem data in DIMACS + format + glp_check_asnprob check correctness of assignment problem + data + glp_asnprob_lp convert assignment problem to LP + glp_asnprob_okalg solve assignment problem with the + out-of-kilter algorithm + glp_asnprob_hall find bipartite matching of maxumum + cardinality with Hall's algorithm + + Also were added some API routines to read plain data files. + + The API routines glp_read_lp and glp_write_lp to read/write + files in CPLEX LP format were re-implemented. Now glp_write_lp + correctly writes double-bounded (ranged) rows by introducing + slack variables rather than by duplicating the rows. + + For description of these new routines see a new edition of the + reference manual included in the distribution. + + The 'xfree(NULL)' bug was fixed in the AMD routines. Thanks to + Niels Klitgord <niels@bu.edu> for bug report. + + The message "Crashing..." was changed to "Constructing initial + basis..." due to suggestion by Thomas Kahle <tom111@gmx.de>. + + Some typos were corrected in glpsol output messages. Thanks to + Xypron <xypron.glpk@gmx.de> for patch. + +GLPK 4.38 (release date: May 02, 2009) + + API routines glp_read_mps and glp_write_mps were improved. + + Some improvements were made in the dual simplex routines. + + Two external software modules AMD and COLAMD were included in + the distribution (for more details please see src/amd/README + and src/colamd/README). Now they are used in the interior-point + solver to reorder the matrix prior to Cholesky factorization. + + API routine glp_ipt_status may return two new statuses due to + changes in the routine glp_interior. For details please see the + reference manual included in the distribution. + + A minor bug was fixed in the graph/network routines. Thanks to + Nelson H. F. Beebe <beebe@math.utah.edu> for bug report. + +GLPK 4.37 (release date: Mar 29, 2009) + + The 0-1 Feasibility Pump heuristic was included in the GLPK + integer optimizer glp_intopt. On API level the heuristic can be + enabled by setting the parameter fp_heur in glp_iocp to GLP_ON. + This feature is also available in the solver glpsol through + command-line option '--fpump'. For more details please see the + reference manual included in the distribution. + + The following new API routines were added: + + glp_print_sol write basic solution in printable format + glp_print_ipt write interior-point solution in printable + format + glp_print_mip write MIP solution in printable format + glp_read_graph read (di)graph from plain text file + glp_write_graph write (di)graph to plain text file + glp_weak_comp find all weakly connected components + glp_strong_comp find all strongly connected components + + The following API routines are deprecated: lpx_print_sol, + lpx_print_ips, lpx_print_mip, lpx_print_prob (the latter is + equivalent to glp_write_lp). + + A bug was fixed in the interior-point solver (glp_interior) to + correctly compute dual solution components when the problem is + scaled. + + The files configure.ac and Makefile.am were changed: + (a) to allow using autoreconf/autoheader; + (b) to allow building the package in a directory other than its + source directory. + Thanks to Marco Atzeri <marco_atzeri@yahoo.it> for bug report. + + An example model in the GNU MathProg language was added. + Thanks to Larry D'Agostino <Larry.D'Agostino@gmacrescap.com> for + contribution. + +GLPK 4.36 (release date: Feb 06, 2009) + + The following new API routines were added to the package: + + glp_mincost_okalg find minimum-cost flow with out-of-kilter + algorithm + glp_maxflow_ffalg find maximal flow with Ford-Fulkerson + algorithm + + For detailed description of these new routines and related data + structures see chapter "Graph and Network API Routines" in a new + edition of the reference manual included in the distribution. + + The following two new command-line options were added to the + solver glpsol: + + --mincost read min-cost flow data in DIMACS format + --maxflow read maximum flow data in DIMACS format + + Duplicate symbols in the header glpk.h were removed to allow + using swig. + Thanks to Kelly Westbrooks <kellywestbrooks@yahoo.com> and + Nigel Galloway <nigel_galloway@operamail.com> for suggestion. + + A minor defect was fixed in the routine glp_write_lp. + Thanks to Sebastien Briais <sbriais@free.fr> for bug report. + + A minor bug was fixed in the SQL module. + Thanks to Xypron <xypron.glpk@gmx.de> for patch. + + Some new example models in the GNU MathProg modeling language + were added. Thanks to Sebastian Nowozin <nowozin@gmail.com> and + Nigel Galloway <nigel_galloway@operamail.com> for contribution. + +GLPK 4.35 (release date: Jan 09, 2009) + + The following new API routines were added to the package: + + glp_create_graph create graph + glp_set_graph_name assign (change) graph name + glp_add_vertices add new vertices to graph + glp_add_arc add new arc to graph + glp_erase_graph erase graph content + glp_delete_graph delete graph + glp_read_mincost read minimum cost flow problem data in + DIMACS format + glp_write_mincost write minimum cost flow problem data in + DIMACS format + glp_mincost_lp convert minimum cost flow problem to LP + glp_netgen Klingman's network problem generator + glp_gridgen grid-like network problem generator + glp_read_maxflow read maximum flow problem data in DIMACS + format + glp_write_maxflow write maximum flow problem data in DIMACS + format + glp_maxflow_lp convert maximum flow problem to LP + glp_rmfgen Goldfarb's maximum flow problem generator + + For detailed description of these new routines and related data + structures see chapter "Graph and Network API Routines" in a new + edition of the reference manual included in the distribution. + + A minor change were made in the internal routine xputc. Thanks + to Luiz Bettoni <bettoni@cpgei.ct.utfpr.edu.br> for suggestion. + + A minor bug was fixed in the internal routine mpl_fn_time2str. + Thanks to Stefan Vigerske <stefan@vigerske.de> for bug report. + +GLPK 4.34 (release date: Dec 04, 2008) + + The GNU MathProg modeling language was supplemented with three + new built-in functions: + + gmtime obtaining current calendar time + str2time converting character string to calendar time + time2str converting calendar time to character string + + (Thanks to Xypron <xypron.glpk@gmx.de>.) + + For detailed description of these functions see Appendix A in + the document "Modeling Language GNU MathProg", a new edition of + which was included in the distribution. + + A bug was fixed in the MIP solver. Thanks to Nigel Galloway + <nigel_galloway@operamail.com> for bug report. + + A new makefile was added to build the GLPK DLL with Microsoft + Visual Studio Express 2008 for 64-bit Windows. Thanks to Xypron + <xypron.glpk@gmx.de> for contribution and testing. + +GLPK 4.33 (release date: Oct 30, 2008) + + The following new API routines were added to the package: + glp_copy_prob copy problem object content + glp_exact solve LP in exact arithmetic + (makes lpx_exact deprecated) + glp_get_unbnd_ray determine variable causing unboundedness + (makes lpx_get_ray_info deprecated) + glp_interior solve LP with interior-point method + (makes lpx_interior deprecated) + + The following new API routines for processing models written in + the GNU Mathprog language were added to the package: + glp_mpl_alloc_wksp allocate the translator workspace + glp_mpl_read_model read and translate model section + glp_mpl_read_data read and translate data section + glp_mpl_generate generate the model + glp_mpl_build_prob build LP/MIP instance from the model + glp_mpl_postsolve postsolve the model + glp_mpl_free_wksp deallocate the translator workspace + (These routines make lpx_read_model deprecated.) + + For description of all these new API routines see the reference + manual included in the distribution. + + A crude implementation of CPLEX-like interface to GLPK API was + added to the package. Currently it allows using GLPK as a core + LP solver for Concorde, a well known computer code for solving + the symmetric TSP. For details see examples/cplex/README. + + Some bugs were fixed in the SQL table driver. Thanks to Xypron + <xypron.glpk@gmx.de>. + +GLPK 4.32 (release date: Oct 03, 2008) + + The following new features were included in the MIP solver + (the API routine glp_intopt): + + * MIP presolver + * mixed cover cut generator + * clique cut generator + * Euclidean reduction of the objective value + + Due to changes the routine glp_intopt may additionally return + GLP_ENOPFS, GLP_ENODFS, and GLP_EMIPGAP. + + The API routines lpx_integer are lpx_intopt are deprecated, + since they are completely superseded by glp_intopt. + + The following new branch-and-cut API routines were added: + glp_ios_row_attr determine additional row attributes + glp_ios_pool_size determine current size of the cut pool + glp_ios_add_row add constraint to the cut pool + glp_ios_del_row delete constraint from the cut pool + glp_ios_clear_pool delete all constraints from the cut pool + + For description of these new routines see the reference manual + included in the distribution. + + The stand-alone solver glpsol was changed to allow multiple + data files. + + A new edition of the supplement "Using Data Tables in the GNU + MathProg Modeling Language" was included. + + As usual, some bugs were fixed (in the MathProg translator). + Thanks to Xypron <xypron.glpk@gmx.de>. + +GLPK 4.31 (release date: Sep 02, 2008) + + The core LP solver based on the dual simplex method was + re-implemented and now it provides both phases I and II. + + The following new API routines were added: + glp_scale_prob automatic scaling of problem data + glp_std_basis construct standard initial LP basis + glp_adv_basis construct advanced initial LP basis + glp_cpx_basis construct Bixby's initial LP basis + + For description of these new routines see the reference manual + included in the distribution. + + The following API routines are deprecated: + lpx_scale_prob, lpx_std_basis, lpx_adv_basis, lpx_cpx_basis. + + Necessary changes were made in memory allocation routines to + resolve portability issues for 64-bit platforms. + + New version of the routine lpx_write_pb to write problem data + in OPB (pseudo boolean format) was added to the package. Thanks + to Oscar Gustafsson <oscarg@isy.liu.se> for the contribution. + + Two new makefiles were added to build the package for 32- and + 64-bit Windows with Microsoft Visual Studio Express 2008. + Thanks to Heinrich Schuchardt <heinrich.schuchardt@gmx.de> (aka + Xypron) for the contribution and testing. + + Two new makefiles were added to build the package with Digital + Mars C/C++ 8.50 and Open Watcom C/C++ 1.6 (for 32-bit Windows). + +GLPK 4.30 (release date: Aug 13, 2008) + + The core LP solver based on the primal simplex method was + re-implemented to allow its further improvements. Currently the + new version provides the same features as the old one, however, + it is a bit faster and more numerically stable. + + Some changes were made in the MathProg translator to allow <, + <=, >=, and > on comparing symbolic values. Thanks to Heinrich + Schuchardt <heinrich.schuchardt@gmx.de> for patches. + + Internal routine set_d_eps in the exact LP solver was changed + to prevent approximation errors in case of integral data. + Thanks to Markus Pilz <pilz@cs.uni-bonn.de> for bug report. + +GLPK 4.29 (release date: Jul 06, 2008) + + The configure script was changed to disable all optional + features by default. For details please see file INSTALL. + + The following new API routines were added: + glp_erase_prob erase problem object content + glp_read_mps read problem data in MPS format + glp_write_mps write problem data in MPS format + glp_read_lp read problem data in CPLEX LP format + glp_write_lp write problem data in CPLEX LP format + + For description of these new routines see the reference manual + included in the distribution. + + The following API routines are deprecated: + lpx_read_mps, lpx_read_freemps, lpx_write_mps, + lpx_write_freemps, lpx_read_cpxlp, and lpx_write_cpxlp. + + Two bugs were fixed. Thanks to + Anne-Laurence Putz <anne-laurence.putz@eurodecision.com> and + Xypron <xypron.glpk@gmx.de> for bug report. + +GLPK 4.28 (release date: Mar 25, 2008) + + The iODBC and MySQL table drivers, which allows transmitting + data between MathProg model objects and relational databases, + were re-implemented to replace a static linking by a dynamic + linking to corresponding shared libraries. + Many thanks to Heinrich Schuchardt <heinrich.schuchardt@gmx.de> + for the contribution, Rafael Laboissiere <rafael@debian.org> + for useful advices concerning the shared library support under + GNU/Linux, and Vijay Patil <vijay.patil@gmail.com> for testing + this feature under Windows XP. + + A new optional feature was added to the package. This feature + is based on the zlib data compression library and allows GLPK + API routines and the stand-alone solver to read and write + compressed data files performing compression/decompression "on + the fly" (compressed data files are recognized by suffix `.gz' + in the file name). It may be useful in case of large MPS files + to save the disk space (up to ten times). + + The `configure' script was re-implemented. Now it supports the + following specific options: + + --with-gmp Enable using the GNU MP bignum library + --without-gmp Disable using the GNU MP bignum library + --with-zlib Enable using the zlib data compression + library + --without-zlib Disable using the zlib data compression + library + --enable-dl Enable shared library support (auto check) + --enable-dl=ltdl Enable shared library support (GNU) + --enable-dl=dlfcn Enable shared library support (POSIX) + --disable-dl Disable shared library support + --enable-odbc Enable using ODBC table driver + --disable-odbc Disable using ODBC table driver + --enable-mysql Enable using MySQL table driver + --disable-mysql Disable using MySQL table driver + + For more details please see file INSTALL. + +GLPK 4.27 (release date: Mar 02, 2008) + + Three new table drivers were added to the MathProg translator: + + xBASE built-in table driver, which allows reading and writing + data in .dbf format (only C and N fields are supported); + + MySQL table driver, which provides connection to a MySQL + database; + + iODBC table driver, which provides connection to a database + through ODBC. + + The MySQL and iODBC table drivers were contributed to GLPK by + Heinrich Schuchardt <heinrich.schuchardt@gmx.de>. + + The table driver is a program module which allows transmitting + data between MathProg model objects and external data tables. + + For detailed description of the table statement and table + drivers see the document "Using Data Tables in the GNU MathProg + Modeling Language" (file doc/tables.txt) included in the + distribution. Some examples which demonstrate using MySQL and + iODBC table drivers can be found in subdirectory examples/sql. + +GLPK 4.26 (release date: Feb 17, 2008) + + The table statement was implemented in the GNU MathProg + modeling language. This new feature allows reading data from + external tables into model objects such as sets and parameters + as well as writing results of computations to external tables. + + A table is a (unordered) set of records, where each record + consists of the same number of fields, and each field is + provided with a unique symbolic name called the field name. + + Currently the GLPK package has the only built-in table driver, + which supports tables in the CSV (comma-separated values) file + format. This format is very simple and supported by almost all + spreadsheets and database management systems. + + Detailed description of the table statement and CSV format can + be found in file doc/tables.txt, included in the distribution. + +GLPK 4.25 (release date: Dec 19, 2007) + + A tentative implementation of Gomory's mixed integer cuts was + included in the branch-and-cut solver. To enable generating + Gomory's cuts the control parameter gmi_cuts passed to the + routine glp_intopt should be set to GLP_ON. This feature is + also available in the solver glpsol through command-line option + '--gomory'. For more details please see the reference manual + included in the distribution. + +GLPK 4.24 (release date: Nov 21, 2007) + + A tentative implementation of MIR (mixed integer rounding) cuts + was included in the MIP solver. To enable generating MIR cuts + the control parameter mir_cuts passed to the routine glp_intopt + should be set to GLP_ON. This feature is also available in the + stand-alone solver glpsol via command-line option '--mir'. For + more details please see the reference manual included in the + distribution. + + The implementation is mainly based on the following two papers: + + 1. H. Marchand and L. A. Wolsey. Aggregation and mixed integer + rounding to solve MIPs. CORE discussion paper 9839, CORE, + Universite catholique de Louvain, June 1998. + + 2. G. Andreello, A. Caprara, and M. Fischetti. Embedding cuts + in a Branch&Cut framework. Preliminary draft, October 2003. + + MIR cuts can be generated on any level of the search tree that + makes the GLPK MIP solver to be a real branch-and-cut solver. + + A bug was fixed in the routine lpx_write_cpxlp. If a variable + x has upper bound and no lower bound, it should appear in the + bounds section as "-inf <= x <= u", not as "x <= u". Thanks to + Enric Rodriguez <erodri@lsi.upc.edu> for the bug report. + +GLPK 4.23 (release date: Oct 28, 2007) + + The following new API routines were added: + + glp_read_sol read basic solution from text file + glp_write_sol write basic solution to text file + glp_read_ipt read interior-point solution from text file + glp_write_ipt write interior-point solution to text file + glp_read_mip read MIP solution from text file + glp_write_mip write MIP solution to text file + + For description of these routines and corresponding file + formats see Chapter "API Routines", Section "Utility routines" + in the reference manual included in the distribution. + + Advanced API routine glp_free_env was added. It may be used by + the application program to free all resources allocated by GLPK + routines. + + The following three new command-line options were added to the + solver glpsol: + + --mipgap tol set relative MIP gap tolerance + -r filename read solution from filename + -w filename write solution to filename + +GLPK 4.22 (release date: Sep 19, 2007) + + This is a maintainer release. + + A bug was fixed in the MIP preprocessor (ios_preprocess_node). + Thanks to Roberto Bagnara <bagnara@cs.unipr.it> (Department of + Mathematics, University of Parma, Italy) for the bug report. + + A bug was fixed in the MIP preprocessor (col_implied_bounds), + due to which constraint coefficients with small magnitude could + lead to wrong implied bounds of structural variables. + + A similar bug was fixed in the routine reduce_bounds. + + A bug was fixed in the routines glp_set_mat_row and + glp_set_mat_col. (The bug appeared due to incorrect removing + zero elements from the row/column lists.) + + A bug was fixed in the API routines lpx_read_mps and + lpx_read_freemps, due to which bounds of type LI specified in + BOUNDS section were incorrectly processed. + + A call to standard function vsprintf was replaced by a call to + vsnprintf for security reasons. Many thanks to Peter T. Breuer + <ptb@inv.it.uc3m.es> and Rafael Laboissiere <rafael@debian.org>. + +GLPK 4.21 (release date: Aug 28, 2007) + + Additional reasons for calling the callback routine used in the + MIP solver (glp_intopt) were introduced. Currently the following + reasons are supported: + + * request for subproblem selection + * request for preprocessing + * request for row generation + * request for heuristic solution + * request for cut generation + * request for branching + * better integer solution found + + A basic preprocessing component used to improve subproblem + formulations by tightening bounds of variables was included in + the MIP solver. Depending on the control parameter pp_tech + passed to the routine glp_intopt the preprocessing can be + performed either on the root level or on all levels (default) + or can be disabled. + + Backtracking heuristic used by default in the MIP solver was + changed to the "best local bound". + + For more details see Chapter "Advanced API routines", Section + "Branch-and-bound interface routines" in a new edition of the + reference manual included in the distribution. + +GLPK 4.20 (release date: Jul 26, 2007) + + API routine lpx_integer was replaced by API routine glp_intopt, + which provides equivalent functionality and additionally allows + the application to control the solution process by means of the + user-written callback routine, which is called by the solver at + various points of the branch-and-bound algorithm. Besides, the + new MIP solver allows generating "lazy" constraints and cutting + planes on all levels of the branch-and-bound tree, not only on + the root level. The routine lpx_integer is also still available + for the backward compatibility. + + The following new advanced API routines, which may be called + from the B&B callback routine, were included in the package: + + glp_ios_reason determine reason for calling callback + routine + glp_ios_get_prob access the problem object + glp_ios_tree_size determine size of the branch-and-bound tree + glp_ios_curr_node determine current active subproblem + glp_ios_next_node determine next active subproblem + glp_ios_prev_node determine previous active subproblem + glp_ios_up_node determine parent subproblem + glp_ios_node_level determine subproblem level + glp_ios_node_bound determine subproblem local bound + glp_ios_mip_gap compute relative MIP gap + glp_ios_heur_sol provide solution found by heuristic + glp_ios_terminate terminate the solution process + + For description of these routines see Chapter "Advanced API + routines", Section "Branch-and-bound interface routines" in a + new edition of the reference manual, which was included in the + distribution. + + Old version of the integer optimization suite (IOS) as well as + TSP solver tspsol based on it are no longer supported and were + removed from the package. + + A minor error in the MIP presolver was fixed; thanks to Graham + Rockwell <bionomicron@gmail.com> for the bug report. + +GLPK 4.19 (release date: Jul 05, 2007) + + The principal change is upgrading to GPLv3. + + A serious bug in the routine glp_del_cols was fixed; thanks to + Cedric[FR] <fox2113@wanadoo.fr> for the bug report. The bug + appeared because on deleting non-basic columns the basis header + remained valid, however, contained invalid (old) column ordinal + numbers. + + A new advanced API routine glp_mem_limit was added. + + The case GLP_EBOUND was added to the routine lpx_simplex. + Thanks to Cameron Kellough <Cameron.Kellough@sri.com> for the + bug report. + + An API routine lpx_write_pb to write the problem instance in + OPB (pseudo boolean) format format was added. Thanks to Oscar + Gustafsson <oscarg@isy.liu.se> for the contribution. + + Two new options --wpb and --wnpb were added to glpsol to write + the problem instance in OPB format. + +GLPK 4.18 (release date: Jun 25, 2007) + + The following new API routines were added: + + glp_set_rii set (change) row scale factor + glp_set_sjj set (change) column scale factor + glp_get_rii retrieve row scale factor + glp_get_sjj retrieve column scale factor + glp_simplex solve LP problem with the simplex method + (this routine replaces lpx_simplex, which is + also available for backward compatibility) + glp_init_smcp initialize simplex method control params + glp_bf_exists check if the basis factorization exists + glp_factorize compute the basis factorization + glp_bf_updated check if the basis factorization has been + updated + glp_get_bfcp retrieve basis factorization control params + glp_set_bfcp change basis factorization control params + glp_get_bhead retrieve the basis header information + glp_get_row_bind retrieve row index in the basis header + glp_get_col_bind retrieve column index in the basis header + glp_ftran perform forward transformation + glp_btran perform backward transformation + + For description of all these routines see a new edition of the + reference manual included in the distribution. + + Type names ulong_t and uldiv_t were changed to glp_ulong and + glp_uldiv to avoid conflicts with standard type names on some + platforms. Thanks to Boris Wirtz <Boris.Wirtz@uni-oldenburg.de> + for the bug report. + + Some new examples in the MathProg language were added. Thanks + to Sebastian Nowozin <nowozin@gmail.com>. + +GLPK 4.17 (release date: May 26, 2007) + + API routines glp_set_mat_row, glp_set_mat_col, and glp_load_mat + were modified to allow zero constraint coefficients (which are + not stored in the constraint matrix). Note that constraint + coefficients with duplicate row/column indices are not allowed. + + Another form of LP basis factorization was implemented in the + package. It is based on LU-factorization of an initial basis + and Schur complement to reflect changes in the basis. Currently + the implementation is incomplete and provides only updating the + factorization on replacing a column of the basis matrix. On API + level the user can set the control parameter LPX_K_BFTYPE to + choose between the folloiwng forms of LP basis factorization to + be used in the simplex method routines: + 1) LU + Forrest-Tomlin update; + 2) LU + Schur complement + Bartels-Golub update; + 3) LU + Schur complement + Givens rotation update. + The GLPK implementation is similar to LUSOL/LUMOD developed by + Michael A. Saunders. + + The user can choose the form of LP basis factorzation used by + the simplex method routines by specifying the folloiwng options + of glpsol: --luf, --cbg, --cgr. + +GLPK 4.16 (release date: May 05, 2007) + + A number of basic GLPK API routines, which now are in the + stable stable, were renamed to be prefixed with 'glp_'. Note + that all these routines are available via their old names + prefixed with 'lpx_' that keeps the downward compatibility with + older versions of the package. + + Three new GLPK API routines were added to the package: + glp_version, glp_term_hook, and glp_mem_usage; for more details + see a new edition of the GLPK reference manual included in the + distribution. The routine glp_version reports the actual version + of the GLPK library and also can be used (along with the header + glpk.h) in Autotools specification files to check if the GLPK + library has been installed. + + The header glpk.h was changed to conform to C++ environment. + +GLPK 4.15 (release date: Feb 18, 2007) + + Autotools specification files (configure.ac, Makefile.am) were + changed to use GNU Libtool. This allows building the static as + well as shared GLPK library. + +GLPK 4.14 (release date: Feb 05, 2007) + + Now GLPK conforms to ILP32, LLP64, and LP64 programming models + (the latter seems to be the ultimate choice regarding 64-bit + architectures). Note that GLPK itself is a 32-bit application, + and the conformity only means that the package works correctly + on all these arenae. Nevertheless, on 64-bit platforms it is + possible to use more than 4GB of memory, if necessary. + +GLPK 4.13 (release date: Nov 13, 2006) + + A tentative implementation of the "exact" simplex method based + on bignum (rational) arithmetic was included in the package. + + On API level this new feature is available through the routine + lpx_exact, which is similar to the routine lpx_simplex. + + In the solver glpsol this feature is available through two new + command-line options: --exact and --xcheck. If the '--exact' + option is specified, glpsol solves LP instance using the exact + simplex method; in case of MIP it is used to obtain optimal + solution of LP relaxation. If the --xcheck option is specified, + LP instance (or LP relaxation) is solved using the standard + (floating-point) simplex method, however, then glpsol calls the + exact simplex routine to make sure that the final LP basis is + exactly optimal, and if it is not, to perform some additional + simplex iterations in exact arithmetic. + +GLPK 4.12 (release date: Nov 08, 2006) + + A tentative implementation of some simplex method routines + based on exact (bignum) arithmetic was included in the package. + Currently these routines provide computing LU-factorization of + the basis matrix and computing components of basic solution. + + These routines were used to implement a routine, which checks + primal and dual feasibility of basic solution exactly, i.e. in + rational numbers, without round-off errors. In glpsol this + feature is available through the command-line option --xcheck. + + GLPK has its own low-level routines implementing operations on + integer and rational numbers that makes it independent on other + software packages. However, to attain a much better performance + it is highly recommended to install (before configuring GLPK) + the GNU Multiple Precision Arithmetic Library (GMP). Using GMP + makes computations 100-200 times faster. + +GLPK 4.11 (release date: Jul 25, 2006) + + Three new built-in functions in the modeling language were + implemented: card (cardinality of set), length (length of + character string), and substr (substring of character string). + Another improvement concerns the printf statement which now + allows redirecting its output to a specified file. These new + features are illustrated in example models crypto.mod and + graph.mod included in the distribution. For more details see + the document "Modeling Language GNU MathProg". + + Four batch files (along with corresponding makefiles) were + included in the distribution to simplify building GLPK under + MS Windows; see them in subdirectory 'w32'. + +GLPK 4.10 (release date: May 11, 2006) + + Cutting planes of two new classes were implemented: mixed cover + cuts and clique cuts. On API level this feature can be enabled + by setting control parameter LPX_K_USECUTS passed to the routine + lpx_intopt. In glpsol this feature is available through the + command-line options --cover and --clique. For more details see + the reference manual. + + Now the routines lpx_read_mps and lpx_read_freemps support LI + bound type. It is similar to LO, however, indicates the column + as of integer kind. + +GLPK 4.9 (release date: Jan 17, 2006) + + An advanced MIP solver was implemented. It includes: + + - basic presolving technique (removing free, singleton and + redundant rows, improving bounds of columns, removing fixed + columns, reducing constraint coefficents); + + - generating cutting planes to improve LP relaxation (currently + only Gomory's mixed integer cuts are implemented); + + - using the branch-and-bound method to solve resultant MIP; + + - recovering solution of the original MIP. + + The solver is available on API level via the routine lpx_intopt + (see the reference manual). It is similar to the routine + lpx_integer, however, does not require initial solution of LP + relaxation. + + The solver is also available in the command-line utility glpsol + via two options: --intopt (only presolving) and --cuts (assumes + --intopt plus generating cuts). + + Note that efficiency of the MIP solver strongly depends on the + internal structure of the problem to be solved. For some hard + instances it is very efficient, but for other instances it may + be significantly worse than the standard branch-and-bound. + + For some comparative benchmarks see doc/bench1.txt. + + Well, what else... + + Three built-in functions were added to MathProg: sin, cos, and + atan (the latter allows one or two arguments). + + Some bugs were fixed. + + Several new examples in MathProg were included: color.mod + (graph coloring problem), tsp.mod (traveling salesman problem), + and pbn.mod (paint-by-numbers puzzle). + +GLPK 4.8 (release date: Jan 12, 2005) + + Core simplex method and interior-point method routines were + re-implemented and now they use a new, "storage-by-rows" sparse + matrix format (unlike previous versions where linked lists were + used to represent sparse matrices). For details see ChangeLog. + + Also a minor bug was fixed in API routine lpx_read_cpxlp. + +GLPK 4.7 (release date: Aug 23, 2004) + + Now GLPK supports free MPS format. Two new API routines + lpx_read_freemps (to read problem data in free MPS format) and + lpx_write_freemps (to write problem data in free MPS format) + were added. This feature is also available in the solver glpsol + via new command-line options --freemps and --wfreemps. For more + details see the GLPK reference manual. + + API routines lpx_read_cpxlp and lpx_write_cpxlp for reading and + writing problem data in CPLEX LP format were re-implemented to + allow long symbolic names (up to 255 characters). + + The following three modules were temporarily removed from the + GLPK distribution due to licensing problems: DELI (an interface + module to Delphi), GLPKMEX (an interface module to Matlab), and + JNI (an interface module to Java). + +GLPK 4.6 (release date: Aug 04, 2004) + + Three new statements were implemented in the GNU MathProg + language: solve, printf, and for. Their detailed description can + be found in the GLPK documentation included in the distribution. + (See also a sample model, examples/queens.mod, which illustrates + using these new statements.) + + Two new API routines were added to the package: lpx_read_prob + and lpx_write_prob. They allow reading/writing problem data in + GNU LP low-level text format. + + Three new command-line options were implemented in the LP/MIP + solver glpsol: --glp (to read problem data in GNU LP format), + --wglp (to write problem data in GNU LP format), and --name (to + change problem name). Now glpsol also supports processing models + where the new statements (see above) are used. + + A new version of GLPKMEX, a Matlab MEX interface to GLPK, was + included. For more details see contrib/glpkmex/ChangeLog. + +GLPK 4.5 (release date: Jul 19, 2004) + + The branch-and-bound solver was completely re-implemented. + + Some modifications were made in memory allocation routines that + allows using the package on 64-bit platforms. + + For more details see ChangeLog. + +GLPK 4.4 (release date: Jan 17, 2004) + + All API routines were re-implemented using new data structures. + The new implementation provides the same specifications and + functionality of API routines as the old one, however, it has + some important advantages, in particular: + * linked lists are used everywhere that allows creating and + modifying the problem object as efficiently as possible + * all data stored in the problem object are non-scaled (even if + the internal scaling is used) that prevents distortion of the + original problem data + * solution components obtained by the solver remain available + even if the problem object has been modified + * no solver-specific data are used in the new data structures + that allows attaching any external lp/mip solver using GLPK + API as an uniform interface + Note that some API routines became obsolete being replaced by + new, more convenient routines. These obsolete routines are kept + for backward compatibility, however, they will be removed in + the future. For more details please see ChangeLog and the GLPK + Reference Manual. + + New edition of the GLPK Reference Manual was included in the + distribution. + + GLPKMEX, a Matlab MEX interface to GLPK package, contributed by + Nicolo Giorgetti <giorgetti@dii.unisi.it> was included in the + distribution. + + GLPK FAQ contributed by Harley Mackenzie <hjm@bigpond.com> was + included in the distribution. + +GLPK 4.3 (release date: Dec 12, 2003) + + The bug, due to which the standard math library is not linked + on building the package on some platforms, was fixed. + + The following new built-in functions were added to the MathProg + language: round, trunc, Irand224, Uniform01, Uniform, Normal01, + Normal. For details see the language description. + + The MathProg syntax was changed to allow writing 'subj to' that + means 'subject to'. + + The new api routine lpx_get_ray_info was added. It is intended + to determine which (non-basic) variable causes unboundness. For + details see the reference manual. + + The module glpmps.c was changed to avoid compilation errors on + building the package on Mac OS X. + + Several typos was fixed and some new material was added to the + GLPK documentation. + +GLPK 4.2 (release date: Nov 14, 2003) + + A preliminary implementation of the Integer Optimization Suite + (IOS) was included in the package. The Branch-and-Cut Framework + being completely superseded by IOS was removed from the package. + + New API routine lpx_print_sens_bnds intended for bounds + sensitivity analysis was contributed to GLPK by Brady Hunsaker + <hunsaker@engr.pitt.edu>. This function is also available in + the solver glpsol (via command-line option --bounds). + + An improved version of GLPK JNI (Java Native Interface) was + contributed by Chris Rosebrugh <cpr@pobox.com>. + + GLPK DELI (Delphi Interface) was contributed by Ivo van Baren + <i.van.baren@freeler.nl>. + + Several makefiles were added to allow compiling GLPK on some + non-GNU 32-bit platforms: + * Windows single-threaded static library, Visual C++ 6.0 + * Windows multi-threaded dynamic library, Visual C++ 6.0 + * Windows single-threaded static library, Borland C++ 5.2 + * DOS single-threaded static library, Digital Mars C++ 7.50 + + And, of course, some bugs were fixed. + + For more details see ChangeLog. + +GLPK 4.1 (release date: Aug 23, 2003) + + Some improvements were made in the lp/mip solver routines and + several bugs were fixed in the model translator. + + For more details see ChangeLog. + +GLPK 4.0 (release date: May 06, 2003) + + Now GLPK supports the GNU MathProg modeling language, which is + a subset of the AMPL modeling language. + + The document "GLPK: Modeling Language GNU MathProg" included in + the distribution is a complete description of GNU MathProg. (See + the files lang.latex, lang.dvi, and lang.ps in the subdirectory + 'doc'. See also some examples in the subdirectory 'sample'.) + + New version of the solver glpsol, which supports models written + in GNU MathProg, was implemented. (Brief instructions how to use + glpsol can be found in the GNU MathProg documentation.) + + The GLPK/L modeling language is no more supported. The reason is + that GNU MathProg being much more powerful completely supersedes + all features of GLPK/L. + +GLPK 3.3 (release date: Mar 25, 2003) + + LP PRESOLVER + ------------ + + Now the routine lpx_simplex (which is a driver to the simplex + method for solving LP) is provided with the built-in LP + presolver, which is a program that transforms the original LP + problem to an equivalent LP problem, which may be easier for + solving with the simplex method than the original one. Once the + transformed LP has been solver, the presolver transforms its + basic solution back to a corresponding basic solution of the + original problem. For details about this feature please see the + GLPK reference manual. + + Currently the LP presolver implements the following features: + * removing empty rows; + * removing empty columns; + * removing free rows; + * removing fixed columns; + * removing row singletons, which have the form of equations; + * removing row singletons, which have the form of inequalities; + * removing column singletons, which are implied slack variables; + * fixing and removing column singletons, which are implied free + variables; + * removing forcing rows that involves fixing and removing the + corresponding columns; + * checking for primal and dual infeasibilities. + + The LP presolver is also used by default in the stand-alone + program glpsol. In order *not* to use it, the option --nopresol + should be specified in the command-line. + + CHANGES IN GLPK/L + ----------------- + + The syntax and semantics of the GLPK/L modeling language was + changed to allow declaration of "interval" sets. This means that + now the user can declare a set, for example, as: + + set task = [8:11]; + + that is exactly equivalent to the following declaration: + + set task = (task_8, task_9, task_10, task_11); + + For details see the language description. + + JAVA INTERFACE + -------------- + + Now GLPK includes the package GLPK JNI (Java Native Interface) + that implements Java binding for GLPK. It allows Java programs + to utilize GLPK in solving LP and MIP problems. For details see + a brief user's guide in the subdirectory contrib/java-binding. + This package was developed and programmed by Yuri Victorovich + <yuri@gjt.org>, who contributed it to GLPK. + +GLPK 3.2.4 (release date: Feb 18, 2003) + + This is a bug-fix release. For details see ChangeLog. + +GLPK 3.2.3 (release date: Nov 11, 2002) + + A new implementation of the api routine lpx_integer which now + is based on the b&b driver (which is based on the implicit + enumeration suite) was included in the package. This new + implementation has exactly the same functionality as the old + version, so all changes are transparent to the api user. + + Four new api routines were included in the package: + lpx_check_kkt checks Karush-Kuhn-Tucker optmality conditions; + lpx_read_bas reads predifined basis in MPS format; + lpx_write_bas writes current basis in MPS format; + lpx_write_lpt writes problem data in CPLEX LP format. + + Also other minor improvements were made (for details see the + file 'ChangeLog'). + +GLPK 3.2.2 (release date: Oct 14, 2002) + + The api routine lpx_read_lpt was included in the package. It + is similar to the routine lpx_read_mps and intended to read + LP/MIP data prepared in CPLEX LP format. Description of this + format is given in the GLPK reference manual, a new edition of + which was also included in the distribution (see the files + 'refman.latex', 'refman.dvi', 'refman.ps' in the subdirectory + 'doc'). In order to use data files in CPLEX LP format with the + solver glpsol the option '--lpt' should be specified in the + command line. + + Several bugs were fixed and some minor improvements were made + (for details see the file 'ChangeLog'). + +GLPK 3.2.1 (release date: Aug 12, 2002) + + Now GLPK includes a preliminary implementation of the + branch-and-cut framework, which is a set of data structures and + routines intended for developing branch-and-cut methods for + solving mixed-integer and combinatorial optimization problems. + + Detailed decsription of the branch-and-cut framework is given in + the document "GLPK: A Preliminary Implementation of the + Branch-And-Cut Framework" included in the distribution (see the + file 'brcut.txt' in the subdirectory 'doc'). + + In order to illustrate how the GLPK branch-and-cut framework + can be used for solving a particular optimization problem there + is an example included in the package. This is a stand-alone + program, TSPSOL, which is intended for solving to optimality the + symmetric Traveling Salesman Problem (TSP), a classical problem + of the combinatorial optimization (see the file 'tspsol.c' in + the subdirectory 'sample'). + +GLPK 3.2 (release date: Jul 15, 2002) + + New edition of the document "GLPK: Reference Manual" was + included (see the files 'refman.latex', 'refman.dvi', and + 'refman.ps' in the subdirectory 'doc'). + + New edition of the document "GLPK: Modeling Language GLPK/L" was + included (see the files 'lang.latex', 'lang.dvi', and 'lang.ps' + in the subdirectory 'doc'). + + The following new API routines were added to the package: + + lpx_transform_row (transform explicitly specified row); + lpx_transform_col (transform explicitly specified column); + lpx_prim_ratio_test (perform primal ratio test); + lpx_dual_ratio_test (perform dual ratio test); + lpx_interior (solve LP problem using interior point method); + lpx_get_ips_stat (query status of interior point solution); + lpx_get_ips_row (obtain row interior point solution); + lpx_get_ips_col (obtain column interior point solution); + lpx_get_ips_obj (obtain interior point value of obj.func.); + lpx_read_lpm (read LP/MIP model written in GLPK/L); + lpx_write_mps (write problem data using MPS format); + lpx_print_ips (print interior point solution). + + Detailed description of all these new API routines are given in + the new edition of the reference manual. + + New version of the stand-alone solver glpsol (which is based on + the new API) was implemented. + + So long as the new API (introduced in glpk 3.0) now provides + all the functions, which were provided by the old API, the old + API routines were removed from the package at all. + +GLPK 3.1 (release date: May 27, 2002) + + A preliminary implementation of new API routines was completed + and included in the package. + + These new API routines provide much more flexible interaction + between the application program, LP/MIP problem instances, and + solver routines. Based on completely changed data structures + they are, however, similar to the API routines and provide the + same functionality. Please note that three routines, namely, + solving LPs using interior point method, reading model written + in the GLPK/L modeling language, and writing problem data in + the MPS format, are not implemented in the new API, however, + these routines are planned to be implemented in the next version + of the package. + + A description of the new API routines is given in the document + "GLPK Reference Manual", a draft edition of which is included + in the package (see the files 'refman.latex', 'refman.dvi', and + 'refman.ps' in the subdirectory 'doc'). + + Although the old API routines are kept in the package, they are + no longer supported and will be removed in the future. + +GLPK 3.0.8 (release date: May 13, 2002) + + A preliminary implementation of new API routines was included + in the package. These new API routines are intended to provide + much more flexible interaction between the application program, + LP/MIP problem and solver routines. See the document "New GLPK + API Routines" (the file 'newapi.txt' in the subdirectory 'doc') + also included in the package. + + The api routines glp_simplex2, glp_call_ipm1, glp_call_bbm1 were + renamed, respectively, to glp_simplex, glp_interior, glp_integer + in order to reflect changes in implementation. The api routines + glp_call_rsm1, glp_simplex1, glp_pivot_in, glp_pivout_out were + removed from the package since they are completely supreseded by + the new API routines (however, these routines still can be found + in the subdirectory 'oldsrc'). Please consult a new edition of + the document "GLPK User's Guide" about all these changes in the + existing api routines. + + The document "GLPK Library Reference" was removed from the + package (into the subdirectory 'oldsrc') since it describes the + obsolete library routines, most of which are no longer used. + +GLPK 3.0.7 (release date: Apr 22, 2002) + + A new, more efficient implementation of the primal/dual simplex + method was included in the package. Due to some improvements the + simplex-based solver allows solving many LP problems faster and + provides more reliable results. Note that the new implementation + is currently incomplete and available only via the api routine + glp_simplex2. + + All the changes are transparent on API level. + +GLPK 3.0.6 (release date: Mar 28, 2002) + + New version of LU-factorization and basis maintenance routines + (based on Forrest-Tomlin updating technique) was implemented. + Since these new routines functionally supersede some routines + (which implement other forms of the basis matrix) and make them + obsolete, the latter were removed from the package (they still + can be found in the subdirectory 'oldsrc'). + + All the changes are transparent on API level. + +GLPK 3.0.5 (release date: Jan 29, 2002) + + New edition of the document "GLPK User's Guide" was included in + the distribution. Now it describes all additional API routines, + which were recently added to the package. + + Structure of the package was re-organized in order to make its + maintenance easier (all small files in the subdurectory 'source' + were merged in bigger units). These changes are transparent for + the user. + +GLPK 3.0.4 (release date: Dec 10, 2001) + + A new, more efficient implementation of the two-phase primal + simplex method was included in the package. Due to some new + features (an advanced initial basis, projected steepest edge, + recursive updating values and reduced costs) the new LP solver + is faster and numerically more stable than the old one. + + The new LP solver is available as API routine glp_simplex2 and + has the same purpose as API routine glp_call_rsm1. For detailed + specification see the file 'newapi.txt' in the directory 'doc'. + + Now the new LP solver is also used by default to solve an + initial LP problem in the branch-and-bound routine glp_call_bbm1 + instead the routine rsm1_driver. Note that the branch-and-bound + procedure itself is still based on rsm1_driver. + + The new LP solver is also used as default solver in GLPSOL for + solving LP and MIP problems. In order to choose the old solver + the option '--old-sim' can be specified in the command line. + +GLPK 3.0.3 (release date: Oct 03, 2001) + + Some minor changes were made in the simplex method routines in + order to improve numerical stability of the method. + +GLPK 3.0.2 (release date: Sep 24, 2001) + + A new implementation of the basis maintaining routines was + included in the package. These routines, which are based on so + called FHV-factorization (a variety of LU-factorization) of the + basis matrix and Gustavson's data structures, allows performing + the main operations faster at the expense of some worsening + numerical accuracy. + + AFI (Advanced Form of the Inverse), which is the form of the + basis matrix based on FHV-factorization, is available via the + parameter form = 3 (on API level) or via the option --afi (in + GLPSOL solver). + +GLPK 3.0.1 (release date: Aug 01, 2001) + + Old GLPK API routines have been removed from the package. + + New GLPK API routines were added: + + - scaling routines; + + - a routine for writing problem data in MPS format; + + - a comprehensive driver to the simplex method; + + - basis maintaining routines. + + A description of the new API routines is given in the document + "Additional GLPK API Routines". This document is included into + the distribution in plain text format (see the file 'newapi.txt' + in the subdirectory 'doc'). + + Now the distribution includes a non-trivial example of using + GLPK as a base LP solver for Concorde, a well known program that + solves Traveling Salesman Problem (TSP). For further details see + comments in the file 'sample/lpglpk30.c'. + +GLPK 3.0 (release date: Jul 19, 2001) + + Now GLPK is provided with new API, which being more flexible + can be used in more complex algorithmic schemes. + + New edition of the document "GLPK User's Guide" is included in + the distribution. Now it completely corresponds to the new GLPK + API routines. + + Old API routines are not removed yet from the package, however + they became obsolete and therefore should not be used. Since now + the header glpk.h corresponds to new API, in order to compile + existing programs that use old GLPK API routines the statement + + #define GLP_OLD_API + + should be inserted before the statement + + #include "glpk.h" + +GLPK 2.4.1 (release date: Jun 14, 2001) + + The document "Modeling language GLPK/L" is included into the + distribution in texinfo format. + + New edition of the document "GLPK User's Guide" is included in + the distribution. Now it describes all additional API routines + which were recently added to the package. + +GLPK 2.4 (release date: May 10, 2001) + + Now GLPK includes an implementation of a preliminary version + of the GLPK/L modeling language. This language is intended for + writing mathematcal programming models. The name GLPK/L is + derived from GNU Linear Programming Kit Language. + + A brief description of the GLPK/L language is given in the + document "GLPK/L Modeling Language: A Brief Description". This + document is included into the distribution in plain text format + (see the file 'language.txt' in the subdirectory 'doc'). + + The language processor (which is a program that analyzes model + description written in GLPK/L and translates it to internal data + structures) is available as the GLPK API routine. + + The stand-alone solver GLPSOL now is able: a) to process model + descriptions written in the GLPK/L language; b) to solve pure LP + problems using the interior point method (therefore the program + GLPIPM was removed from the package). + +GLPK 2.3 (release date: Apr 09, 2001) + + New edition of the document "GLPK User's Guide" is included in + the distribution. Now it describes all additional API routines + which were recently added to the package. + + The MIP solver was fully re-programmed in order to improve its + robustness and performance. In particular, a basis recovering + procedure was implemented (this procedure allows switching to + the primal simplex method in case when the dual simplex method + fails). + +GLPK 2.2 (release date: Mar 15, 2001) + + Now GLPK includes a tentative implementation of the + branch-and-bound procedure based on the dual simplex method for + mixed integer linear programming (MIP). + + Complete description of this new feature of the package is given + in the preliminary document "Mixed Integer Linear Programming + Using GLPK Version 2.2 (Supplement to GLPK User's Guide)". This + document is included into the distribution in plain text format + (see the file 'mip.txt' in the subdirectory 'doc'). + + The MIP solver (glp_integer) can be used as GLPK API routine in + the same way as the pure LP solver (glp_simplex). + + The stand-alone program 'glpsol' is now able to solve LP as well + as MIP problems. + + Note that the current version of GLPK MIP solver is based on + easiest heuristics for branching and backtrackng. Therefore the + solver is fit mainly for MIP problems which are not very hard + and have few integer variables. + +GLPK 2.1 (release date: Feb 19, 2001) + + The document "GLPK Implementation of the Revised Simplex Method" + is included into the distribution. This document describes most + of routines related to the revised simplex method. + +GLPK 2.0 (release date: Jan 25, 2001) + + Now GLPK includes a tentative implementation of the primal-dual + interior point method for large-scale linear programming. + + The interior point solver can be used as GLPK API routine in the + same manner as the simplex method solver (glp_simplex): + + ret = glp_interior(); + + Note that currently the interior point solver implemented in + GLPK doesn't include many important features, in particular: + + * it can't process dense columns; therefore if the problem has + dense columns, the solving will be extremely inefficient; + + * it has no special features against numerical unstability; + some problems may cause premature termination of the solving + when the matrix A*D*A' becomes ill-conditioned; + + * it computes only values of primal (auxiliary and structural) + variables and doesn't compute values of dual variables (i.e. + reduced costs) which are just set to zero; + + * it doesn't identify optimal basis corresponding to the found + interior point solution; all variables in the found solution + are just marked as basic variables. + + GLPK also includes a stand-alone program 'glpipm' which is a + demo based on the interior point method. It may be used in the + same way as the program 'glpsol' that is based on the simplex + method. diff --git a/resources/3rdparty/glpk-4.53/README b/resources/3rdparty/glpk-4.53/README new file mode 100644 index 000000000..2e7feb08b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/README @@ -0,0 +1,39 @@ + Olga K. gewidmet + +GLPK (GNU Linear Programming Kit) Version 4.53 + +Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +2009, 2010, 2011, 2013, 2014 Andrew Makhorin, Department for Applied +Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +reserved. E-mail: <mao@gnu.org>. + +GLPK is part of the GNU Project released under the aegis of GNU. + +GLPK 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 3 of the License, or (at your +option) any later version. + +See the file COPYING for the GNU General Public License. + +See the file INSTALL for compilation and installation instructions. + +The GLPK package is a set of routines written in ANSI C and organized +in the form of a callable library. This package is intended for solving +large-scale linear programming (LP), mixed integer linear programming +(MIP), and other related problems. + +The GLPK package includes the following main components: + +* implementation of the simplex method; +* implementation of the exact simplex method based on bignum (rational) + arithmetic; +* implementation of the primal-dual interior-point method; +* implementation of the branch-and-cut method; +* application program interface (API); +* GNU MathProg modeling language (a subset of AMPL); +* GLPSOL, a stand-alone LP/MIP solver. + +See GLPK webpage <http://www.gnu.org/software/glpk/glpk.html>. + +Please report bugs to <bug-glpk@gnu.org>. diff --git a/resources/3rdparty/glpk-4.53/THANKS b/resources/3rdparty/glpk-4.53/THANKS new file mode 100644 index 000000000..6cbd95613 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/THANKS @@ -0,0 +1,204 @@ +Achim Gaedke <achim.gaedke@gmail.com> for bug report. + +Alexandre Oliva <oliva@lsd.ic.unicamp.br> for bug report. + +Andre Girard <andre@inrs-emt.uquebec.ca> for bug report. + +Andrew Hamilton-Wright <andrewhw@ieee.org> for bug report. + +Andrew Hood <ajhood@fl.net.au> for bug report. + +Anne-Laurence Putz <anne-laurence.putz@eurodecision.com> for bug +report. + +Axel Simon <Axel.Simon@ens.fr> for bug report. + +Bernhard Schmidt <schmidt@math.uni-augsburg.de> for bug report. + +Boris Wirtz <Boris.Wirtz@uni-oldenburg.de> for bug report. + +Brady Hunsaker <hunsaker@engr.pitt.edu> for contribution of a routine +for bounds sensitivity analysis. + +Brady Hunsaker <hunsaker@engr.pitt.edu> for some suggestions concerning +MIP routines. + +Cameron Kellough <Cameron.Kellough@sri.com> for bug report. + +Carlo Baldassi <carlobaldassi@gmail.com> for bug report. + +Cedric[FR] <fox2113@wanadoo.fr> for bug report. + +Charles Brixko <charles.brixko@voo.be> for bug report. + +Chris Rosebrugh <cpr@pobox.com> for contribution of a new version of +GLPK JNI (Java Native Interface). + +Christophe Caron <caron@diamant.jouy.inra.fr> for bug report. + +David T. Price <dtprice@speakeasy.net> for bug report. + +Dennis Schridde <devurandom@gmx.net> for bug report. + +Enric Rodriguez <erodri@lsi.upc.edu> for bug report. + +Flavio Keidi Miyazawa <fkm@ic.unicamp.br> for bug report. + +Gabriel Hackebeil <gabehack@gmail.com> for bug report. + +Giles Thompson <gwpt1@cus.cam.ac.uk> for bug report. + +Giorgio Sartor <0gioker0@gmail.com> for contribution of routines that +implement the proximity search heuristic for MIP. + +Graham Rockwell <bionomicron@gmail.com> for bug report. + +Hans Schwengeler <Hans.Schwengeler@unibas.ch> for bug report. + +Harley Mackenzie <hjm@bigpond.com> for contribution of GLPK FAQ. + +Dr. Harley Mackenzie <hjm@hardsoftware.com> for two example MathProg +models (curve fitting problem). + +Heinrich Schuchardt <heinrich.schuchardt@gmx.de> for contribution of +makefiles and testing the package under 64-bit Windows. + +Heinrich Schuchardt <heinrich.schuchardt@gmx.de> for contribution of +two MathProg table drivers for iODBC and MySQL. + +Heinrich Schuchardt <heinrich.schuchardt@gmx.de> for some patches for +the MathProg translator. + +Heinrich Schuchardt <xypron.glpk@gmx.de> for testing the package on +32- and 64-bit MS Windows platforms. + +Ivan Luzzi <iluzzi@libero.it> for comments concerning CPLEX LP format. + +Ivo van Baren <i.van.baren@freeler.nl> for contribution of GLPK DELI +(Delphi Interface). + +Jan Engelhardt <jengelh@inai.de> for some suggestions. + +Jeffrey Kantor <Kantor.1@nd.edu> for reporting typos in the MathProg +language reference. + +Jiri Spitz <jiri.spitz@telecom.cz> for bug report. + +Joey Rios <joeylrios@hotmail.com> for some suggestions. + +Jonathan Senning <Jonathan.Senning@gordon.edu> for bug report. + +Karel Zimmermann <kzimm@diamant.jouy.inra.fr> for bug report. + +Kelly Westbrooks <kellywestbrooks@yahoo.com> for suggestions. + +Kendall Demaree <kendal.demaree@verizon.net> for bug report. + +Kjell Eikland <kjell.eikland@broadpark.no> for bug report. + +Larry D'Agostino <Larry.D'Agostino@gmacrescap.com> for example model in +MathProg. + +Luiz Bettoni <bettoni@cpgei.ct.utfpr.edu.br> for some suggestions. + +Marco Atzeri <marco.atzeri@gmail.com> for bug report. + +Marco Atzeri <marco_atzeri@yahoo.it> for bug report. + +Markus Pilz <pilz@cs.uni-bonn.de> for bug report. + +Minh Ha Duong <haduong@centre-cired.fr> for fixing doc typos. + +Morten Welinder <terra@diku.dk> for bug report. + +Morten Welinder <terra@gnu.org> for bug report. + +Nelson H. F. Beebe <beebe@math.utah.edu> for bug report. + +Nicolo Giorgetti <giorgetti@dii.unisi.it> for contribution of GLPKMEX, +a Matlab MEX interface. + +Niels Klitgord <niels@bu.edu> for bug report. + +Nigel Galloway <Nigel_Galloway@operamail.com> for an example MathProg +model. + +Nigel Galloway <Nigel_Galloway@operamail.com> for an example program +in C#. + +Nigel Galloway <nigel_galloway@operamail.com> for bug report. + +Nigel Galloway <nigel_galloway@operamail.com> for example models in +MathProg. + +Noli Sicad <nsicad@gmail.com> for testing glpk under Mac OS. + +Noli Sicad <nsicad@gmail.com> for example model in MathProg. + +Olivier <odwl@skynet.be> for bug report. + +Oscar Gustafsson <oscarg@isy.liu.se> for contribution of a routine to +write data in OPB (pseudo boolean) format. + +Peter T. Breuer <ptb@inv.it.uc3m.es> for bug report. + +Peter A. Huegler <phuegler@bsco.com> for bug report. + +Peter Ingerfeld <peter.ingerfeld@mops-optimizer.com> for bug report. + +Peter Lee <plee@kinggee.com.au> for example LP model and bug report. + +Pietro Scionti <pietro.scionti@archinet.it> for report typos found in +the reference manual. + +Rafael Laboissiere <rafael@debian.org> for useful advices concerning +shared library support under GNU/Linux. + +Raniere Gaia Costa da Silva for bug report. + +Robbie Morrison <robbie@actrix.co.nz> for correcting the glpk manual. + +Robert Wood <rgwood01@cox.net> for example model in MathProg. + +Roberto Bagnara <bagnara@cs.unipr.it> (Department of Mathematics, +University of Parma, Italy) for bug report. + +Sami Farin <sfarin@ratol.fi> for bug report. + +Sebastian Nowozin <nowozin@gmail.com> for example models in MathProg. + +Sebastien Briais <sbriais@free.fr> for bug report. + +Sebastien de Menten <sdementen@hotmail.com> for bug report. + +Sebastien Villemot <sebastien@debian.org> for bug report. + +Stefan Vigerske <stefan@math.hu-berlin.de> for bug report. + +Stefan Vigerske <stefan@vigerske.de> for bug report. + +Sylvain Fournier for bug report. + +Thomas Kahle <tom111@gmx.de> for some suggestions. + +Uday Venkatadri <Uday.Venkatadri@dal.ca> for bug report. + +Vijay Patil <vijay.patil@gmail.com> for testing the package under +Windows XP. + +Vlahos Kiriakos <Kiriakos.Vlahos@gs.com> for bug report. + +Xypron <xypron.glpk@gmx.de> for bug fixing and some improvments in the +FPUMP module. + +Xypron <xypron.glpk@gmx.de> for bug patch. + +Xypron <xypron.glpk@gmx.de> for contribution and testing batch scripts +to build Glpk with MS Visual Studio 2010. + +Xypron <xypron.glpk@gmx.de> for improving the SQL table driver. + +Xypron <xypron.glpk@gmx.de> for testing GLPK on 64-bit platforms and +for maintaining Windows versions of the package. + +Yuri Victorovich <yuri@gjt.org> for contribution of GLPK Java binding. diff --git a/resources/3rdparty/glpk-4.53/aclocal.m4 b/resources/3rdparty/glpk-4.53/aclocal.m4 new file mode 100644 index 000000000..636b7ac2f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/aclocal.m4 @@ -0,0 +1,949 @@ +# generated automatically by aclocal 1.12.5 -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. + +# This file 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. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# Copyright (C) 2002-2012 Free Software Foundation, Inc. +# +# This file 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. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.12' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.12.5], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.12.5])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file 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. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# +# This file 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. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file 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. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[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". + rm -rf conftest.dir + 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_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + 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 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # 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. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + 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 + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj 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_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file 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. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + 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. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + 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"` + # 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'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file 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 macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +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 +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], +[$0: two- and three-arguments forms are deprecated. For more info, see: +http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +dnl Support for Objective C++ was only introduced in Autoconf 2.65, +dnl but we still cater to Autoconf 2.62. +m4_ifdef([AC_PROG_OBJCXX], +[AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file 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. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2012 Free Software Foundation, Inc. +# +# This file 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. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[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 +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file 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. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# +# This file 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. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file 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. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file 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. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# 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 ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + 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 + 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". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file 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. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# 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. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2012 Free Software Foundation, Inc. +# +# This file 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. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2012 Free Software Foundation, Inc. +# +# This file 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. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of '-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar <conftest.tar]) + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) diff --git a/resources/3rdparty/glpk-4.53/config.guess b/resources/3rdparty/glpk-4.53/config.guess new file mode 100644 index 000000000..872b96a16 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/config.guess @@ -0,0 +1,1537 @@ +#! /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, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-09-25' + +# 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, see <http://www.gnu.org/licenses/>. +# +# 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 (context +# diff format) to <config-patches@gnu.org> and include a 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. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +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 <config-patches@gnu.org>." + +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, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +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 tuples: *-*-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 -q __ELF__ + 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 ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_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'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + 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 ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + 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:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-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 <stdio.h> /* 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 <sys/systemcfg.h> + + 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:*:[4567]) + 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 <stdlib.h> + #include <unistd.h> + + 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 -q __LP64__ + 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 <unistd.h> + 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:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-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 ;; + 8664:Windows_NT:*) + echo x86_64-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 ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-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 -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + 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:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + 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 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-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 ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + 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.[02]*:*) + 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' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/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 i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-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; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + 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; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; 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.[02]*:*) + 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 <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # 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 ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + 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 + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + 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 ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + 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 ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#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 <sys/param.h> + 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 <sys/param.h> +# 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 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> 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: diff --git a/resources/3rdparty/glpk-4.53/config.h.cmake.in b/resources/3rdparty/glpk-4.53/config.h.cmake.in new file mode 100644 index 000000000..ebde8d1b6 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/config.h.cmake.in @@ -0,0 +1,27 @@ +/* config.h.in (GLPK configuration template file) */ + +#@GLPK_HAVE_SYS_TIME_H@ HAVE_SYS_TIME_H +/* defined if the <sys/time.h> header can be used */ + +#@GLPK_HAVE_GETTIMEOFDAY@ HAVE_GETTIMEOFDAY +/* defined if the gettimeofday function can be used */ + +#@GLPK_HAVE_GMP@ HAVE_GMP +/* defined if the GNU MP bignum library is available */ +/* requires <gmp.h> and -lgmp */ + +#@GLPK_HAVE_LTDL@ HAVE_LTDL +/* defined if the GNU Libtool shared library support is enabled */ +/* requires <ltdl.h> and -lltdl */ + +#@GLPK_HAVE_DLFCN@ HAVE_DLFCN +/* defined if the POSIX shared library support is enabled */ +/* requires <dlfcn.h> */ + +#@GLPK_HAVE_ODBC@ ODBC_DLNAME @GLPK_ODBC_DLNAME@ +/* ODBC shared library name if this feature is enabled */ + +#@GLPK_HAVE_MYSQL@ MYSQL_DLNAME @GLPK_MYSQL_DLNAME@ +/* MySQL shared library name if this feature is enabled */ + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/config.h.in b/resources/3rdparty/glpk-4.53/config.h.in new file mode 100644 index 000000000..2849bf9c4 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/config.h.in @@ -0,0 +1,27 @@ +/* config.h.in (GLPK configuration template file) */ + +#undef HAVE_SYS_TIME_H +/* defined if the <sys/time.h> header can be used */ + +#undef HAVE_GETTIMEOFDAY +/* defined if the gettimeofday function can be used */ + +#undef HAVE_GMP +/* defined if the GNU MP bignum library is available */ +/* requires <gmp.h> and -lgmp */ + +#undef HAVE_LTDL +/* defined if the GNU Libtool shared library support is enabled */ +/* requires <ltdl.h> and -lltdl */ + +#undef HAVE_DLFCN +/* defined if the POSIX shared library support is enabled */ +/* requires <dlfcn.h> */ + +#undef ODBC_DLNAME +/* ODBC shared library name if this feature is enabled */ + +#undef MYSQL_DLNAME +/* MySQL shared library name if this feature is enabled */ + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/config.sub b/resources/3rdparty/glpk-4.53/config.sub new file mode 100644 index 000000000..89b128630 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/config.sub @@ -0,0 +1,1789 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-10-10' + +# 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, see <http://www.gnu.org/licenses/>. +# +# 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 <config-patches@gnu.org>. Submit a context +# diff and a properly formatted GNU 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. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# 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 <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +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-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + 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 | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -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*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -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 \ + | aarch64 | aarch64_be \ + | 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[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | 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 \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-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-* \ + | aarch64-* | aarch64_be-* \ + | 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-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | 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-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | 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-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | 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-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # 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 + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + 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 + ;; + cr16 | cr16-*) + basic_machine=cr16-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 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + 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*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 + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + 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-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + 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 + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + 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 + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + 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 | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + 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 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + 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 + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + 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 + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-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[24]aeb | 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. + -auroraux) + os=-auroraux + ;; + -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* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -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* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -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* | -es*) + # 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 + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -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 + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + 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 + ;; + 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 + ;; + -cnk*|-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: diff --git a/resources/3rdparty/glpk-4.53/configure b/resources/3rdparty/glpk-4.53/configure new file mode 100644 index 000000000..049242a6b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/configure @@ -0,0 +1,13839 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for GLPK 4.53. +# +# Report bugs to <bug-glpk@gnu.org>. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +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 +IFS=$as_save_IFS + + ;; +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 + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and bug-glpk@gnu.org +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; 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 + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# 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 + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # 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 sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# 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'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='GLPK' +PACKAGE_TARNAME='glpk' +PACKAGE_VERSION='4.53' +PACKAGE_STRING='GLPK 4.53' +PACKAGE_BUGREPORT='bug-glpk@gnu.org' +PACKAGE_URL='' + +ac_unique_file="src/glpk.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +CPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_gmp +enable_dl +enable_odbc +enable_mysql +enable_dependency_tracking +enable_shared +enable_static +with_pic +enable_fast_install +with_gnu_ld +with_sysroot +enable_libtool_lock +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# 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. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +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 + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -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) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$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 ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$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 ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + 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 ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$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_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=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 ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_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'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +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 + 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 + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# 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 the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + 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 + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# 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 GLPK 4.53 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 \`..'] + +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] + --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] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/glpk] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_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 GLPK 4.53:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-dl enable shared library support [[default=no]] + --enable-odbc enable MathProg ODBC support [[default=no]] + --enable-mysql enable MathProg MySQL support [[default=no]] + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gmp use GNU MP bignum library [[default=no]] + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + CPP C preprocessor + +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 <bug-glpk@gnu.org>. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested 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 + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +GLPK configure 4.53 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* 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_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------- ## +## Report this to bug-glpk@gnu.org ## +## ------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by GLPK $as_me 4.53, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +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` +/usr/bin/hostinfo = `(/usr/bin/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=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&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_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=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append 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 + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset 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: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > 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 + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + 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. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_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 $ac_precious_vars; 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,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_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 + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_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. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +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 + + + + + + + +am__api_version='1.12' + +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 + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# 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. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&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_fn_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 + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +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. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$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' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# 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 ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + 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 + 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". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +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 $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "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 + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +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='glpk' + VERSION='4.53' + + +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"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +ac_config_headers="$ac_config_headers config.h" + + + +# Check whether --with-gmp was given. +if test "${with_gmp+set}" = set; then : + withval=$with_gmp; case $withval in + yes | no) ;; + *) as_fn_error $? "invalid value \`$withval' for --with-gmp" "$LINENO" 5;; + esac +else + with_gmp=no +fi + + +# Check whether --enable-dl was given. +if test "${enable_dl+set}" = set; then : + enableval=$enable_dl; case $enableval in + yes | ltdl | dlfcn | no) ;; + *) as_fn_error $? "invalid value \`$enableval' for --enable-dl" "$LINENO" 5;; + esac +else + enable_dl=no +fi + + +# Check whether --enable-odbc was given. +if test "${enable_odbc+set}" = set; then : + enableval=$enable_odbc; case $enableval in + yes | unix | no) ;; + *) as_fn_error $? "invalid value \`$enableval' for --enable-odbc" "$LINENO" 5;; + esac +else + enable_odbc=no +fi + + +# Check whether --enable-mysql was given. +if test "${enable_mysql+set}" = set; then : + enableval=$enable_mysql; case $enableval in + yes | no) ;; + *) as_fn_error $? "invalid value \`$enableval' for --enable-mysql" "$LINENO" 5;; + esac +else + enable_mysql=no +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 +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # 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_fn_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_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +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_CC + 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 CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM 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. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; 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 | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* 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 -std 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 -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 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 +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +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 +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-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='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&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". + rm -rf conftest.dir + 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 + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + 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 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # 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. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + 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 + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$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 + + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4' +macro_revision='1.3294' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +# Backslashify metacharacters that are still active within +# double-quoted strings. +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 delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + 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_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-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. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&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 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&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 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&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 + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&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* | cegcc*) + # 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; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + 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 + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + 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` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # 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. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + 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` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$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 + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + 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 + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&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 +aix[4-9]*) + 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', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | 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 + ;; + +haiku*) + 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])(-bit)?( [LM]SB)? 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 + ;; + +interix[3-9]*) + # 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* | k*bsd*-gnu | kopensolaris*-gnu) + 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=pass_all + ;; + +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 + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + 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 + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +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 test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +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 + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# 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 for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&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]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + 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 + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \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\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# 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 + +# Try without a prefix underscore, 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. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$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=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && 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 <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_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 -rf 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 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +# Check whether --enable-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\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; 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 '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; 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-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + 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-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + 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" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$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\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&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 <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> 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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$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 <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> 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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +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 + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core 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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#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)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +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=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-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-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=yes +fi + + + + + + + + + + +# Check whether --with-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 + + + + + + + + # Check whether --enable-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 + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +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 + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&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 <<_LT_EOF 1>&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 + +_LT_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 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&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 <<_LT_EOF 1>&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 + +_LT_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 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +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;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# 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 the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$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 +echo "$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 -r 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... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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 "$_lt_compiler_boilerplate" | $SED '/^$/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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$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= + + + 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*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # 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' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # 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). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + 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' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # 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 + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + lt_prog_compiler_pic='-Xcompiler -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 + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # 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' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # 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' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + 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 + +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 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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 "$_lt_compiler_boilerplate" | $SED '/^$/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_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_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 + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$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 "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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 "$_lt_compiler_boilerplate" | $SED '/^$/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 .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$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:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $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 "$_lt_compiler_boilerplate" | $SED '/^$/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 .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$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 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&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 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_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 + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # 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_|_GLOBAL__F[ID]_.*' + # 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. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # 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 + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = 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>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [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 + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, 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 install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + 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 + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach <jrb3@best.com> 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* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + 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/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + 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 + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + 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' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + 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; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # 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; func_echo_all \"$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' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; 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 '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld='-rpath $libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; 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~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + 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 $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $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 <<_LT_EOF 1>&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. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $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 + ;; + *) + # 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. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + 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 + ;; + + 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 $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $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 + ;; + + aix[4-9]*) + 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 + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + 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") || (\$ 2 == "W")) && (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].*|aix[5-9]*) + 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_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + 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 + : + 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 + + export_dynamic_flag_spec='${wl}-bexpall' + # 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. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +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 func_echo_all "${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. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +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' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + 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*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + 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 + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # 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. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # 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 $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + 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' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + 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 `func_echo_all "$deplibs" | $SED '\''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' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + 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* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -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 $pic_flag ${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 && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${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_flag_spec_ld='+b $libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=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 && test "$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 $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag ${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' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$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 "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${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 + + ;; + 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_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=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 $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + 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 + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + 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 + else + ld_shlibs=no + 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" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + 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} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${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='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-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; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_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 + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${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 $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + 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' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $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 -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + 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 and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + 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* | sco3.2v5.0.[024]*) + 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='${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,$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 + ;; + + 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 + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# 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. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 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\":${as_lineno-$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=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # 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. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +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" +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' + ;; + +aix[4-9]*) + 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<name>.so + # instead of lib<name>.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*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + 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=`func_echo_all "$lib" | $SED '\''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' + ;; + esac + ;; + +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* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + 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~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + 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="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + 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 + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + 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 + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # 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' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # 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}${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`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + 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 + ;; + +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 + ;; + *) # from 4.6 on, and DragonFly + 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 + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + 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=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + 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' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + 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* | k*bsd*-gnu | kopensolaris*-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' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # 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>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;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' + ;; + +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=qnx + 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='ldqnx.so' + ;; + +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" + ;; + +rdos*) + dynamic_linker=no + ;; + +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 + 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 + shlibpath_overrides_runpath=yes + 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' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + 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' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/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}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$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 + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent 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_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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; 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 + + + + + + + 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* | cegcc*) + 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 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; 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 + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +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" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&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 <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#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 + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 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; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$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\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&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 <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#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 + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 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; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$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 + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&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" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "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" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&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 + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +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" + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exp in -lm" >&5 +$as_echo_n "checking for exp in -lm... " >&6; } +if ${ac_cv_lib_m_exp+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char exp (); +int +main () +{ +return exp (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_exp=yes +else + ac_cv_lib_m_exp=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_exp" >&5 +$as_echo "$ac_cv_lib_m_exp" >&6; } +if test "x$ac_cv_lib_m_exp" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + + +ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_time_h" = xyes; then : + +$as_echo "#define HAVE_SYS_TIME_H 1" >>confdefs.h + +fi + + + +ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" +if test "x$ac_cv_func_gettimeofday" = xyes; then : + +$as_echo "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h + +fi + + +if test "$with_gmp" = "yes"; then + ac_fn_c_check_header_mongrel "$LINENO" "gmp.h" "ac_cv_header_gmp_h" "$ac_includes_default" +if test "x$ac_cv_header_gmp_h" = xyes; then : + +else + as_fn_error $? "gmp.h header not found" "$LINENO" 5 +fi + + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use GNU MP bignum library" >&5 +$as_echo_n "checking whether to use GNU MP bignum library... " >&6; } +if test "$with_gmp" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_GMP 1" >>confdefs.h + + LIBS="-lgmp $LIBS" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable shared library support" >&5 +$as_echo_n "checking whether to enable shared library support... " >&6; } +if test "$enable_dl" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ltdl" >&5 +$as_echo "ltdl" >&6; } + +$as_echo "#define HAVE_LTDL 1" >>confdefs.h + + LIBS="-lltdl $LIBS" +elif test "$enable_dl" = "ltdl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ltdl" >&5 +$as_echo "ltdl" >&6; } + +$as_echo "#define HAVE_LTDL 1" >>confdefs.h + + LIBS="-lltdl $LIBS" +elif test "$enable_dl" = "dlfcn"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: dlfcn" >&5 +$as_echo "dlfcn" >&6; } + +$as_echo "#define HAVE_DLFCN 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +case $host_os in + darwin* | macosx*) + LIBIODBC="libiodbc.dylib" + LIBODBC="libodbc.dylib" + LIBMYSQL="libmysqlclient.dylib" + ;; + *) + LIBIODBC="libiodbc.so" + LIBODBC="libodbc.so" + LIBMYSQL="libmysqlclient.so" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable MathProg ODBC support" >&5 +$as_echo_n "checking whether to enable MathProg ODBC support... " >&6; } +if test "$enable_odbc" = "yes"; then + if test "$enable_dl" = "no"; then + as_fn_error $? "--enable-odbc requires --enable-dl" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<_ACEOF +#define ODBC_DLNAME "$LIBIODBC" +_ACEOF + +elif test "$enable_odbc" = "unix"; then + if test "$enable_dl" = "no"; then + as_fn_error $? "--enable-odbc requires --enable-dl" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unix" >&5 +$as_echo "unix" >&6; } + +cat >>confdefs.h <<_ACEOF +#define ODBC_DLNAME "$LIBODBC" +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable MathProg MySQL support" >&5 +$as_echo_n "checking whether to enable MathProg MySQL support... " >&6; } +if test "$enable_mysql" = "yes"; then + if test "$enable_dl" = "no"; then + as_fn_error $? "--enable-mysql requires --enable-dl" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CPPFLAGS="-I/usr/include/mysql $CPPFLAGS" + +cat >>confdefs.h <<_ACEOF +#define MYSQL_DLNAME "$LIBMYSQL" +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +ac_config_files="$ac_config_files src/Makefile examples/Makefile Makefile" + +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, we kill variables containing newlines. +# 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. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}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 "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + 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}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $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} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +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 +IFS=$as_save_IFS + + ;; +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 + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; 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 + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# 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 + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# 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'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by GLPK $as_me 4.53, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + 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 <bug-glpk@gnu.org>." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +GLPK config.status 4.53 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +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=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + 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 || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# 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 + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +nm_file_list_spec \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + 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 against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries 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[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' <confdefs.h | sed ' +s/'"$ac_delim"'/"\\\ +"/g' >>$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #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. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # 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. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;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&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + 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. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_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"` + # 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'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # 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 + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# 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 + +# 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//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# 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 + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# 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 + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# 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 + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# 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 + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# 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 + +# 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 + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# 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 + +# 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 + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# 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 a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# 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 DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# 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 + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# 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 + +# 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 + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_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 +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # 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) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# 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 || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + diff --git a/resources/3rdparty/glpk-4.53/configure.ac b/resources/3rdparty/glpk-4.53/configure.ac new file mode 100644 index 000000000..7f3de1878 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/configure.ac @@ -0,0 +1,147 @@ +dnl Process this file with autoconf to produce a configure script + +AC_INIT([GLPK], [4.53], [bug-glpk@gnu.org]) + +AC_CONFIG_SRCDIR([src/glpk.h]) + +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE + +AC_CONFIG_HEADERS([config.h]) + +AC_ARG_WITH(gmp, +AC_HELP_STRING([--with-gmp], + [use GNU MP bignum library [[default=no]]]), + [case $withval in + yes | no) ;; + *) AC_MSG_ERROR([invalid value `$withval' for --with-gmp]);; + esac], + [with_gmp=no]) + +AC_ARG_ENABLE(dl, +AC_HELP_STRING([--enable-dl], + [enable shared library support [[default=no]]]), + [case $enableval in + yes | ltdl | dlfcn | no) ;; + *) AC_MSG_ERROR([invalid value `$enableval' for --enable-dl]);; + esac], + [enable_dl=no]) + +AC_ARG_ENABLE(odbc, +AC_HELP_STRING([--enable-odbc], + [enable MathProg ODBC support [[default=no]]]), + [case $enableval in + yes | unix | no) ;; + *) AC_MSG_ERROR([invalid value `$enableval' for --enable-odbc]);; + esac], + [enable_odbc=no]) + +AC_ARG_ENABLE(mysql, +AC_HELP_STRING([--enable-mysql], + [enable MathProg MySQL support [[default=no]]]), + [case $enableval in + yes | no) ;; + *) AC_MSG_ERROR([invalid value `$enableval' for --enable-mysql]);; + esac], + [enable_mysql=no]) + +dnl Disable unnecessary libtool tests +define([AC_LIBTOOL_LANG_CXX_CONFIG], [:]) +define([AC_LIBTOOL_LANG_F77_CONFIG], [:]) +define([AC_LIBTOOL_LANG_GCJ_CONFIG], [:]) + +dnl Check for programs +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_LIBTOOL + +dnl Check for math library +AC_CHECK_LIB([m], [exp]) + +dnl Check for <sys/time.h> header +AC_CHECK_HEADER([sys/time.h], + AC_DEFINE([HAVE_SYS_TIME_H], [1], [N/A])) + +dnl Check for gettimeofday function +AC_CHECK_FUNC([gettimeofday], + AC_DEFINE([HAVE_GETTIMEOFDAY], [1], [N/A])) + +dnl Check for <gmp.h> header +if test "$with_gmp" = "yes"; then + AC_CHECK_HEADER([gmp.h], [], + [AC_MSG_ERROR([gmp.h header not found])]) +fi + +AC_MSG_CHECKING([whether to use GNU MP bignum library]) +if test "$with_gmp" = "yes"; then + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_GMP], [1], [N/A]) + LIBS="-lgmp $LIBS" +else + AC_MSG_RESULT([no]) +fi + +AC_MSG_CHECKING([whether to enable shared library support]) +if test "$enable_dl" = "yes"; then + AC_MSG_RESULT([ltdl]) + AC_DEFINE([HAVE_LTDL], [1], [N/A]) + LIBS="-lltdl $LIBS" +elif test "$enable_dl" = "ltdl"; then + AC_MSG_RESULT([ltdl]) + AC_DEFINE([HAVE_LTDL], [1], [N/A]) + LIBS="-lltdl $LIBS" +elif test "$enable_dl" = "dlfcn"; then + AC_MSG_RESULT([dlfcn]) + AC_DEFINE([HAVE_DLFCN], [1], [N/A]) +else + AC_MSG_RESULT([no]) +fi + +case $host_os in + darwin* | macosx*) + LIBIODBC="libiodbc.dylib" + LIBODBC="libodbc.dylib" + LIBMYSQL="libmysqlclient.dylib" + ;; + *) + LIBIODBC="libiodbc.so" + LIBODBC="libodbc.so" + LIBMYSQL="libmysqlclient.so" + ;; +esac + +AC_MSG_CHECKING([whether to enable MathProg ODBC support]) +if test "$enable_odbc" = "yes"; then + if test "$enable_dl" = "no"; then + AC_MSG_ERROR([--enable-odbc requires --enable-dl]) + fi + AC_MSG_RESULT([yes]) + AC_DEFINE_UNQUOTED([ODBC_DLNAME], ["$LIBIODBC"], [N/A]) +elif test "$enable_odbc" = "unix"; then + if test "$enable_dl" = "no"; then + AC_MSG_ERROR([--enable-odbc requires --enable-dl]) + fi + AC_MSG_RESULT([unix]) + AC_DEFINE_UNQUOTED([ODBC_DLNAME], ["$LIBODBC"], [N/A]) +else + AC_MSG_RESULT([no]) +fi + +AC_MSG_CHECKING([whether to enable MathProg MySQL support]) +if test "$enable_mysql" = "yes"; then + if test "$enable_dl" = "no"; then + AC_MSG_ERROR([--enable-mysql requires --enable-dl]) + fi + AC_MSG_RESULT([yes]) + CPPFLAGS="-I/usr/include/mysql $CPPFLAGS" + AC_DEFINE_UNQUOTED([MYSQL_DLNAME], ["$LIBMYSQL"], [N/A]) +else + AC_MSG_RESULT([no]) +fi + +AC_CONFIG_FILES( + [src/Makefile examples/Makefile Makefile]) +AC_OUTPUT + +dnl eof diff --git a/resources/3rdparty/glpk-4.53/depcomp b/resources/3rdparty/glpk-4.53/depcomp new file mode 100644 index 000000000..e1f51f482 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/depcomp @@ -0,0 +1,787 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2012-07-12.20; # UTC + +# Copyright (C) 1999-2012 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, see <http://www.gnu.org/licenses/>. + +# 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 <oliva@dcc.unicamp.br>. + +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 outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to <bug-automake@gnu.org>. +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' + +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" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# 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 + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +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. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## 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). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - 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 ' ' "$nl" < "$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. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## 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 "s|.*$object$||" -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 ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$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" + ;; + +xlc) + # 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 + ;; + +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. + 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 + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # 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,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$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 anf tcc (Tiny C Compiler) understand '-MD -MF file'. + # However on + # $CC -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 ... \ + # ... + # tcc 0.9.26 (FIXME still under development at the moment of writing) + # will emit a similar output, but also prepend the continuation lines + # with horizontal tabulation characters. + "$@" -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 -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ + < "$tmpdepfile" > "$depfile" + sed ' + s/[ '"$tab"'][ '"$tab"']*/ /g + s/^ *// + s/ *\\*$// + s/^[^:]*: *// + /^$/d + /:$/d + s/$/ :/ + ' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + base=`echo "$source" | sed -e 's|^.*/||' -e 's/\.[-_a-zA-Z0-9]*$//'` + tmpdepfile="$base.d" + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir="$base.d-lock" + trap "echo '$0: caught signal, cleaning up...' >&2; rm -rf $lockdir" 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0 ; do + # mkdir is a portable test-and-set. + if mkdir $lockdir 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rm -rf $lockdir + break + else + ## the lock is being held by a different process, + ## wait until the winning process is done or we timeout + while test -d $lockdir && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + 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" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + 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 + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +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 mechanism 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 $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" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test "$stat" = 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # 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 + ;; + +#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 "X$1" != 'X--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:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' "$nl" < "$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 "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + 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. + -arch) + eat=yes ;; + -*|$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" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ +## 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 "X$1" != 'X--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. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # 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 + ;; + +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-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/resources/3rdparty/glpk-4.53/doc/cnfsat.pdf b/resources/3rdparty/glpk-4.53/doc/cnfsat.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d7ff1932fe4de6ed4e0831b6c1b9c47db02e85a8 GIT binary patch literal 59926 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	su6W<q+(qT2NA)^$Vel-z!U+W94F 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 CJ^;)B literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/doc/cnfsat.tex b/resources/3rdparty/glpk-4.53/doc/cnfsat.tex new file mode 100644 index 000000000..4a2c3bbab --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/cnfsat.tex @@ -0,0 +1,413 @@ +%* cnfsat.tex *% + +\documentclass[11pt,draft]{article} +\usepackage{amssymb} +\usepackage{indentfirst} + +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{8.5in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +\setlength{\itemsep}{\parskip} +\setlength{\parsep}{0pt} +\setlength{\leftmargini}{\parindent} +\renewcommand{\labelitemi}{---} + +\def\para#1{\noindent{\bf#1}} +\def\synopsis{\para{Synopsis}} +\def\description{\para{Description}} +\def\returns{\para{Returns}} + +\newenvironment{retlist} +{ \def\arraystretch{1.5} + \noindent + \begin{tabular}{@{}p{1in}@{}p{5.5in}@{}} +} +{\end{tabular}} + +\begin{document} + +\title{\bf CNF Satisfiability Problem} + +\author{Andrew Makhorin {\tt<mao@gnu.org>}} + +\date{August 2011} + +\maketitle + +\section{Introduction} + +The {\it Satisfiability Problem (SAT)} is a classic combinatorial +problem. Given a Boolean formula of $n$ variables +$$f(x_1,x_2,\dots,x_n),\eqno(1.1)$$ +this problem is to find such values of the variables, on which the +formula takes on the value {\it true}. + +The {\it CNF Satisfiability Problem (CNF-SAT)} is a version of the +Satisfiability Problem, where the Boolean formula (1.1) is specified +in the {\it Conjunctive Normal Form (CNF)}, that means that it is a +conjunction of {\it clauses}, where a clause is a disjunction of +{\it literals}, and a literal is a variable or its negation. +For example: +$$(x_1\vee x_2)\;\&\;(\neg x_2\vee x_3\vee\neg x_4)\;\&\;(\neg +x_1\vee x_4).\eqno(1.2)$$ +Here $x_1$, $x_2$, $x_3$, $x_4$ are Boolean variables to be assigned, +$\neg$ means +negation (logical {\it not}), $\vee$ means disjunction (logical +{\it or}), and $\&$ means conjunction (logical {\it and}). One may +note that the formula (1.2) is {\it satisfiable}, because on +$x_1$ = {\it true}, $x_2$ = {\it false}, $x_3$ = {\it false}, and +$x_4$ = {\it true} it takes on the value {\it true}. If a formula +is not satisfiable, it is called {\it unsatisfiable}, that means that +it takes on the value {\it false} on any values of its variables. + +Any CNF-SAT problem can be easily translated to a 0-1 programming +problem as follows.\linebreak A Boolean variable $x$ can be modeled by +a binary variable in a natural way: $x=1$ means that $x$ takes on the +value {\it true}, and $x=0$ means that $x$ takes on the value +{\it false}. Then, if a literal is a negated variable, i.e. $t=\neg x$, +it can be expressed as $t=1-x$. Since a formula in CNF is a conjunction +of clauses, to provide its satisfiability we should require all its +clauses to take on the value {\it true}. A particular clause is +a disjunction of literals: +$$t\vee t'\vee t''\dots ,\eqno(1.3)$$ +so it takes on the value {\it true} iff at least one of its literals +takes on the value {\it true}, that can be expressed as the following +inequality constraint: +$$t+t'+t''+\dots\geq 1.\eqno(1.4)$$ +Note that no objective function is used in this case, because only +a feasible solution needs to be found. + +For example, the formula (1.2) can be translated to the following +constraints: +$$\begin{array}{c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c} +x_1&+&x_2&&&&&\geq&1\\ +&&(1-x_2)&+&x_3&+&(1-x_4)&\geq&1\\ +(1-x_1)&&&&&+&x_4&\geq&1\\ +\end{array}$$ +$$x_1, x_2, x_3, x_4\in\{0,1\}$$ +Carrying out all constant terms to the right-hand side gives +corresponding 0-1 programming problem in the standard format: +$$\begin{array}{r@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }r} +x_1&+&x_2&&&&&\geq&1\\ +&-&x_2&+&x_3&-&x_4&\geq&-1\\ +-x_1&&&&&+&x_4&\geq&0\\ +\end{array}$$ +$$x_1, x_2, x_3, x_4\in\{0,1\}$$ + +In general case translation of a CNF-SAT problem results in the +following 0-1 programming problem: +$$\sum_{j\in J^+_i}x_j-\sum_{j\in J^-_i}x_j\geq 1-|J^-_i|, +\ \ \ i=1,\dots,m\eqno(1.5)$$ +$$x_j\in\{0,1\},\ \ \ j=1,\dots,n\eqno(1.6)$$ +where $n$ is the number of variables, $m$ is the number of clauses +(inequality constraints),\linebreak $J^+_i\subseteq\{1,\dots,n\}$ is +a subset of variables, whose literals in $i$-th clause do not have +negation, and $J^-_i\subseteq\{1,\dots,n\}$ is a subset of variables, +whose literals in $i$-th clause are negations of that variables. It is +assumed that $J^+_i\cap J^-_i=\varnothing$ for all $i$. + +\section{GLPK API Routines} + +\subsection{glp\_read\_cnfsat --- read CNF-SAT problem data in DIMACS +format} + +\synopsis + +\begin{verbatim} + int glp_read_cnfsat(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_cnfsat| reads the CNF-SAT problem data from +a text file in DIMACS format and automatically translates the data to +corresponding 0-1 programming problem instance (1.5)--(1.6). + +The parameter \verb|P| specifies the problem object, to which the +0-1 programming problem instance should be stored. Note that before +reading data the current content of the problem object is completely +erased with the routine \verb|glp_erase_prob|. + +The character string \verb|fname| specifies the name of a text file +to be read in. (If the file name ends with the suffix `\verb|.gz|', +the file is assumed to be compressed, in which case the routine +decompresses it ``on the fly''.) + +\newpage + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\para{DIMACS CNF-SAT problem format}\footnote{This material is based on +the paper ``Satisfiability Suggested Format'', which is publicly +available at {\tt http://dimacs.rutgers.edu/}.} + +The DIMACS input file is a plain ASCII text file. It contains lines of +several types described below. A line is terminated with an end-of-line +character. Fields in each line are separated by at least one blank +space. + +\para{Comment lines.} Comment lines give human-readable information +about the file and are ignored by programs. Comment lines can appear +anywhere in the file. Each comment line begins with a lower-case +character \verb|c|. + +\begin{verbatim} + c This is a comment line +\end{verbatim} + +\para{Problem line.} There is one problem line per data file. The +problem line must appear before any clause lines. It has the following +format: + +\begin{verbatim} + p cnf VARIABLES CLAUSES +\end{verbatim} + +\noindent +The lower-case character \verb|p| signifies that this is a problem +line. The three character problem designator \verb|cnf| identifies the +file as containing specification information for the CNF-SAT problem. +The \verb|VARIABLES| field contains an integer value specifying $n$, +the number of variables in the instance. The \verb|CLAUSES| field +contains an integer value specifying $m$, the number of clauses in the +instance. + +\para{Clauses.} The clauses appear immediately after the problem +line. The variables are assumed to be numbered from 1 up to $n$. It is +not necessary that every variable appears in the instance. Each clause +is represented by a sequence of numbers separated by either a space, +tab, or new-line character. The non-negated version of a variable $j$ +is represented by $j$; the negated version is represented by $-j$. Each +clause is terminated by the value 0. Unlike many formats that represent +the end of a clause by a new-line character, this format allows clauses +to be on multiple lines. + +\para{Example.} Below here is an example of the data file in DIMACS +format corresponding to the CNF-SAT problem (1.2). + +\begin{footnotesize} +\begin{verbatim} +c sample.cnf +c +c This is an example of the CNF-SAT problem data +c in DIMACS format. +c +p cnf 4 3 +1 2 0 +-4 3 +-2 0 +-1 4 0 +c +c eof +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_check\_cnfsat --- check for CNF-SAT problem instance} + +\synopsis + +\begin{verbatim} + int glp_check_cnfsat(glp\_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_check_cnfsat| checks if the specified problem +object \verb|P| contains a 0-1 programming problem instance in the +format (1.5)--(1.6) and therefore encodes a CNF-SAT problem instance. + +\returns + +If the specified problem object has the format (1.5)--(1.6), the +routine returns zero, otherwise non-zero. + +\subsection{glp\_write\_cnfsat --- write CNF-SAT problem data in DIMACS +format} + +\synopsis + +\begin{verbatim} + int glp_write_cnfsat(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_cnfsat| automatically translates the +specified 0-1 programming problem instance (1.5)--(1.6) to a CNF-SAT +problem instance and writes the problem data to a text file in DIMACS +format. + +The parameter \verb|P| is the problem object, which should specify +a 0-1 programming problem instance in the format (1.5)--(1.6). + +The character string \verb|fname| specifies a name of the output text +file to be written. (If the file name ends with suffix `\verb|.gz|', +the file is assumed to be compressed, in which case the routine +performs automatic compression on writing that file.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\subsection{glp\_minisat1 --- solve CNF-SAT problem instance with +MiniSat solver} + +\synopsis + +\begin{verbatim} + int glp_minisat1(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_minisat1| is a driver to MiniSat, a CNF-SAT +solver developed by Niklas E\'en and Niklas S\"orensson, Chalmers +University of Technology, Sweden.\footnote{The MiniSat software module +is {\it not} part of GLPK, but is used with GLPK and included in the +distribution.} + +\newpage + +It is assumed that the specified problem object \verb|P| contains +a 0-1 programming problem instance in the format (1.5)--(1.6) and +therefore encodes a CNF-SAT problem instance. + +If the problem instance has been successfully solved to the end, the +routine \verb|glp_minisat1| returns 0. In this case the routine +\verb|glp_mip_status| can be used to determine the solution status: + +\begin{itemize} +\item {\tt GLP\_OPT} means that the solver found an integer feasible +solution and therefore the corresponding CNF-SAT instance is +satisfiable; + +\item {\tt GLP\_NOFEAS} means that no integer feasible solution exists +and therefore the corresponding CNF-SAT instance is unsatisfiable. +\end{itemize} + +If an integer feasible solution was found, corresponding values of +binary variables can be retrieved with the routine +\verb|glp_mip_col_val|. + +\returns + +\begin{retlist} +0 & The MIP problem instance has been successfully solved. (This code +does {\it not} necessarily mean that the solver has found feasible +solution. It only means that the solution process was successful.)\\ + +{\tt GLP\_EDATA} & The specified problem object contains a MIP +instance which does {\it not} have the format (1.5)--(1.6).\\ + +{\tt GLP\_EFAIL} & The solution process was unsuccessful because of +the solver failure.\\ +\end{retlist} + +\subsection{glp\_intfeas1 --- solve integer feasibility problem} + +\synopsis + +\begin{verbatim} + int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound); +\end{verbatim} + +\description + +The routine \verb|glp_intfeas1| is a tentative implementation of +an integer feasibility solver based on a CNF-SAT solver (currently +it is MiniSat; see Subsection 2.4). + +If the parameter \verb|use_bound| is zero, the routine searches for +{\it any} integer feasibile solution to the specified integer +programming problem. Note that in this case the objective function is +ignored. + +If the parameter \verb|use_bound| is non-zero, the routine searches for +an integer feasible solution, which provides a value of the objective +function not worse than \verb|obj_bound|. In other word, the parameter +\verb|obj_bound| specifies an upper (in case of minimization) or lower +(in case of maximization) bound to the objective function. + +If the specified problem has been successfully solved to the end, the +routine \verb|glp_intfeas1| returns 0. In this case the routine +\verb|glp_mip_status| can be used to determine the solution status: + +\begin{itemize} +\item {\tt GLP\_FEAS} means that the solver found an integer feasible +solution; + +\item {\tt GLP\_NOFEAS} means that the problem has no integer feasible +solution (if {\tt use\_bound} is zero) or it has no integer feasible +solution, which is not worse than {\tt obj\_bound} (if {\tt use\_bound} +is non-zero). +\end{itemize} + +\newpage + +If an integer feasible solution was found, corresponding values of +variables (columns) can be retrieved with the routine +\verb|glp_mip_col_val|. + +\para{Usage Notes} + +The integer programming problem specified by the parameter \verb|P| +should satisfy to the following requirements: + +\begin{enumerate} +\item All variables (columns) should be either binary ({\tt GLP\_BV}) +or fixed at integer values ({\tt GLP\_FX}). + +\item All constraint and objective coefficients should be integer +numbers in the range\linebreak $[-2^{31},\ +2^{31}-1]$. +\end{enumerate} + +Though there are no special requirements to the constraints, +currently the routine \verb|glp_intfeas1| is efficient mainly for +problems, where most constraints (rows) fall into the following three +classes: + +\begin{enumerate} +\item Covering inequalities +$$\sum_{j}t_j\geq 1,$$ +where $t_j=x_j$ or $t_j=1-x_j$, $x_j$ is a binary variable. + +\item Packing inequalities +$$\sum_{j}t_j\leq 1.$$ + +\item Partitioning equalities (SOS1 constraints) +$$\sum_{j}t_j=1.$$ +\end{enumerate} + +\returns + +\begin{retlist} +0 & The problem has been successfully solved. (This code does +{\it not} necessarily mean that the solver has found an integer +feasible solution. It only means that the solution process was +successful.) \\ + +{\tt GLP\_EDATA} & The specified problem object does not satisfy +to the requirements listed in Paragraph `Usage Notes'. \\ + +{\tt GLP\_ERANGE} & An integer overflow occured on translating the +specified problem to a CNF-SAT problem. \\ + +{\tt GLP\_EFAIL} & The solution process was unsuccessful because of +the solver failure. \\ +\end{retlist} + +\end{document} diff --git a/resources/3rdparty/glpk-4.53/doc/glpk.pdf b/resources/3rdparty/glpk-4.53/doc/glpk.pdf new file mode 100644 index 0000000000000000000000000000000000000000..670f58b3c56502d8749e805bbcd9b796fe2a4bc6 GIT binary patch literal 478088 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%0D+S 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	qGs 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%0ALZs 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�N~&evmRlE^te5Ju+ouTbJ+BkeG-}K! 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 ZbYXIIcyeWC3N$w}I5Ig3B_%~qMhZoW#Cre$ literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/doc/glpk.tex b/resources/3rdparty/glpk-4.53/doc/glpk.tex new file mode 100644 index 000000000..dbff90a66 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk.tex @@ -0,0 +1,167 @@ +%* glpk.tex *% + +%*********************************************************************** +% This code is part of GLPK (GNU Linear Programming Kit). +% +% Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +% 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +% Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +% reserved. E-mail: <mao@gnu.org>. +% +% GLPK 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 3 of the License, or +% (at your option) any later version. +% +% GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +%*********************************************************************** + +\documentclass[11pt]{report} +\usepackage{amssymb} +\usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, +urlcolor=blue]{hyperref} +\usepackage{indentfirst} +\usepackage{lscape} +\usepackage[all]{xy} + +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{8.5in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +\setlength{\itemsep}{\parskip} +\setlength{\parsep}{0pt} +\setlength{\leftmargini}{\parindent} +\renewcommand{\labelitemi}{---} + +\def\para#1{\noindent{\bf#1}} +\def\synopsis{\para{Synopsis}} +\def\description{\para{Description}} +\def\returns{\para{Returns}} + +\renewcommand\contentsname{\sf\bfseries Contents} +\renewcommand\chaptername{\sf\bfseries Chapter} +\renewcommand\appendixname{\sf\bfseries Appendix} + +\newenvironment{retlist} +{ \def\arraystretch{1.5} + \noindent + \begin{tabular}{@{}p{1in}@{}p{5.5in}@{}} +} +{\end{tabular}} + +\begin{document} + +\thispagestyle{empty} + +\begin{center} + +\vspace*{1.5in} + +\begin{huge} +\sf\bfseries GNU Linear Programming Kit +\end{huge} + +\vspace{0.5in} + +\begin{LARGE} +\sf Reference Manual +\end{LARGE} + +\vspace{0.5in} + +\begin{LARGE} +\sf for GLPK Version 4.52 +\end{LARGE} + +\vspace{0.5in} +\begin{Large} +\sf (DRAFT, July 2013) +\end{Large} +\end{center} + +\newpage + +\vspace*{1in} + +\vfill + +\noindent +The GLPK package is part of the GNU Project released under the aegis of +GNU. + +\noindent +Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +reserved. + +\noindent +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +02110-1301, USA. + +\noindent +Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + +\noindent +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that +the entire resulting derived work is distributed under the terms of +a permission notice identical to this one. + +\noindent +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +{\setlength{\parskip}{0pt} +\tableofcontents +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\include{glpk01} + +\include{glpk02} + +\include{glpk03} + +\include{glpk04} + +\include{glpk05} + +\include{glpk06} + +\appendix + +\include{glpk07} + +\include{glpk08} + +\include{glpk09} + +\include{glpk10} + +\include{glpk11} + +\include{glpk12} + +\end{document} diff --git a/resources/3rdparty/glpk-4.53/doc/glpk01.tex b/resources/3rdparty/glpk-4.53/doc/glpk01.tex new file mode 100644 index 000000000..29ed67cce --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk01.tex @@ -0,0 +1,343 @@ +%* glpk01.tex *% + +\chapter{Introduction} + +GLPK (\underline{G}NU \underline{L}inear \underline{P}rogramming +\underline{K}it) is a set of routines written in the ANSI C programming +language and organized in the form of a callable library. It is +intended for solving linear programming (LP), mixed integer programming +(MIP), and other related problems. + +\section{LP problem} +\label{seclp} + +GLPK assumes the following formulation of {\it linear programming (LP)} +problem: + +\medskip\noindent +\hspace{.5in} minimize (or maximize) +$$z = c_1x_{m+1} + c_2x_{m+2} + \dots + c_nx_{m+n} + c_0 \eqno (1.1)$$ +\hspace{.5in} subject to linear constraints +$$ +\begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} +x_1&=&a_{11}x_{m+1}&+&a_{12}x_{m+2}&+ \dots +&a_{1n}x_{m+n} \\ +x_2&=&a_{21}x_{m+1}&+&a_{22}x_{m+2}&+ \dots +&a_{2n}x_{m+n} \\ +\multicolumn{7}{c} +{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .} \\ +x_m&=&a_{m1}x_{m+1}&+&a_{m2}x_{m+2}&+ \dots +&a_{mn}x_{m+n} \\ +\end{array} \eqno (1.2) +$$ +\hspace{.5in} and bounds of variables +$$ +\begin{array}{r@{\:}c@{\:}c@{\:}c@{\:}l} +l_1&\leq&x_1&\leq&u_1 \\ +l_2&\leq&x_2&\leq&u_2 \\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .}\\ +l_{m+n}&\leq&x_{m+n}&\leq&u_{m+n} \\ +\end{array} \eqno (1.3) +$$ + +\medskip\noindent +where: $x_1, x_2, \dots, x_m$ are auxiliary variables; +$x_{m+1}, x_{m+2}, \dots, x_{m+n}$ are structural variables; +$z$ is the objective function; +$c_1, c_2, \dots, c_n$ are objective coefficients; +$c_0$ is the constant term (``shift'') of the objective function; +$a_{11}, a_{12}, \dots, a_{mn}$ are constraint coefficients; +$l_1, l_2, \dots, l_{m+n}$ are lower bounds of variables; +$u_1, u_2, \dots, u_{m+n}$ are upper bounds of variables. + +Auxiliary variables are also called {\it rows}, because they correspond +to rows of the constraint matrix (i.e. a matrix built of the constraint +coefficients). Similarly, structural variables are also called +{\it columns}, because they correspond to columns of the constraint +matrix. + +Bounds of variables can be finite as well as infinite. Besides, lower +and upper bounds can be equal to each other. Thus, the following types +of variables are possible: + +\begin{center} +\begin{tabular}{r@{}c@{}ll} +\multicolumn{3}{c}{Bounds of variable} & Type of variable \\ +\hline +$-\infty <$ &$\ x_k\ $& $< +\infty$ & Free (unbounded) variable \\ +$l_k \leq$ &$\ x_k\ $& $< +\infty$ & Variable with lower bound \\ +$-\infty <$ &$\ x_k\ $& $\leq u_k$ & Variable with upper bound \\ +$l_k \leq$ &$\ x_k\ $& $\leq u_k$ & Double-bounded variable \\ +$l_k =$ &$\ x_k\ $& $= u_k$ & Fixed variable \\ +\end{tabular} +\end{center} + +\noindent +Note that the types of variables shown above are applicable to +structural as well as to auxiliary variables. + +To solve the LP problem (1.1)---(1.3) is to find such values of all +structural and auxiliary variables, which: + +\vspace*{-10pt} + +\begin{itemize}\setlength{\itemsep}{0pt} +\item satisfy to all the linear constraints (1.2), and + +\item are within their bounds (1.3), and + +\item provide smallest (in case of minimization) or largest (in case of +maximization) value of the objective function (1.1). +\end{itemize} + +\section{MIP problem} + +{\it Mixed integer linear programming (MIP)} problem is an LP problem +in which some variables are additionally required to be integer. + +GLPK assumes that MIP problem has the same formulation as ordinary +(pure) LP problem (1.1)---(1.3), i.e. includes auxiliary and structural +variables, which may have lower and/or upper bounds. However, in case +of MIP problem some variables may be required to be integer. This +additional constraint means that a value of each {\it integer variable} +must be only integer number. (Should note that GLPK allows only +structural variables to be of integer kind.) + +\section{Using the package} + +\subsection{Brief example} + +In order to understand what GLPK is from the user's standpoint, +consider the following simple LP problem: + +\medskip + +\noindent +\hspace{.5in} maximize +$$z = 10 x_1 + 6 x_2 + 4 x_3$$ +\hspace{.5in} subject to +$$ +\begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} +x_1 &+&x_2 &+&x_3 &\leq 100 \\ +10 x_1 &+& 4 x_2 & +&5 x_3 & \leq 600 \\ +2 x_1 &+& 2 x_2 & +& 6 x_3 & \leq 300 \\ +\end{array} +$$ +\hspace{.5in} where all variables are non-negative +$$x_1 \geq 0, \ x_2 \geq 0, \ x_3 \geq 0$$ + +At first, this LP problem should be transformed to the standard form +(1.1)---(1.3). This can be easily done by introducing auxiliary +variables, by one for each original inequality constraint. Thus, the +problem can be reformulated as follows: + +\medskip + +\noindent +\hspace{.5in} maximize +$$z = 10 x_1 + 6 x_2 + 4 x_3$$ +\hspace{.5in} subject to +$$ +\begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} +p& = &x_1 &+&x_2 &+&x_3 \\ +q& = &10 x_1 &+& 4 x_2 &+& 5 x_3 \\ +r& = &2 x_1 &+& 2 x_2 &+& 6 x_3 \\ +\end{array} +$$ +\hspace{.5in} and bounds of variables +$$ +\begin{array}{ccc} +\nonumber -\infty < p \leq 100 && 0 \leq x_1 < +\infty \\ +\nonumber -\infty < q \leq 600 && 0 \leq x_2 < +\infty \\ +\nonumber -\infty < r \leq 300 && 0 \leq x_3 < +\infty \\ +\end{array} +$$ + +\medskip + +where $p, q, r$ are auxiliary variables (rows), and $x_1, x_2, x_3$ are +structural variables (columns). + +The example C program shown below uses GLPK API routines in order to +solve this LP problem.\footnote{If you just need to solve LP or MIP +instance, you may write it in MPS or CPLEX LP format and then use the +GLPK stand-alone solver to obtain a solution. This is much less +time-consuming than programming in C with GLPK API routines.} + +\begin{footnotesize} +\begin{verbatim} +/* sample.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *lp; + int ia[1+1000], ja[1+1000]; + double ar[1+1000], z, x1, x2, x3; +s1: lp = glp_create_prob(); +s2: glp_set_prob_name(lp, "sample"); +s3: glp_set_obj_dir(lp, GLP_MAX); +s4: glp_add_rows(lp, 3); +s5: glp_set_row_name(lp, 1, "p"); +s6: glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 100.0); +s7: glp_set_row_name(lp, 2, "q"); +s8: glp_set_row_bnds(lp, 2, GLP_UP, 0.0, 600.0); +s9: glp_set_row_name(lp, 3, "r"); +s10: glp_set_row_bnds(lp, 3, GLP_UP, 0.0, 300.0); +s11: glp_add_cols(lp, 3); +s12: glp_set_col_name(lp, 1, "x1"); +s13: glp_set_col_bnds(lp, 1, GLP_LO, 0.0, 0.0); +s14: glp_set_obj_coef(lp, 1, 10.0); +s15: glp_set_col_name(lp, 2, "x2"); +s16: glp_set_col_bnds(lp, 2, GLP_LO, 0.0, 0.0); +s17: glp_set_obj_coef(lp, 2, 6.0); +s18: glp_set_col_name(lp, 3, "x3"); +s19: glp_set_col_bnds(lp, 3, GLP_LO, 0.0, 0.0); +s20: glp_set_obj_coef(lp, 3, 4.0); +s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */ +s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2] = 1 */ +s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3] = 1 */ +s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */ +s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1] = 2 */ +s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2] = 4 */ +s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2] = 2 */ +s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3] = 5 */ +s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3] = 6 */ +s30: glp_load_matrix(lp, 9, ia, ja, ar); +s31: glp_simplex(lp, NULL); +s32: z = glp_get_obj_val(lp); +s33: x1 = glp_get_col_prim(lp, 1); +s34: x2 = glp_get_col_prim(lp, 2); +s35: x3 = glp_get_col_prim(lp, 3); +s36: printf("\nz = %g; x1 = %g; x2 = %g; x3 = %g\n", + z, x1, x2, x3); +s37: glp_delete_prob(lp); + return 0; +} + +/* eof */ +\end{verbatim} +\end{footnotesize} + +The statement \verb|s1| creates a problem object. Being created the +object is initially empty. The statement \verb|s2| assigns a symbolic +name to the problem object. + +The statement \verb|s3| calls the routine \verb|glp_set_obj_dir| in +order to set the optimization direction flag, where \verb|GLP_MAX| +means maximization. + +The statement \verb|s4| adds three rows to the problem object. + +The statement \verb|s5| assigns the symbolic name `\verb|p|' to the +first row, and the statement \verb|s6| sets the type and bounds of the +first row, where \verb|GLP_UP| means that the row has an upper bound. +The statements \verb|s7|, \verb|s8|, \verb|s9|, \verb|s10| are used in +the same way in order to assign the symbolic names `\verb|q|' and +`\verb|r|' to the second and third rows and set their types and bounds. + +The statement \verb|s11| adds three columns to the problem object. + +The statement \verb|s12| assigns the symbolic name `\verb|x1|' to the +first column, the statement \verb|s13| sets the type and bounds of the +first column, where \verb|GLP_LO| means that the column has an lower +bound, and the statement \verb|s14| sets the objective coefficient for +the first column. The statements \verb|s15|---\verb|s20| are used in +the same way in order to assign the symbolic names `\verb|x2|' and +`\verb|x3|' to the second and third columns and set their types, +bounds, and objective coefficients. + +The statements \verb|s21|---\verb|s29| prepare non-zero elements of the +constraint matrix (i.e. constraint coefficients). Row indices of each +element are stored in the array \verb|ia|, column indices are stored in +the array \verb|ja|, and numerical values of corresponding elements are +stored in the array \verb|ar|. Then the statement \verb|s30| calls +the routine \verb|glp_load_matrix|, which loads information from these +three arrays into the problem object. + +Now all data have been entered into the problem object, and therefore +the statement \verb|s31| calls the routine \verb|glp_simplex|, which is +a driver to the simplex method, in order to solve the LP problem. This +routine finds an optimal solution and stores all relevant information +back into the problem object. + +The statement \verb|s32| obtains a computed value of the objective +function, and the statements \verb|s33|---\verb|s35| obtain computed +values of structural variables (columns), which correspond to the +optimal basic solution found by the solver. + +The statement \verb|s36| writes the optimal solution to the standard +output. The printout may look like follows: + +\begin{footnotesize} +\begin{verbatim} +* 0: objval = 0.000000000e+00 infeas = 0.000000000e+00 (0) +* 2: objval = 7.333333333e+02 infeas = 0.000000000e+00 (0) +OPTIMAL SOLUTION FOUND + +z = 733.333; x1 = 33.3333; x2 = 66.6667; x3 = 0 +\end{verbatim} +\end{footnotesize} + +Finally, the statement \verb|s37| calls the routine +\verb|glp_delete_prob|, which frees all the memory allocated to the +problem object. + +\subsection{Compiling} + +The GLPK package has the only header file \verb|glpk.h|, which should +be available on compiling a C (or C++) program using GLPK API routines. + +If the header file is installed in the default location +\verb|/usr/local/include|, the following typical command may be used to +compile, say, the example C program described above with the GNU C +compiler: + +\begin{verbatim} + $ gcc -c sample.c +\end{verbatim} + +If \verb|glpk.h| is not in the default location, the corresponding +directory containing it should be made known to the C compiler through +\verb|-I| option, for example: + +\begin{verbatim} + $ gcc -I/foo/bar/glpk-4.15/include -c sample.c +\end{verbatim} + +In any case the compilation results in an object file \verb|sample.o|. + +\subsection{Linking} + +The GLPK library is a single file \verb|libglpk.a|. (On systems which +support shared libraries there may be also a shared version of the +library \verb|libglpk.so|.) + +If the library is installed in the default +location \verb|/usr/local/lib|, the following typical command may be +used to link, say, the example C program described above against with +the library: + +\begin{verbatim} + $ gcc sample.o -lglpk -lm +\end{verbatim} + +If the GLPK library is not in the default location, the corresponding +directory containing it should be made known to the linker through +\verb|-L| option, for example: + +\begin{verbatim} + $ gcc -L/foo/bar/glpk-4.15 sample.o -lglpk -lm +\end{verbatim} + +Depending on configuration of the package linking against with the GLPK +library may require optional libraries, in which case these libraries +should be also made known to the linker, for example: + +\begin{verbatim} + $ gcc sample.o -lglpk -lgmp -lm +\end{verbatim} + +For more details about configuration options of the GLPK package see +Appendix \ref{install}, page \pageref{install}. + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk02.tex b/resources/3rdparty/glpk-4.53/doc/glpk02.tex new file mode 100644 index 000000000..c2663026e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk02.tex @@ -0,0 +1,3428 @@ +%* glpk02.tex *% + +\chapter{Basic API Routines} + +\section{General conventions} + +\subsection{Library header} + +All GLPK API data types and routines are defined in the header file +\verb|glpk.h|. It should be included in all source files which use +GLPK API, either directly or indirectly through some other header file +as follows: + +\begin{verbatim} + #include <glpk.h> +\end{verbatim} + +\subsection{Error handling} + +If some GLPK API routine detects erroneous or incorrect data passed by +the application program, it writes appropriate diagnostic messages to +the terminal and then abnormally terminates the application program. +In most practical cases this allows to simplify programming by avoiding +numerous checks of return codes. Thus, in order to prevent crashing the +application program should check all data, which are suspected to be +incorrect, before calling GLPK API routines. + +Should note that this kind of error handling is used only in cases of +incorrect data passed by the application program. If, for example, the +application program calls some GLPK API routine to read data from an +input file and these data are incorrect, the GLPK API routine reports +about error in the usual way by means of the return code. + +\subsection{Thread safety} + +The standard version of GLPK API is {\it not} thread safe and therefore +should not be used in multi-threaded programs. + +\subsection{Array indexing} + +Normally all GLPK API routines start array indexing from 1, not from 0 +(except the specially stipulated cases). This means, for example, that +if some vector $x$ of the length $n$ is passed as an array to some GLPK +API routine, the latter expects vector components to be placed in +locations \verb|x[1]|, \verb|x[2]|, \dots, \verb|x[n]|, and the +location \verb|x[0]| normally is not used. + +To avoid indexing errors it is most convenient and most reliable to +declare the array \verb|x| as follows: + +\begin{verbatim} + double x[1+n]; +\end{verbatim} + +\noindent +or to allocate it as follows: + +\begin{verbatim} + double *x; + . . . + x = calloc(1+n, sizeof(double)); + . . . +\end{verbatim} + +\noindent +In both cases one extra location \verb|x[0]| is reserved that allows +passing the array to GLPK routines in a usual way. + +\section{Problem object} + +All GLPK API routines deal with so called {\it problem object}, which +is a program object of type \verb|glp_prob| and intended to represent +a particular LP or MIP instance. + +The type \verb|glp_prob| is a data structure declared in the header +file \verb|glpk.h| as follows: + +\begin{verbatim} + typedef struct glp_prob glp_prob; +\end{verbatim} + +Problem objects (i.e. program objects of the \verb|glp_prob| type) are +allocated and managed internally by the GLPK API routines. The +application program should never use any members of the \verb|glp_prob| +structure directly and should deal only with pointers to these objects +(that is, \verb|glp_prob *| values). + +The problem object consists of the following segments: + +\vspace*{-8pt} + +\begin{itemize}\setlength{\itemsep}{0pt} +\item problem segment, + +\item basis segment, + +\item interior-point segment, and + +\item MIP segment. +\end{itemize} + +\subsection{Problem segment} + +The {\it problem segment} contains original LP/MIP data, which +corresponds to the problem formulation (1.1)---(1.3) (see Section +\ref{seclp}, page \pageref{seclp}). This segment includes the following +components: + +\vspace*{-8pt} + +\begin{itemize}\setlength{\itemsep}{0pt} +\item rows (auxiliary variables), + +\item columns (structural variables), + +\item objective function, and + +\item constraint matrix. +\end{itemize} + +\vspace*{-7pt} + +Rows and columns have the same set of the following attributes: + +\vspace*{-7pt} + +\begin{itemize}\setlength{\itemsep}{0pt} +\item ordinal number, + +\item symbolic name (1 up to 255 arbitrary graphic characters), + +\item type (free, lower bound, upper bound, double bound, fixed), + +\item numerical values of lower and upper bounds, + +\item scale factor. +\end{itemize} + +\vspace*{-7pt} + +{\it Ordinal numbers} are intended for referencing rows and columns. +Row ordinal numbers are integers $1, 2, \dots, m$, and column ordinal +numbers are integers $1, 2, \dots, n$, where $m$ and $n$ are, +respectively, the current number of rows and columns in the problem +object. + +{\it Symbolic names} are intended for informational purposes. They also +can be used for referencing rows and columns. + +{\it Types and bounds} of rows (auxiliary variables) and columns +(structural variables) are explained above (see Section \ref{seclp}, +page \pageref{seclp}). + +{\it Scale factors} are used internally for scaling rows and columns of +the constraint matrix. + +Information about the {\it objective function} includes numerical +values of objective coefficients and a flag, which defines the +optimization direction (i.e. minimization or maximization). + +The {\it constraint matrix} is a $m \times n$ rectangular matrix built +of constraint coefficients $a_{ij}$, which defines the system of linear +constraints (1.2) (see Section \ref{seclp}, page \pageref{seclp}). This +matrix is stored in the problem object in both row-wise and column-wise +sparse formats. + +Once the problem object has been created, the application program can +access and modify any components of the problem segment in arbitrary +order. + +\subsection{Basis segment} + +The {\it basis segment} of the problem object keeps information related +to the current basic solution. It includes: + +\vspace*{-8pt} + +\begin{itemize}\setlength{\itemsep}{0pt} +\item row and column statuses, + +\item basic solution statuses, + +\item factorization of the current basis matrix, and + +\item basic solution components. +\end{itemize} + +\vspace*{-8pt} + +The {\it row and column statuses} define which rows and columns are +basic and which are non-basic. These statuses may be assigned either by +the application program of by some API routines. Note that these +statuses are always defined independently on whether the corresponding +basis is valid or not. + +The {\it basic solution statuses} include the {\it primal status} and +the {\it dual status}, which are set by the simplex-based solver once +the problem has been solved. The primal status shows whether a primal +basic solution is feasible, infeasible, or undefined. The dual status +shows the same for a dual basic solution. + +The {\it factorization of the basis matrix} is some factorized form +(like {\it LU}-factorization) of the current basis matrix (defined by +the current row and column statuses). The factorization is used by +simplex-based solvers and kept when the solver terminates the search. +This feature allows efficiently reoptimizing the problem after some +modifications (for example, after changing some bounds or objective +coefficients). It also allows performing the post-optimal analysis (for +example, computing components of the simplex table, etc.). + +The {\it basic solution components} include primal and dual values of +all auxiliary and structural variables for the most recently obtained +basic solution. + +\subsection{Interior-point segment} + +The {\it interior-point segment} contains interior-point solution +components, which include the solution status, and primal and dual +values of all auxiliary and structural variables. + +\subsection{MIP segment} + +The {\it MIP segment} is used only for MIP problems. This segment +includes: + +\vspace*{-8pt} + +\begin{itemize}\setlength{\itemsep}{0pt} +\item column kinds, + +\item MIP solution status, and + +\item MIP solution components. +\end{itemize} + +\vspace*{-8pt} + +The {\it column kinds} define which columns (i.e. structural variables) +are integer and which are continuous. + +The {\it MIP solution status} is set by the MIP solver and shows whether +a MIP solution is integer optimal, integer feasible (non-optimal), or +undefined. + +The {\it MIP solution components} are computed by the MIP solver and +include primal values of all auxiliary and structural variables for the +most recently obtained MIP solution. + +Note that in case of MIP problem the basis segment corresponds to +the optimal solution of LP relaxation, which is also available to the +application program. + +Currently the search tree is not kept in the MIP segment, so if the +search has been terminated, it cannot be continued. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Problem creating and modifying routines} + +\subsection{glp\_create\_prob --- create problem object} + +\synopsis + +\begin{verbatim} + glp_prob *glp_create_prob(void); +\end{verbatim} + +\description + +The routine \verb|glp_create_prob| creates a new problem object, which +initially is ``empty'', i.e. has no rows and columns. + +\returns + +The routine returns a pointer to the created object, which should be +used in any subsequent operations on this object. + +\subsection{glp\_set\_prob\_name --- assign (change) problem name} + +\synopsis + +\begin{verbatim} + void glp_set_prob_name(glp_prob *P, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_prob_name| assigns a given symbolic +\verb|name| (1 up to 255 characters) to the specified problem object. + +If the parameter \verb|name| is \verb|NULL| or empty string, the +routine erases an existing symbolic name of the problem object. + +\subsection{glp\_set\_obj\_name --- assign (change) objective function +name} + +\synopsis + +\begin{verbatim} + void glp_set_obj_name(glp_prob *P, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_obj_name| assigns a given symbolic +\verb|name| (1 up to 255 characters) to the objective function of the +specified problem object. + +If the parameter \verb|name| is \verb|NULL| or empty string, the +routine erases an existing symbolic name of the objective function. + +\newpage + +\subsection{glp\_set\_obj\_dir --- set (change) optimization direction +flag} + +\synopsis + +\begin{verbatim} + void glp_set_obj_dir(glp_prob *P, int dir); +\end{verbatim} + +\description + +The routine \verb|glp_set_obj_dir| sets (changes) the optimization +direction flag (i.e. ``sense'' of the objective function) as specified +by the parameter \verb|dir|: + +\verb|GLP_MIN| means minimization; + +\verb|GLP_MAX| means maximization. + +\noindent +(Note that by default the problem is minimization.) + +\subsection{glp\_add\_rows --- add new rows to problem object} + +\synopsis + +\begin{verbatim} + int glp_add_rows(glp_prob *P, int nrs); +\end{verbatim} + +\description + +The routine \verb|glp_add_rows| adds \verb|nrs| rows (constraints) to +the specified problem object. New rows are always added to the end of +the row list, so the ordinal numbers of existing rows are not changed. + +Being added each new row is initially free (unbounded) and has empty +list of the constraint coefficients. + +\returns + +The routine \verb|glp_add_rows| returns the ordinal number of the first +new row added to the problem object. + +\subsection{glp\_add\_cols --- add new columns to problem object} + +\synopsis + +\begin{verbatim} + int glp_add_cols(glp_prob *P, int ncs); +\end{verbatim} + +\description + +The routine \verb|glp_add_cols| adds \verb|ncs| columns (structural +variables) to the specified problem object. New columns are always +added to the end of the column list, so the ordinal numbers of existing +columns are not changed. + +Being added each new column is initially fixed at zero and has empty +list of the constraint coefficients. + +\returns + +The routine \verb|glp_add_cols| returns the ordinal number of the first +new column added to the problem object. + +\subsection{glp\_set\_row\_name --- assign (change) row name} + +\synopsis + +\begin{verbatim} + void glp_set_row_name(glp_prob *P, int i, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_row_name| assigns a given symbolic +\verb|name| (1 up to 255 characters) to \verb|i|-th row (auxiliary +variable) of the specified problem object. + +If the parameter \verb|name| is \verb|NULL| or empty string, the +routine erases an existing name of $i$-th row. + +\subsection{glp\_set\_col\_name --- assign (change) column name} + +\synopsis + +\begin{verbatim} + void glp_set_col_name(glp_prob *P, int j, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_col_name| assigns a given symbolic +\verb|name| (1 up to 255 characters) to \verb|j|-th column (structural +variable) of the specified problem object. + +If the parameter \verb|name| is \verb|NULL| or empty string, the +routine erases an existing name of $j$-th column. + +\subsection{glp\_set\_row\_bnds --- set (change) row bounds} + +\synopsis + +{\tt void glp\_set\_row\_bnds(glp\_prob *P, int i, int type, +double lb, double ub);} + +\description + +The routine \verb|glp_set_row_bnds| sets (changes) the type and bounds +of \verb|i|-th row (auxiliary variable) of the specified problem +object. + +The parameters \verb|type|, \verb|lb|, and \verb|ub| specify the type, +lower bound, and upper bound, respectively, as follows: + +\begin{center} +\begin{tabular}{cr@{}c@{}ll} +Type & \multicolumn{3}{c}{Bounds} & Comment \\ +\hline +\verb|GLP_FR| & $-\infty <$ &$\ x\ $& $< +\infty$ + & Free (unbounded) variable \\ +\verb|GLP_LO| & $lb \leq$ &$\ x\ $& $< +\infty$ + & Variable with lower bound \\ +\verb|GLP_UP| & $-\infty <$ &$\ x\ $& $\leq ub$ + & Variable with upper bound \\ +\verb|GLP_DB| & $lb \leq$ &$\ x\ $& $\leq ub$ + & Double-bounded variable \\ +\verb|GLP_FX| & $lb =$ &$\ x\ $& $= ub$ + & Fixed variable \\ +\end{tabular} +\end{center} + +\noindent +where $x$ is the auxiliary variable associated with $i$-th row. + +If the row has no lower bound, the parameter \verb|lb| is ignored. If +the row has no upper bound, the parameter \verb|ub| is ignored. If the +row is an equality constraint (i.e. the corresponding auxiliary +variable is of fixed type), only the parameter \verb|lb| is used while +the parameter \verb|ub| is ignored. + +Being added to the problem object each row is initially free, i.e. its +type is \verb|GLP_FR|. + +\subsection{glp\_set\_col\_bnds --- set (change) column bounds} + +\synopsis + +{\tt void glp\_set\_col\_bnds(glp\_prob *P, int j, int type, +double lb, double ub);} + +\description + +The routine \verb|glp_set_col_bnds| sets (changes) the type and bounds +of \verb|j|-th column (structural variable) of the specified problem +object. + +The parameters \verb|type|, \verb|lb|, and \verb|ub| specify the type, +lower bound, and upper bound, respectively, as follows: + +\begin{center} +\begin{tabular}{cr@{}c@{}ll} +Type & \multicolumn{3}{c}{Bounds} & Comment \\ +\hline +\verb|GLP_FR| & $-\infty <$ &$\ x\ $& $< +\infty$ + & Free (unbounded) variable \\ +\verb|GLP_LO| & $lb \leq$ &$\ x\ $& $< +\infty$ + & Variable with lower bound \\ +\verb|GLP_UP| & $-\infty <$ &$\ x\ $& $\leq ub$ + & Variable with upper bound \\ +\verb|GLP_DB| & $lb \leq$ &$\ x\ $& $\leq ub$ + & Double-bounded variable \\ +\verb|GLP_FX| & $lb =$ &$\ x\ $& $= ub$ + & Fixed variable \\ +\end{tabular} +\end{center} + +\noindent +where $x$ is the structural variable associated with $j$-th column. + +If the column has no lower bound, the parameter \verb|lb| is ignored. +If the column has no upper bound, the parameter \verb|ub| is ignored. +If the column is of fixed type, only the parameter \verb|lb| is used +while the parameter \verb|ub| is ignored. + +Being added to the problem object each column is initially fixed at +zero, i.e. its type is \verb|GLP_FX| and both bounds are 0. + +\subsection{glp\_set\_obj\_coef --- set (change) objective coefficient +or constant term} + +\synopsis + +\begin{verbatim} + void glp_set_obj_coef(glp_prob *P, int j, double coef); +\end{verbatim} + +\description + +The routine \verb|glp_set_obj_coef| sets (changes) the objective +coefficient at \verb|j|-th column (structural variable). A new value of +the objective coefficient is specified by the parameter \verb|coef|. + +If the parameter \verb|j| is 0, the routine sets (changes) the constant +term (``shift'') of the objective function. + +\newpage + +\subsection{glp\_set\_mat\_row --- set (replace) row of the constraint +matrix} + +\synopsis + +\begin{verbatim} + void glp_set_mat_row(glp_prob *P, int i, int len, const int ind[], + const double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_set_mat_row| stores (replaces) the contents of +\verb|i|-th row of the constraint matrix of the specified problem +object. + +Column indices and numerical values of new row elements should be +placed in locations\linebreak \verb|ind[1]|, \dots, \verb|ind[len]| and +\verb|val[1]|, \dots, \verb|val[len]|, respectively, where +$0 \leq$ \verb|len| $\leq n$ is the new length of $i$-th row, $n$ is +the current number of columns in the problem object. Elements with +identical column indices are not allowed. Zero elements are allowed, +but they are not stored in the constraint matrix. + +If the parameter \verb|len| is 0, the parameters \verb|ind| and/or +\verb|val| can be specified as \verb|NULL|. + +\subsection{glp\_set\_mat\_col --- set (replace) column of the +constr\-aint matrix} + +\synopsis + +\begin{verbatim} + void glp_set_mat_col(glp_prob *P, int j, int len, const int ind[], + const double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_set_mat_col| stores (replaces) the contents of +\verb|j|-th column of the constraint matrix of the specified problem +object. + +Row indices and numerical values of new column elements should be +placed in locations\linebreak \verb|ind[1]|, \dots, \verb|ind[len]| and +\verb|val[1]|, \dots, \verb|val[len]|, respectively, where +$0 \leq$ \verb|len| $\leq m$ is the new length of $j$-th column, $m$ is +the current number of rows in the problem object. Elements with +identical row indices are not allowed. Zero elements are allowed, but +they are not stored in the constraint matrix. + +If the parameter \verb|len| is 0, the parameters \verb|ind| and/or +\verb|val| can be specified as \verb|NULL|. + +\subsection{glp\_load\_matrix --- load (replace) the whole constraint +matrix} + +\synopsis + +\begin{verbatim} + void glp_load_matrix(glp_prob *P, int ne, const int ia[], + const int ja[], const double ar[]); +\end{verbatim} + +\description + +The routine \verb|glp_load_matrix| loads the constraint matrix passed +in the arrays \verb|ia|, \verb|ja|, and \verb|ar| into the specified +problem object. Before loading the current contents of the constraint +matrix is destroyed. + +Constraint coefficients (elements of the constraint matrix) should be +specified as triplets (\verb|ia[k]|, \verb|ja[k]|, \verb|ar[k]|) for +$k=1,\dots,ne$, where \verb|ia[k]| is the row index, \verb|ja[k]| is +the column index, and \verb|ar[k]| is a numeric value of corresponding +constraint coefficient. The parameter \verb|ne| specifies the total +number of (non-zero) elements in the matrix to be loaded. Coefficients +with identical indices are not allowed. Zero coefficients are allowed, +however, they are not stored in the constraint matrix. + +If the parameter \verb|ne| is 0, the parameters \verb|ia|, \verb|ja|, +and/or \verb|ar| can be specified as \verb|NULL|. + +\subsection{glp\_check\_dup --- check for duplicate elements in sparse +matrix} + +\synopsis + +{\tt int glp\_check\_dup(int m, int n, int ne, const int ia[], +const int ja[]);} + +\description + +The routine \verb|glp_check_dup checks| for duplicate elements (that +is, elements with identical indices) in a sparse matrix specified in +the coordinate format. + +The parameters $m$ and $n$ specifies, respectively, the number of rows +and columns in the matrix, $m\geq 0$, $n\geq 0$. + +The parameter {\it ne} specifies the number of (structurally) non-zero +elements in the matrix,\linebreak {\it ne} $\geq 0$. + +Elements of the matrix are specified as doublets $(ia[k],ja[k])$ for +$k=1,\dots,ne$, where $ia[k]$ is a row index, $ja[k]$ is a column +index. + +The routine \verb|glp_check_dup| can be used prior to a call to the +routine \verb|glp_load_matrix| to check that the constraint matrix to +be loaded has no duplicate elements. + +\returns + +\begin{retlist} +0& the matrix representation is correct;\\ +$-k$& indices $ia[k]$ or/and $ja[k]$ are out of range;\\ +$+k$& element $(ia[k],ja[k])$ is duplicate.\\ +\end{retlist} + +\subsection{glp\_sort\_matrix --- sort elements of the constraint +matrix} + +\synopsis + +\begin{verbatim} + void glp_sort_matrix(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_sort_matrix| sorts elements of the constraint +matrix by rebuilding its row and column linked lists. + +On exit from the routine the constraint matrix is not changed, however, +elements in the row linked lists become ordered by ascending column +indices, and the elements in the column linked lists become ordered by +ascending row indices. + +\subsection{glp\_del\_rows --- delete rows from problem object} + +\synopsis + +\begin{verbatim} + void glp_del_rows(glp_prob *P, int nrs, const int num[]); +\end{verbatim} + +\description + +The routine \verb|glp_del_rows| deletes rows from the specified problem +object. Ordinal numbers of rows to be deleted should be placed in +locations \verb|num[1]|, \dots, \verb|num[nrs]|, where ${\tt nrs}>0$. + +Note that deleting rows involves changing ordinal numbers of other +rows remaining in the problem object. New ordinal numbers of the +remaining rows are assigned under the assumption that the original +order of rows is not changed. Let, for example, before deletion there +be five rows $a$, $b$, $c$, $d$, $e$ with ordinal numbers 1, 2, 3, 4, +5, and let rows $b$ and $d$ have been deleted. Then after deletion the +remaining rows $a$, $c$, $e$ are assigned new oridinal numbers 1, 2, 3. + +\subsection{glp\_del\_cols --- delete columns from problem object} + +\synopsis + +\begin{verbatim} + void glp_del_cols(glp_prob *P, int ncs, const int num[]); +\end{verbatim} + +\description + +The routine \verb|glp_del_cols| deletes columns from the specified +problem object. Ordinal numbers of columns to be deleted should be +placed in locations \verb|num[1]|, \dots, \verb|num[ncs]|, where +${\tt ncs}>0$. + +Note that deleting columns involves changing ordinal numbers of other +columns remaining in\linebreak the problem object. New ordinal numbers +of the remaining columns are assigned under the assumption that the +original order of columns is not changed. Let, for example, before +deletion there be six columns $p$, $q$, $r$, $s$, $t$, $u$ with +ordinal numbers 1, 2, 3, 4, 5, 6, and let columns $p$, $q$, $s$ have +been deleted. Then after deletion the remaining columns $r$, $t$, $u$ +are assigned new ordinal numbers 1, 2, 3. + +\subsection{glp\_copy\_prob --- copy problem object content} + +\synopsis + +\begin{verbatim} + void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names); +\end{verbatim} + +\description + +The routine \verb|glp_copy_prob| copies the content of the problem +object \verb|prob| to the problem object \verb|dest|. + +The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, +the routine also copies all symbolic names; otherwise, if it is +\verb|GLP_OFF|, no symbolic names are copied. + +\newpage + +\subsection{glp\_erase\_prob --- erase problem object content} + +\synopsis + +\begin{verbatim} + void glp_erase_prob(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_erase_prob| erases the content of the specified +problem object. The effect of this operation is the same as if the +problem object would be deleted with the routine \verb|glp_delete_prob| +and then created anew with the routine \verb|glp_create_prob|, with the +only exception that the pointer to the problem object remains valid. + +\subsection{glp\_delete\_prob --- delete problem object} + +\synopsis + +\begin{verbatim} + void glp_delete_prob(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_delete_prob| deletes a problem object, which the +parameter \verb|lp| points to, freeing all the memory allocated to this +object. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Problem retrieving routines} + +\subsection{glp\_get\_prob\_name --- retrieve problem name} + +\synopsis + +\begin{verbatim} + const char *glp_get_prob_name(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_prob_name| returns a pointer to an internal +buffer, which contains symbolic name of the problem. However, if the +problem has no assigned name, the routine returns \verb|NULL|. + +\subsection{glp\_get\_obj\_name --- retrieve objective function name} + +\synopsis + +\begin{verbatim} + const char *glp_get_obj_name(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_obj_name| returns a pointer to an internal +buffer, which contains symbolic name assigned to the objective +function. However, if the objective function has no assigned name, the +routine returns \verb|NULL|. + +\subsection{glp\_get\_obj\_dir --- retrieve optimization direction +flag} + +\synopsis + +\begin{verbatim} + int glp_get_obj_dir(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_obj_dir| returns the optimization direction +flag (i.e. ``sense'' of the objective function): + +\verb|GLP_MIN| means minimization; + +\verb|GLP_MAX| means maximization. + +\subsection{glp\_get\_num\_rows --- retrieve number of rows} + +\synopsis + +\begin{verbatim} + int glp_get_num_rows(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_num_rows| returns the current number of rows +in the specified problem object. + +\subsection{glp\_get\_num\_cols --- retrieve number of columns} + +\synopsis + +\begin{verbatim} + int glp_get_num_cols(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_num_cols| returns the current number of +columns in the specified problem object. + +\subsection{glp\_get\_row\_name --- retrieve row name} + +\synopsis + +\begin{verbatim} + const char *glp_get_row_name(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_name| returns a pointer to an internal +buffer, which contains a symbolic name assigned to \verb|i|-th row. +However, if the row has no assigned name, the routine returns +\verb|NULL|. + +\subsection{glp\_get\_col\_name --- retrieve column name} + +\synopsis + +\begin{verbatim} + const char *glp_get_col_name(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_name| returns a pointer to an internal +buffer, which contains a symbolic name assigned to \verb|j|-th column. +However, if the column has no assigned name, the routine returns +\verb|NULL|. + +\subsection{glp\_get\_row\_type --- retrieve row type} + +\synopsis + +\begin{verbatim} + int glp_get_row_type(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_type| returns the type of \verb|i|-th +row, i.e. the type of corresponding auxiliary variable, as follows: + +\verb|GLP_FR| --- free (unbounded) variable; + +\verb|GLP_LO| --- variable with lower bound; + +\verb|GLP_UP| --- variable with upper bound; + +\verb|GLP_DB| --- double-bounded variable; + +\verb|GLP_FX| --- fixed variable. + +\subsection{glp\_get\_row\_lb --- retrieve row lower bound} + +\synopsis + +\begin{verbatim} + double glp_get_row_lb(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_lb| returns the lower bound of +\verb|i|-th row, i.e. the lower bound of corresponding auxiliary +variable. However, if the row has no lower bound, the routine returns +\verb|-DBL_MAX|. + +\vspace*{-4pt} + +\subsection{glp\_get\_row\_ub --- retrieve row upper bound} + +\synopsis + +\begin{verbatim} + double glp_get_row_ub(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_ub| returns the upper bound of +\verb|i|-th row, i.e. the upper bound of corresponding auxiliary +variable. However, if the row has no upper bound, the routine returns +\verb|+DBL_MAX|. + +\vspace*{-4pt} + +\subsection{glp\_get\_col\_type --- retrieve column type} + +\synopsis + +\begin{verbatim} + int glp_get_col_type(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_type| returns the type of \verb|j|-th +column, i.e. the type of corresponding structural variable, as follows: + +\verb|GLP_FR| --- free (unbounded) variable; + +\verb|GLP_LO| --- variable with lower bound; + +\verb|GLP_UP| --- variable with upper bound; + +\verb|GLP_DB| --- double-bounded variable; + +\verb|GLP_FX| --- fixed variable. + +\vspace*{-4pt} + +\subsection{glp\_get\_col\_lb --- retrieve column lower bound} + +\synopsis + +\begin{verbatim} + double glp_get_col_lb(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_lb| returns the lower bound of +\verb|j|-th column, i.e. the lower bound of corresponding structural +variable. However, if the column has no lower bound, the routine +returns \verb|-DBL_MAX|. + +\subsection{glp\_get\_col\_ub --- retrieve column upper bound} + +\synopsis + +\begin{verbatim} + double glp_get_col_ub(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_ub| returns the upper bound of +\verb|j|-th column, i.e. the upper bound of corresponding structural +variable. However, if the column has no upper bound, the routine +returns \verb|+DBL_MAX|. + +\subsection{glp\_get\_obj\_coef --- retrieve objective coefficient or +constant term} + +\synopsis + +\begin{verbatim} + double glp_get_obj_coef(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_obj_coef| returns the objective coefficient +at \verb|j|-th structural variable (column). + +If the parameter \verb|j| is 0, the routine returns the constant term +(``shift'') of the objective function. + +\subsection{glp\_get\_num\_nz --- retrieve number of constraint +coefficients} + +\synopsis + +\begin{verbatim} + int glp_get_num_nz(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_num_nz| returns the number of non-zero +elements in the constraint matrix of the specified problem object. + +\subsection{glp\_get\_mat\_row --- retrieve row of the constraint +matrix} + +\synopsis + +\begin{verbatim} + int glp_get_mat_row(glp_prob *P, int i, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_get_mat_row| scans (non-zero) elements of +\verb|i|-th row of the constraint matrix of the specified problem +object and stores their column indices and numeric values to locations +\verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, +\verb|val[len]|, respectively, where $0\leq{\tt len}\leq n$ is the +number of elements in $i$-th row, $n$ is the number of columns. + +The parameter \verb|ind| and/or \verb|val| can be specified as +\verb|NULL|, in which case corresponding information is not stored. + +\newpage + +\returns + +The routine \verb|glp_get_mat_row| returns the length \verb|len|, i.e. +the number of (non-zero) elements in \verb|i|-th row. + +\subsection{glp\_get\_mat\_col --- retrieve column of the constraint +matrix} + +\synopsis + +\begin{verbatim} + int glp_get_mat_col(glp_prob *P, int j, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_get_mat_col| scans (non-zero) elements of +\verb|j|-th column of the constraint matrix of the specified problem +object and stores their row indices and numeric values to locations +\linebreak \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, +\dots, \verb|val[len]|, respectively, where $0\leq{\tt len}\leq m$ is +the number of elements in $j$-th column, $m$ is the number of rows. + +The parameter \verb|ind| and/or \verb|val| can be specified as +\verb|NULL|, in which case corresponding information is not stored. + +\returns + +The routine \verb|glp_get_mat_col| returns the length \verb|len|, i.e. +the number of (non-zero) elements in \verb|j|-th column. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Row and column searching routines} + +Sometimes it may be necessary to find rows and/or columns by their +names (assigned with the routines \verb|glp_set_row_name| and +\verb|glp_set_col_name|). Though a particular row/column can be found +by its name using simple enumeration of all rows/columns, in case of +large instances such a {\it linear} search may take too long time. + +To significantly reduce the search time the application program may +create the row/column name index, which is an auxiliary data structure +implementing a {\it binary} search. Even in worst cases the search +takes logarithmic time, i.e. the time needed to find a particular row +(or column) by its name is $O(\log_2m)$ (or $O(\log_2n)$), where $m$ +and $n$ are, resp., the number of rows and columns in the problem +object. + +It is important to note that: + +1. On creating the problem object with the routine +\verb|glp_create_prob| the name index is {\it not} created. + +2. The name index can be created (destroyed) at any time with the +routine \verb|glp_create_index| (\verb|glp_delete_index|). Having been +created the name index becomes part of the corresponding problem +object. + +3. The time taken to create the name index is $O[(m+n)\log_2(m+n)]$, +so it is recommended to create the index only once, for example, just +after the problem object was created. + +4. If the name index exists, it is automatically updated every time +the name of a row/column is assigned/changed. The update operation +takes logarithmic time. + +5. If the name index does not exist, the application should not call +the routines \verb|glp_find_row| and \verb|glp_find_col|. Otherwise, +an error message will be issued and abnormal program termination will +occur. + +6. On destroying the problem object with the routine +\verb|glp_delete_prob|, the name index, if exists, is automatically +destroyed. + +\subsection{glp\_create\_index --- create the name index} + +\synopsis + +\begin{verbatim} + void glp_create_index(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_create_index| creates the name index for the +specified problem object. The name index is an auxiliary data +structure, which is intended to quickly (i.e. for logarithmic time) +find rows and columns by their names. + +This routine can be called at any time. If the name index already +exists, the routine does nothing. + +\newpage + +\subsection{glp\_find\_row --- find row by its name} + +\synopsis + +\begin{verbatim} + int glp_find_row(glp_prob *P, const char *name); +\end{verbatim} + +\returns + +The routine \verb|glp_find_row| returns the ordinal number of a row, +which is assigned the specified symbolic \verb|name|. If no such row +exists, the routine returns 0. + +\subsection{glp\_find\_col --- find column by its name} + +\synopsis + +\begin{verbatim} + int glp_find_col(glp_prob *P, const char *name); +\end{verbatim} + +\returns + +The routine \verb|glp_find_col| returns the ordinal number of a column, +which is assigned the specified symbolic \verb|name|. If no such column +exists, the routine returns 0. + +\subsection{glp\_delete\_index --- delete the name index} + +\synopsis + +\begin{verbatim} + void glp_delete_index(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_delete_index| deletes the name index previously +created by the routine\linebreak \verb|glp_create_index| and frees the +memory allocated to this auxiliary data structure. + +This routine can be called at any time. If the name index does not +exist, the routine does nothing. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Problem scaling routines} + +\subsection{Background} + +In GLPK the {\it scaling} means a linear transformation applied to the +constraint matrix to improve its numerical properties.\footnote{In many +cases a proper scaling allows making the constraint matrix to be better +conditioned, i.e. decreasing its condition number, that makes +computations numerically more stable.} + +The main equality is the following: +$$\widetilde{A}=RAS,\eqno(2.1)$$ +where $A=(a_{ij})$ is the original constraint matrix, $R=(r_{ii})>0$ is +a diagonal matrix used to scale rows (constraints), $S=(s_{jj})>0$ is a +diagonal matrix used to scale columns (variables), $\widetilde{A}$ is +the scaled constraint matrix. + +From (2.1) it follows that in the {\it scaled} problem instance each +original constraint coefficient $a_{ij}$ is replaced by corresponding +scaled constraint coefficient: +$$\widetilde{a}_{ij}=r_{ii}a_{ij}s_{jj}.\eqno(2.2)$$ + +Note that the scaling is performed internally and therefore +transparently to the user. This means that on API level the user always +deal with unscaled data. + +Scale factors $r_{ii}$ and $s_{jj}$ can be set or changed at any time +either directly by the application program in a problem specific way +(with the routines \verb|glp_set_rii| and \verb|glp_set_sjj|), or by +some API routines intended for automatic scaling. + +\subsection{glp\_set\_rii --- set (change) row scale factor} + +\synopsis + +\begin{verbatim} + void glp_set_rii(glp_prob *P, int i, double rii); +\end{verbatim} + +\description + +The routine \verb|glp_set_rii| sets (changes) the scale factor $r_{ii}$ +for $i$-th row of the specified problem object. + +\subsection{glp\_set\_sjj --- set (change) column scale factor} + +\synopsis + +\begin{verbatim} + void glp_set_sjj(glp_prob *P, int j, double sjj); +\end{verbatim} + +\description + +The routine \verb|glp_set_sjj| sets (changes) the scale factor $s_{jj}$ +for $j$-th column of the specified problem object. + +\subsection{glp\_get\_rii --- retrieve row scale factor} + +\synopsis + +\begin{verbatim} + double glp_get_rii(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_rii| returns current scale factor $r_{ii}$ +for $i$-th row of the specified problem object. + +\vspace*{-6pt} + +\subsection{glp\_get\_sjj --- retrieve column scale factor} + +\vspace*{-4pt} + +\synopsis + +\begin{verbatim} + double glp_get_sjj(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_sjj| returns current scale factor $s_{jj}$ +for $j$-th column of the specified problem object. + +\vspace*{-6pt} + +\subsection{glp\_scale\_prob --- scale problem data} + +\vspace*{-4pt} + +\synopsis + +\begin{verbatim} + void glp_scale_prob(glp_prob *P, int flags); +\end{verbatim} + +\description + +The routine \verb|glp_scale_prob| performs automatic scaling of problem +data for the specified problem object. + +The parameter \verb|flags| specifies scaling options used by the +routine. The options can be combined with the bitwise OR operator and +may be the following: + +\verb|GLP_SF_GM | --- perform geometric mean scaling; + +\verb|GLP_SF_EQ | --- perform equilibration scaling; + +\verb|GLP_SF_2N | --- round scale factors to nearest power of two; + +\verb|GLP_SF_SKIP| --- skip scaling, if the problem is well scaled. + +The parameter \verb|flags| may be also specified as \verb|GLP_SF_AUTO|, +in which case the routine chooses the scaling options automatically. + +\vspace*{-6pt} + +\subsection{glp\_unscale\_prob --- unscale problem data} + +\vspace*{-4pt} + +\synopsis + +\begin{verbatim} + void glp_unscale_prob(glp_prob *P); +\end{verbatim} + +The routine \verb|glp_unscale_prob| performs unscaling of problem data +for the specified problem object. + +``Unscaling'' means replacing the current scaling matrices $R$ and $S$ +by unity matrices that cancels the scaling effect. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{LP basis constructing routines} + +\subsection{Background} + +To start the search the simplex method needs a valid initial basis. +In GLPK the basis is completely defined by a set of {\it statuses} +assigned to {\it all} (auxiliary and structural) variables, where the +status may be one of the following: + +\verb|GLP_BS| --- basic variable; + +\verb|GLP_NL| --- non-basic variable having active lower bound; + +\verb|GLP_NU| --- non-basic variable having active upper bound; + +\verb|GLP_NF| --- non-basic free variable; + +\verb|GLP_NS| --- non-basic fixed variable. + +The basis is {\it valid}, if the basis matrix, which is a matrix built +of columns of the augmented constraint matrix $(I\:|-A)$ corresponding +to basic variables, is non-singular. This, in particular, means that +the number of basic variables must be the same as the number of rows in +the problem object. (For more details see Section \ref{lpbasis}, page +\pageref{lpbasis}.) + +Any initial basis may be constructed (or restored) with the API +routines \verb|glp_set_row_stat| and \verb|glp_set_col_stat| by +assigning appropriate statuses to auxiliary and structural variables. +Another way to construct an initial basis is to use API routines like +\verb|glp_adv_basis|, which implement so called +{\it crashing}.\footnote{This term is from early linear programming +systems and means a heuristic to construct a valid initial basis.} Note +that on normal exit the simplex solver remains the basis valid, so in +case of reoptimization there is no need to construct an initial basis +from scratch. + +\subsection{glp\_set\_row\_stat --- set (change) row status} + +\synopsis + +\begin{verbatim} + void glp_set_row_stat(glp_prob *P, int i, int stat); +\end{verbatim} + +\description + +The routine \verb|glp_set_row_stat| sets (changes) the current status +of \verb|i|-th row (auxiliary variable) as specified by the parameter +\verb|stat|: + +\verb|GLP_BS| --- make the row basic (make the constraint inactive); + +\verb|GLP_NL| --- make the row non-basic (make the constraint active); + +\verb|GLP_NU| --- make the row non-basic and set it to the upper bound; +if the row is not double-bounded, this status is equivalent to +\verb|GLP_NL| (only in case of this routine); + +\verb|GLP_NF| --- the same as \verb|GLP_NL| (only in case of this +routine); + +\verb|GLP_NS| --- the same as \verb|GLP_NL| (only in case of this +routine). + +\newpage + +\subsection{glp\_set\_col\_stat --- set (change) column status} + +\synopsis + +\begin{verbatim} + void glp_set_col_stat(glp_prob *P, int j, int stat); +\end{verbatim} + +\description + +The routine \verb|glp_set_col_stat sets| (changes) the current status +of \verb|j|-th column (structural variable) as specified by the +parameter \verb|stat|: + +\verb|GLP_BS| --- make the column basic; + +\verb|GLP_NL| --- make the column non-basic; + +\verb|GLP_NU| --- make the column non-basic and set it to the upper +bound; if the column is not double-bounded, this status is equivalent +to \verb|GLP_NL| (only in case of this routine); + +\verb|GLP_NF| --- the same as \verb|GLP_NL| (only in case of this +routine); + +\verb|GLP_NS| --- the same as \verb|GLP_NL| (only in case of this +routine). + +\subsection{glp\_std\_basis --- construct standard initial LP basis} + +\synopsis + +\begin{verbatim} + void glp_std_basis(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_std_basis| constructs the ``standard'' (trivial) +initial LP basis for the specified problem object. + +In the ``standard'' LP basis all auxiliary variables (rows) are basic, +and all structural variables (columns) are non-basic (so the +corresponding basis matrix is unity). + +\subsection{glp\_adv\_basis --- construct advanced initial LP basis} + +\synopsis + +\begin{verbatim} + void glp_adv_basis(glp_prob *P, int flags); +\end{verbatim} + +\description + +The routine \verb|glp_adv_basis| constructs an advanced initial LP +basis for the specified problem object. + +The parameter \verb|flags| is reserved for use in the future and must +be specified as zero. + +In order to construct the advanced initial LP basis the routine does +the following: + +1) includes in the basis all non-fixed auxiliary variables; + +2) includes in the basis as many non-fixed structural variables as +possible keeping the triangular form of the basis matrix; + +3) includes in the basis appropriate (fixed) auxiliary variables to +complete the basis. + +As a result the initial LP basis has as few fixed variables as possible +and the corresponding basis matrix is triangular. + +\subsection{glp\_cpx\_basis --- construct Bixby's initial LP basis} + +\synopsis + +\begin{verbatim} + void glp_cpx_basis(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_cpx_basis| constructs an initial basis for the +specified problem object with the algorithm proposed by +R.~Bixby.\footnote{Robert E. Bixby, ``Implementing the Simplex Method: +The Initial Basis.'' ORSA Journal on Computing, Vol. 4, No. 3, 1992, +pp. 267-84.} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Simplex method routines} + +The {\it simplex method} is a well known efficient numerical procedure +to solve LP problems. + +On each iteration the simplex method transforms the original system of +equaility constraints (1.2) resolving them through different sets of +variables to an equivalent system called {\it the simplex table} (or +sometimes {\it the simplex tableau}), which has the following form: +$$ +\begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} +z&=&d_1(x_N)_1&+&d_2(x_N)_2&+ \dots +&d_n(x_N)_n \\ +(x_B)_1&=&\xi_{11}(x_N)_1& +& \xi_{12}(x_N)_2& + \dots +& + \xi_{1n}(x_N)_n \\ +(x_B)_2&=& \xi_{21}(x_N)_1& +& \xi_{22}(x_N)_2& + \dots +& + \xi_{2n}(x_N)_n \\ +\multicolumn{7}{c} +{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .} \\ +(x_B)_m&=&\xi_{m1}(x_N)_1& +& \xi_{m2}(x_N)_2& + \dots +& + \xi_{mn}(x_N)_n \\ +\end{array} \eqno (2.3) +$$ +where: $(x_B)_1, (x_B)_2, \dots, (x_B)_m$ are basic variables; +$(x_N)_1, (x_N)_2, \dots, (x_N)_n$ are non-basic variables; +$d_1, d_2, \dots, d_n$ are reduced costs; +$\xi_{11}, \xi_{12}, \dots, \xi_{mn}$ are coefficients of the +simplex table. (May note that the original LP problem (1.1)---(1.3) +also has the form of a simplex table, where all equalities are resolved +through auxiliary variables.) + +From the linear programming theory it is known that if an optimal +solution of the LP problem (1.1)---(1.3) exists, it can always be +written in the form (2.3), where non-basic variables are set on their +bounds while values of the objective function and basic variables are +determined by the corresponding equalities of the simplex table. + +A set of values of all basic and non-basic variables determined by the +simplex table is called {\it basic solution}. If all basic variables +are within their bounds, the basic solution is called {\it (primal) +feasible}, otherwise it is called {\it (primal) infeasible}. A feasible +basic solution, which provides a smallest (in case of minimization) or +a largest (in case of maximization) value of the objective function is +called {\it optimal}. Therefore, for solving LP problem the simplex +method tries to find its optimal basic solution. + +Primal feasibility of some basic solution may be stated by simple +checking if all basic variables are within their bounds. Basic solution +is optimal if additionally the following optimality conditions are +satisfied for all non-basic variables: +\begin{center} +\begin{tabular}{lcc} +Status of $(x_N)_j$ & Minimization & Maximization \\ +\hline +$(x_N)_j$ is free & $d_j = 0$ & $d_j = 0$ \\ +$(x_N)_j$ is on its lower bound & $d_j \geq 0$ & $d_j \leq 0$ \\ +$(x_N)_j$ is on its upper bound & $d_j \leq 0$ & $d_j \geq 0$ \\ +\end{tabular} +\end{center} +In other words, basic solution is optimal if there is no non-basic +variable, which changing in the feasible direction (i.e. increasing if +it is free or on its lower bound, or decreasing if it is free or on its +upper bound) can improve (i.e. decrease in case of minimization or +increase in case of maximization) the objective function. + +If all non-basic variables satisfy to the optimality conditions shown +above (independently on whether basic variables are within their bounds +or not), the basic solution is called {\it dual feasible}, otherwise it +is called {\it dual infeasible}. + +It may happen that some LP problem has no primal feasible solution due +to incorrect\linebreak formulation --- this means that its constraints +conflict with each other. It also may happen that some LP problem has +unbounded solution again due to incorrect formulation --- this means +that some non-basic variable can improve the objective function, i.e. +the optimality conditions are violated, and at the same time this +variable can infinitely change in the feasible direction meeting +no resistance from basic variables. (May note that in the latter case +the LP problem has no dual feasible solution.) + +\subsection{glp\_simplex --- solve LP problem with the primal or dual +simplex method} + +\synopsis + +\begin{verbatim} + int glp_simplex(glp_prob *P, const glp_smcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_simplex| is a driver to the LP solver based on +the simplex method. This routine retrieves problem data from the +specified problem object, calls the solver to solve the problem +instance, and stores results of computations back into the problem +object. + +The simplex solver has a set of control parameters. Values of the +control parameters can be passed in the structure \verb|glp_smcp|, +which the parameter \verb|parm| points to. For detailed description of +this structure see paragraph ``Control parameters'' below. +Before specifying some control parameters the application program +should initialize the structure \verb|glp_smcp| by default values of +all control parameters using the routine \verb|glp_init_smcp| (see the +next subsection). This is needed for backward compatibility, because in +the future there may appear new members in the structure +\verb|glp_smcp|. + +The parameter \verb|parm| can be specified as \verb|NULL|, in which +case the solver uses default settings. + +\returns + +\begin{retlist} +0 & The LP problem instance has been successfully solved. (This code +does {\it not} necessarily mean that the solver has found optimal +solution. It only means that the solution process was successful.) \\ + +\verb|GLP_EBADB| & Unable to start the search, because the initial +basis specified in the problem object is invalid---the number of basic +(auxiliary and structural) variables is not the same as the number of +rows in the problem object.\\ + +\verb|GLP_ESING| & Unable to start the search, because the basis matrix +corresponding to the initial basis is singular within the working +precision.\\ + +\verb|GLP_ECOND| & Unable to start the search, because the basis matrix +corresponding to the initial basis is ill-conditioned, i.e. its +condition number is too large.\\ + +\verb|GLP_EBOUND| & Unable to start the search, because some +double-bounded (auxiliary or structural) variables have incorrect +bounds.\\ + +\verb|GLP_EFAIL| & The search was prematurely terminated due to the +solver failure.\\ + +\verb|GLP_EOBJLL| & The search was prematurely terminated, because the +objective function being maximized has reached its lower limit and +continues decreasing (the dual simplex only).\\ +\end{retlist} + +\begin{retlist} +\verb|GLP_EOBJUL| & The search was prematurely terminated, because the +objective function being minimized has reached its upper limit and +continues increasing (the dual simplex only).\\ + +\verb|GLP_EITLIM| & The search was prematurely terminated, because the +simplex iteration limit has been exceeded.\\ + +\verb|GLP_ETMLIM| & The search was prematurely terminated, because the +time limit has been exceeded.\\ + +\verb|GLP_ENOPFS| & The LP problem instance has no primal feasible +solution (only if the LP presolver is used).\\ + +\verb|GLP_ENODFS| & The LP problem instance has no dual feasible +solution (only if the LP presolver is used).\\ +\end{retlist} + +\para{Built-in LP presolver} + +The simplex solver has {\it built-in LP presolver}. It is a subprogram +that transforms the original LP problem specified in the problem object +to an equivalent LP problem, which may be easier for solving with the +simplex method than the original one. This is attained mainly due to +reducing the problem size and improving its numeric properties (for +example, by removing some inactive constraints or by fixing some +non-basic variables). Once the transformed LP problem has been solved, +the presolver transforms its basic solution back to the corresponding +basic solution of the original problem. + +Presolving is an optional feature of the routine \verb|glp_simplex|, +and by default it is disabled. In order to enable the LP presolver the +control parameter \verb|presolve| should be set to \verb|GLP_ON| (see +paragraph ``Control parameters'' below). Presolving may be used when +the problem instance is solved for the first time. However, on +performing re-optimization the presolver should be disabled. + +The presolving procedure is transparent to the API user in the sense +that all necessary processing is performed internally, and a basic +solution of the original problem recovered by the presolver is the same +as if it were computed directly, i.e. without presolving. + +Note that the presolver is able to recover only optimal solutions. If +a computed solution is infeasible or non-optimal, the corresponding +solution of the original problem cannot be recovered and therefore +remains undefined. If you need to know a basic solution even if it is +infeasible or non-optimal, the presolver should be disabled. + +\para{Terminal output} + +Solving large problem instances may take a long time, so the solver +reports some information about the current basic solution, which is sent +to the terminal. This information has the following format: + +\begin{verbatim} + nnn: obj = xxx infeas = yyy (ddd) +\end{verbatim} + +\noindent +where: `\verb|nnn|' is the iteration number, `\verb|xxx|' is the +current value of the objective function (it is is unscaled and has +correct sign); `\verb|yyy|' is the current sum of primal or dual +infeasibilities (it is scaled and therefore may be used only for visual +estimating), `\verb|ddd|' is the current number of fixed basic +variables. + +The symbol preceding the iteration number indicates which phase of the +simplex method is in effect: + +{\it Blank} means that the solver is searching for primal feasible +solution using the primal simplex or for dual feasible solution using +the dual simplex; + +{\it Asterisk} (\verb|*|) means that the solver is searching for +optimal solution using the primal simplex; + +{\it Vertical dash} (\verb/|/) means that the solver is searching for +optimal solution using the dual simplex. + +\para{Control parameters} + +This paragraph describes all control parameters currently used in the +simplex solver. Symbolic names of control parameters are names of +corresponding members in the structure \verb|glp_smcp|. + +\bigskip + +{\tt int msg\_lev} (default: {\tt GLP\_MSG\_ALL}) + +Message level for terminal output: + +\verb|GLP_MSG_OFF| --- no output; + +\verb|GLP_MSG_ERR| --- error and warning messages only; + +\verb|GLP_MSG_ON | --- normal output; + +\verb|GLP_MSG_ALL| --- full output (including informational messages). + +\bigskip + +{\tt int meth} (default: {\tt GLP\_PRIMAL}) + +Simplex method option: + +\verb|GLP_PRIMAL| --- use two-phase primal simplex; + +\verb|GLP_DUAL | --- use two-phase dual simplex; + +\verb|GLP_DUALP | --- use two-phase dual simplex, and if it fails, +switch to the primal simplex. + +\bigskip + +{\tt int pricing} (default: {\tt GLP\_PT\_PSE}) + +Pricing technique: + +\verb|GLP_PT_STD| --- standard (``textbook''); + +\verb|GLP_PT_PSE| --- projected steepest edge. + +\bigskip + +{\tt int r\_test} (default: {\tt GLP\_RT\_HAR}) + +Ratio test technique: + +\verb|GLP_RT_STD| --- standard (``textbook''); + +\verb|GLP_RT_HAR| --- Harris' two-pass ratio test. + +\bigskip + +{\tt double tol\_bnd} (default: {\tt 1e-7}) + +Tolerance used to check if the basic solution is primal feasible. +(Do not change this parameter without detailed understanding its +purpose.) + +\newpage + +{\tt double tol\_dj} (default: {\tt 1e-7}) + +Tolerance used to check if the basic solution is dual feasible. +(Do not change this parameter without detailed understanding its +purpose.) + +\bigskip + +{\tt double tol\_piv} (default: {\tt 1e-10}) + +Tolerance used to choose eligble pivotal elements of the simplex table. +(Do not change this parameter without detailed understanding its +purpose.) + +\bigskip + +{\tt double obj\_ll} (default: {\tt -DBL\_MAX}) + +Lower limit of the objective function. If the objective function +reaches this limit and continues decreasing, the solver terminates the +search. (Used in the dual simplex only.) + +\bigskip + +{\tt double obj\_ul} (default: {\tt +DBL\_MAX}) + +Upper limit of the objective function. If the objective function +reaches this limit and continues increasing, the solver terminates the +search. (Used in the dual simplex only.) + +\bigskip + +{\tt int it\_lim} (default: {\tt INT\_MAX}) + +Simplex iteration limit. + +\bigskip + +{\tt int tm\_lim} (default: {\tt INT\_MAX}) + +Searching time limit, in milliseconds. + +\bigskip + +{\tt int out\_frq} (default: {\tt 500}) + +Output frequency, in iterations. This parameter specifies how +frequently the solver sends information about the solution process to +the terminal. + +\bigskip + +{\tt int out\_dly} (default: {\tt 0}) + +Output delay, in milliseconds. This parameter specifies how long the +solver should delay sending information about the solution process to +the terminal. + +\bigskip + +{\tt int presolve} (default: {\tt GLP\_OFF}) + +LP presolver option: + +\verb|GLP_ON | --- enable using the LP presolver; + +\verb|GLP_OFF| --- disable using the LP presolver. + +\newpage + +\para{Example 1} + +The following example main program reads LP problem instance in fixed +MPS format from file \verb|25fv47.mps|,\footnote{This instance in fixed +MPS format can be found in the Netlib LP collection; see +{\tt ftp://ftp.netlib.org/lp/data/}.} constructs an advanced initial +basis, solves the instance with the primal simplex method (by default), +and writes the solution to file \verb|25fv47.txt|. + +\begin{footnotesize} +\begin{verbatim} +/* spxsamp1.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *P; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_adv_basis(P, 0); + glp_simplex(P, NULL); + glp_print_sol(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ +\end{verbatim} +\end{footnotesize} + +Below here is shown the terminal output from this example program. + +\begin{footnotesize} +\begin{verbatim} +Reading problem data from `25fv47.mps'... +Problem: 25FV47 +Objective: R0000 +822 rows, 1571 columns, 11127 non-zeros +6919 records were read +Crashing... +Size of triangular part = 799 + 0: obj = 1.627307307e+04 infeas = 5.194e+04 (23) + 200: obj = 1.474901610e+04 infeas = 1.233e+04 (19) + 400: obj = 1.343909995e+04 infeas = 3.648e+03 (13) + 600: obj = 1.756052217e+04 infeas = 4.179e+02 (7) +* 775: obj = 1.789251591e+04 infeas = 4.982e-14 (1) +* 800: obj = 1.663354510e+04 infeas = 2.857e-14 (1) +* 1000: obj = 1.024935068e+04 infeas = 1.958e-12 (1) +* 1200: obj = 7.860174791e+03 infeas = 2.810e-29 (1) +* 1400: obj = 6.642378184e+03 infeas = 2.036e-16 (1) +* 1600: obj = 6.037014568e+03 infeas = 0.000e+00 (1) +* 1800: obj = 5.662171307e+03 infeas = 6.447e-15 (1) +* 2000: obj = 5.528146165e+03 infeas = 9.764e-13 (1) +* 2125: obj = 5.501845888e+03 infeas = 0.000e+00 (1) +OPTIMAL SOLUTION FOUND +Writing basic solution to `25fv47.txt'... +\end{verbatim} +\end{footnotesize} + +\newpage + +\para{Example 2} + +The following example main program solves the same LP problem instance +as in Example 1 above, however, it uses the dual simplex method, which +starts from the standard initial basis. + +\begin{footnotesize} +\begin{verbatim} +/* spxsamp2.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *P; + glp_smcp parm; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_init_smcp(&parm); + parm.meth = GLP_DUAL; + glp_simplex(P, &parm); + glp_print_sol(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ +\end{verbatim} +\end{footnotesize} + +Below here is shown the terminal output from this example program. + +\begin{footnotesize} +\begin{verbatim} +Reading problem data from `25fv47.mps'... +Problem: 25FV47 +Objective: R0000 +822 rows, 1571 columns, 11127 non-zeros +6919 records were read + 0: infeas = 1.223e+03 (516) + 200: infeas = 7.000e+00 (471) + 240: infeas = 1.106e-14 (461) +| 400: obj = -5.394267152e+03 infeas = 5.571e-16 (391) +| 600: obj = -4.586395752e+03 infeas = 1.389e-15 (340) +| 800: obj = -4.158268146e+03 infeas = 1.640e-15 (264) +| 1000: obj = -3.725320045e+03 infeas = 5.181e-15 (245) +| 1200: obj = -3.104802163e+03 infeas = 1.019e-14 (210) +| 1400: obj = -2.584190499e+03 infeas = 8.865e-15 (178) +| 1600: obj = -2.073852927e+03 infeas = 7.867e-15 (142) +| 1800: obj = -1.164037407e+03 infeas = 8.792e-15 (109) +| 2000: obj = -4.370590250e+02 infeas = 2.591e-14 (85) +| 2200: obj = 1.068240144e+03 infeas = 1.025e-13 (70) +| 2400: obj = 1.607481126e+03 infeas = 3.272e-14 (67) +| 2600: obj = 3.038230551e+03 infeas = 4.850e-14 (52) +| 2800: obj = 4.316238187e+03 infeas = 2.622e-14 (36) +| 3000: obj = 5.443842629e+03 infeas = 3.976e-15 (11) +| 3060: obj = 5.501845888e+03 infeas = 8.806e-15 (2) +OPTIMAL SOLUTION FOUND +Writing basic solution to `25fv47.txt'... +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_exact --- solve LP problem in exact arithmetic} + +\synopsis + +\begin{verbatim} + int glp_exact(glp_prob *P, const glp_smcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_exact| is a tentative implementation of the +primal two-phase simplex method based on exact (rational) arithmetic. +It is similar to the routine \verb|glp_simplex|, however, for all +internal computations it uses arithmetic of rational numbers, which is +exact in mathematical sense, i.e. free of round-off errors unlike +floating-point arithmetic. + +Note that the routine \verb|glp_exact| uses only two control parameters +passed in the structure \verb|glp_smcp|, namely, \verb|it_lim| and +\verb|tm_lim|. + +\returns + +\begin{retlist} +0 & The LP problem instance has been successfully solved. (This code +does {\it not} necessarily mean that the solver has found optimal +solution. It only means that the solution process was successful.) \\ + +\verb|GLP_EBADB| & Unable to start the search, because the initial basis +specified in the problem object is invalid---the number of basic +(auxiliary and structural) variables is not the same as the number of +rows in the problem object.\\ + +\verb|GLP_ESING| & Unable to start the search, because the basis matrix +corresponding to the initial basis is exactly singular.\\ + +\verb|GLP_EBOUND| & Unable to start the search, because some +double-bounded (auxiliary or structural) variables have incorrect +bounds.\\ + +\verb|GLP_EFAIL| & The problem instance has no rows/columns.\\ + +\verb|GLP_EITLIM| & The search was prematurely terminated, because the +simplex iteration limit has been exceeded.\\ + +\verb|GLP_ETMLIM| & The search was prematurely terminated, because the +time limit has been exceeded.\\ +\end{retlist} + +\para{Note} + +Computations in exact arithmetic are very time-consuming, so solving +LP problem with the routine \verb|glp_exact| from the very beginning is +not a good idea. It is much better at first to find an optimal basis +with the routine \verb|glp_simplex| and only then to call +\verb|glp_exact|, in which case only a few simplex iterations need to +be performed in exact arithmetic. + +\newpage + +\subsection{glp\_init\_smcp --- initialize simplex solver control +parameters} + +\synopsis + +\begin{verbatim} + int glp_init_smcp(glp_smcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_init_smcp| initializes control parameters, which +are used by the simplex solver, with default values. + +Default values of the control parameters are stored in +a \verb|glp_smcp| structure, which the parameter \verb|parm| points to. + +\subsection{glp\_get\_status --- determine generic status of basic +solution} + +\synopsis + +\begin{verbatim} + int glp_get_status(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_status| reports the generic status of the +current basic solution for the specified problem object as follows: + +\verb|GLP_OPT | --- solution is optimal; + +\verb|GLP_FEAS | --- solution is feasible; + +\verb|GLP_INFEAS| --- solution is infeasible; + +\verb|GLP_NOFEAS| --- problem has no feasible solution; + +\verb|GLP_UNBND | --- problem has unbounded solution; + +\verb|GLP_UNDEF | --- solution is undefined. + +More detailed information about the status of basic solution can be +retrieved with the routines \verb|glp_get_prim_stat| and +\verb|glp_get_dual_stat|. + +\subsection{glp\_get\_prim\_stat --- retrieve status of primal basic +solution} + +\synopsis + +\begin{verbatim} + int glp_get_prim_stat(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_prim_stat| reports the status of the primal +basic solution for the specified problem object as follows: + +\verb|GLP_UNDEF | --- primal solution is undefined; + +\verb|GLP_FEAS | --- primal solution is feasible; + +\verb|GLP_INFEAS| --- primal solution is infeasible; + +\verb|GLP_NOFEAS| --- no primal feasible solution exists. + +\subsection{glp\_get\_dual\_stat --- retrieve status of dual basic +solution} + +\synopsis + +\begin{verbatim} + int glp_get_dual_stat(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_dual_stat| reports the status of the dual +basic solution for the specified problem object as follows: + +\verb|GLP_UNDEF | --- dual solution is undefined; + +\verb|GLP_FEAS | --- dual solution is feasible; + +\verb|GLP_INFEAS| --- dual solution is infeasible; + +\verb|GLP_NOFEAS| --- no dual feasible solution exists. + +\subsection{glp\_get\_obj\_val --- retrieve objective value} + +\synopsis + +\begin{verbatim} + double glp_get_obj_val(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_obj_val| returns current value of the +objective function. + +\subsection{glp\_get\_row\_stat --- retrieve row status} + +\synopsis + +\begin{verbatim} + int glp_get_row_stat(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_stat| returns current status assigned to +the auxiliary variable associated with \verb|i|-th row as follows: + +\verb|GLP_BS| --- basic variable; + +\verb|GLP_NL| --- non-basic variable on its lower bound; + +\verb|GLP_NU| --- non-basic variable on its upper bound; + +\verb|GLP_NF| --- non-basic free (unbounded) variable; + +\verb|GLP_NS| --- non-basic fixed variable. + +\newpage + +\subsection{glp\_get\_row\_prim --- retrieve row primal value} + +\synopsis + +\begin{verbatim} + double glp_get_row_prim(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_prim| returns primal value of the +auxiliary variable associated with \verb|i|-th row. + +\subsection{glp\_get\_row\_dual --- retrieve row dual value} + +\synopsis + +\begin{verbatim} + double glp_get_row_dual(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_dual| returns dual value (i.e. reduced +cost) of the auxiliary variable associated with \verb|i|-th row. + +\subsection{glp\_get\_col\_stat --- retrieve column status} + +\synopsis + +\begin{verbatim} + int glp_get_col_stat(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_stat| returns current status assigned to +the structural variable associated with \verb|j|-th column as follows: + +\verb|GLP_BS| --- basic variable; + +\verb|GLP_NL| --- non-basic variable on its lower bound; + +\verb|GLP_NU| --- non-basic variable on its upper bound; + +\verb|GLP_NF| --- non-basic free (unbounded) variable; + +\verb|GLP_NS| --- non-basic fixed variable. + +\subsection{glp\_get\_col\_prim --- retrieve column primal value} + +\synopsis + +\begin{verbatim} + double glp_get_col_prim(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_prim| returns primal value of the +structural variable associated with \verb|j|-th column. + +\newpage + +\subsection{glp\_get\_col\_dual --- retrieve column dual value} + +\synopsis + +\begin{verbatim} + double glp_get_col_dual(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_dual| returns dual value (i.e. reduced +cost) of the structural variable associated with \verb|j|-th column. + +\subsection{glp\_get\_unbnd\_ray --- determine variable causing +unboundedness} + +\synopsis + +\begin{verbatim} + int glp_get_unbnd_ray(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_unbnd_ray| returns the number $k$ of +a variable, which causes primal or dual unboundedness. +If $1\leq k\leq m$, it is $k$-th auxiliary variable, and if +$m+1\leq k\leq m+n$, it is $(k-m)$-th structural variable, where $m$ is +the number of rows, $n$ is the number of columns in the problem object. +If such variable is not defined, the routine returns 0. + +\para{Note} + +If it is not exactly known which version of the simplex solver +detected unboundedness, i.e. whether the unboundedness is primal or +dual, it is sufficient to check the status of the variable +with the routine \verb|glp_get_row_stat| or \verb|glp_get_col_stat|. +If the variable is non-basic, the unboundedness is primal, otherwise, +if the variable is basic, the unboundedness is dual (the latter case +means that the problem has no primal feasible dolution). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Interior-point method routines} + +{\it Interior-point methods} (also known as {\it barrier methods}) are +more modern and powerful numerical methods for large-scale linear +programming. Such methods are especially efficient for very sparse LP +problems and allow solving such problems much faster than the simplex +method. + +In brief, the GLPK interior-point solver works as follows. + +At first, the solver transforms the original LP to a {\it working} LP +in the standard format: + +\medskip + +\noindent +\hspace{.5in} minimize +$$z = c_1x_{m+1} + c_2x_{m+2} + \dots + c_nx_{m+n} + c_0 \eqno (2.4)$$ +\hspace{.5in} subject to linear constraints +$$ +\begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}l} +a_{11}x_{m+1}&+&a_{12}x_{m+2}&+ \dots +&a_{1n}x_{m+n}&=&b_1 \\ +a_{21}x_{m+1}&+&a_{22}x_{m+2}&+ \dots +&a_{2n}x_{m+n}&=&b_2 \\ +\multicolumn{7}{c} +{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .} \\ +a_{m1}x_{m+1}&+&a_{m2}x_{m+2}&+ \dots +&a_{mn}x_{m+n}&=&b_m \\ +\end{array} \eqno (2.5) +$$ +\hspace{.5in} and non-negative variables +$$x_1\geq 0,\ \ x_2\geq 0,\ \ \dots,\ \ x_n\geq 0 \eqno(2.6)$$ +where: $z$ is the objective function; $x_1$, \dots, $x_n$ are variables; +$c_1$, \dots, $c_n$ are objective coefficients; $c_0$ is a constant term +of the objective function; $a_{11}$, \dots, $a_{mn}$ are constraint +coefficients; $b_1$, \dots, $b_m$ are right-hand sides. + +Using vector and matrix notations the working LP (2.4)---(2.6) can be +written as follows: +$$z=c^Tx+c_0\ \rightarrow\ \min,\eqno(2.7)$$ +$$Ax=b,\eqno(2.8)$$ +$$x\geq 0,\eqno(2.9)$$ +where: $x=(x_j)$ is $n$-vector of variables, $c=(c_j)$ is $n$-vector of +objective coefficients, $A=(a_{ij})$ is $m\times n$-matrix of +constraint coefficients, and $b=(b_i)$ is $m$-vector of right-hand +sides. + +Karush--Kuhn--Tucker optimality conditions for LP (2.7)---(2.9) are the +following: +$$Ax=b,\eqno(2.10)$$ +$$A^T\pi+\lambda=c,\eqno(2.11)$$ +$$\lambda^Tx=0,\eqno(2.12)$$ +$$x\geq 0,\ \ \lambda\geq 0,\eqno(2.13)$$ +where: +$\pi$ is $m$-vector of Lagrange multipliers (dual variables) for +equality constraints (2.8),\linebreak $\lambda$ is $n$-vector of +Lagrange multipliers (dual variables) for non-negativity constraints +(2.9),\linebreak (2.10) is the primal feasibility condition, (2.11) is +the dual feasibility condition, (2.12) is the primal-dual +complementarity condition, and (2.13) is the non-negativity conditions. + +The main idea of the primal-dual interior-point method is based on +finding a point in the primal-dual space (i.e. in the space of all +primal and dual variables $x$, $\pi$, and $\lambda$), which satisfies +to all optimality conditions (2.10)---(2.13). Obviously, $x$-component +of such point then provides an optimal solution to the working LP +(2.7)---(2.9). + +To find the optimal point $(x^*,\pi^*,\lambda^*)$ the interior-point +method attempts to solve the system of equations (2.10)---(2.12), which +is closed in the sense that the number of variables $x_j$, $\pi_i$, and +$\lambda_j$ and the number equations are the same and equal to $m+2n$. +Due to condition (2.12) this system of equations is non-linear, so it +can be solved with a version of {\it Newton's method} provided with +additional rules to keep the current point within the positive orthant +as required by the non-negativity conditions (2.13). + +Finally, once the optimal point $(x^*,\pi^*,\lambda^*)$ has been found, +the solver performs inverse transformations to recover corresponding +solution to the original LP passed to the solver from the application +program. + +\subsection{glp\_interior --- solve LP problem with the interior-point +method} + +\synopsis + +\begin{verbatim} + int glp_interior(glp_prob *P, const glp_iptcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_interior| is a driver to the LP solver based on +the primal-dual interior-point method. This routine retrieves problem +data from the specified problem object, calls the solver to solve the +problem instance, and stores results of computations back into the +problem object. + +The interior-point solver has a set of control parameters. Values of +the control parameters can be passed in the structure \verb|glp_iptcp|, +which the parameter \verb|parm| points to. For detailed description of +this structure see paragraph ``Control parameters'' below. Before +specifying some control parameters the application program should +initialize the structure \verb|glp_iptcp| by default values of all +control parameters using the routine \verb|glp_init_iptcp| (see the +next subsection). This is needed for backward compatibility, because in +the future there may appear new members in the structure +\verb|glp_iptcp|. + +The parameter \verb|parm| can be specified as \verb|NULL|, in which +case the solver uses default settings. + +\returns + +\begin{retlist} +0 & The LP problem instance has been successfully solved. (This code +does {\it not} necessarily mean that the solver has found optimal +solution. It only means that the solution process was successful.) \\ + +\verb|GLP_EFAIL| & The problem has no rows/columns.\\ + +\verb|GLP_ENOCVG| & Very slow convergence or divergence.\\ + +\verb|GLP_EITLIM| & Iteration limit exceeded.\\ + +\verb|GLP_EINSTAB| & Numerical instability on solving Newtonian +system.\\ +\end{retlist} + +\newpage + +\para{Comments} + +The routine \verb|glp_interior| implements an easy version of +the primal-dual interior-point method based on Mehrotra's +technique.\footnote{S. Mehrotra. On the implementation of a primal-dual +interior point method. SIAM J. on Optim., 2(4), pp. 575-601, 1992.} + +Note that currently the GLPK interior-point solver does not include +many important features, in particular: + +\vspace*{-8pt} + +\begin{itemize} +\item it is not able to process dense columns. Thus, if the constraint +matrix of the LP problem has dense columns, the solving process may be +inefficient; + +\item it has no features against numerical instability. For some LP +problems premature termination may happen if the matrix $ADA^T$ becomes +singular or ill-conditioned; + +\item it is not able to identify the optimal basis, which corresponds +to the interior-point solution found. +\end{itemize} + +\vspace*{-8pt} + +\para{Terminal output} + +Solving large LP problems may take a long time, so the solver reports +some information about every interior-point iteration,\footnote{Unlike +the simplex method the interior point method usually needs 30---50 +iterations (independently on the problem size) in order to find an +optimal solution.} which is sent to the terminal. This information has +the following format: + +\begin{verbatim} +nnn: obj = fff; rpi = ppp; rdi = ddd; gap = ggg +\end{verbatim} + +\noindent where: \verb|nnn| is iteration number, \verb|fff| is the +current value of the objective function (in the case of maximization it +has wrong sign), \verb|ppp| is the current relative primal +infeasibility (cf. (2.10)): +$$\frac{\|Ax^{(k)}-b\|}{1+\|b\|},\eqno(2.14)$$ +\verb|ddd| is the current relative dual infeasibility (cf. (2.11)): +$$\frac{\|A^T\pi^{(k)}+\lambda^{(k)}-c\|}{1+\|c\|},\eqno(2.15)$$ +\verb|ggg| is the current primal-dual gap (cf. (2.12)): +$$\frac{|c^Tx^{(k)}-b^T\pi^{(k)}|}{1+|c^Tx^{(k)}|},\eqno(2.16)$$ +and $[x^{(k)},\pi^{(k)},\lambda^{(k)}]$ is the current point on $k$-th +iteration, $k=0,1,2,\dots$\ . Note that all solution components are +internally scaled, so information sent to the terminal is suitable only +for visual inspection. + +\newpage + +\para{Control parameters} + +This paragraph describes all control parameters currently used in the +interior-point solver. Symbolic names of control parameters are names of +corresponding members in the structure \verb|glp_iptcp|. + +\bigskip + +{\tt int msg\_lev} (default: {\tt GLP\_MSG\_ALL}) + +Message level for terminal output: + +\verb|GLP_MSG_OFF|---no output; + +\verb|GLP_MSG_ERR|---error and warning messages only; + +\verb|GLP_MSG_ON |---normal output; + +\verb|GLP_MSG_ALL|---full output (including informational messages). + +\bigskip + +{\tt int ord\_alg} (default: {\tt GLP\_ORD\_AMD}) + +Ordering algorithm used prior to Cholesky factorization: + +\verb|GLP_ORD_NONE |---use natural (original) ordering; + +\verb|GLP_ORD_QMD |---quotient minimum degree (QMD); + +\verb|GLP_ORD_AMD |---approximate minimum degree (AMD); + +\verb|GLP_ORD_SYMAMD|---approximate minimum degree (SYMAMD). + +\bigskip + +\para{Example} + +The following main program reads LP problem instance in fixed MPS +format from file\linebreak \verb|25fv47.mps|,\footnote{This instance in +fixed MPS format can be found in the Netlib LP collection; see +{\tt ftp://ftp.netlib.org/lp/data/}.} solves it with the interior-point +solver, and writes the solution to file \verb|25fv47.txt|. + +\begin{footnotesize} +\begin{verbatim} +/* iptsamp.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *P; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_interior(P, NULL); + glp_print_ipt(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ +\end{verbatim} +\end{footnotesize} + +\newpage + +Below here is shown the terminal output from this example program. + +\begin{footnotesize} +\begin{verbatim} +Reading problem data from `25fv47.mps'... +Problem: 25FV47 +Objective: R0000 +822 rows, 1571 columns, 11127 non-zeros +6919 records were read +Original LP has 822 row(s), 1571 column(s), and 11127 non-zero(s) +Working LP has 821 row(s), 1876 column(s), and 10705 non-zero(s) +Matrix A has 10705 non-zeros +Matrix S = A*A' has 11895 non-zeros (upper triangle) +Minimal degree ordering... +Computing Cholesky factorization S = L'*L... +Matrix L has 35411 non-zeros +Guessing initial point... +Optimization begins... + 0: obj = 1.823377629e+05; rpi = 1.3e+01; rdi = 1.4e+01; gap = 9.3e-01 + 1: obj = 9.260045192e+04; rpi = 5.3e+00; rdi = 5.6e+00; gap = 6.8e+00 + 2: obj = 3.596999742e+04; rpi = 1.5e+00; rdi = 1.2e+00; gap = 1.8e+01 + 3: obj = 1.989627568e+04; rpi = 4.7e-01; rdi = 3.0e-01; gap = 1.9e+01 + 4: obj = 1.430215557e+04; rpi = 1.1e-01; rdi = 8.6e-02; gap = 1.4e+01 + 5: obj = 1.155716505e+04; rpi = 2.3e-02; rdi = 2.4e-02; gap = 6.8e+00 + 6: obj = 9.660273208e+03; rpi = 6.7e-03; rdi = 4.6e-03; gap = 3.9e+00 + 7: obj = 8.694348283e+03; rpi = 3.7e-03; rdi = 1.7e-03; gap = 2.0e+00 + 8: obj = 8.019543639e+03; rpi = 2.4e-03; rdi = 3.9e-04; gap = 1.0e+00 + 9: obj = 7.122676293e+03; rpi = 1.2e-03; rdi = 1.5e-04; gap = 6.6e-01 + 10: obj = 6.514534518e+03; rpi = 6.1e-04; rdi = 4.3e-05; gap = 4.1e-01 + 11: obj = 6.361572203e+03; rpi = 4.8e-04; rdi = 2.2e-05; gap = 3.0e-01 + 12: obj = 6.203355508e+03; rpi = 3.2e-04; rdi = 1.7e-05; gap = 2.6e-01 + 13: obj = 6.032943411e+03; rpi = 2.0e-04; rdi = 9.3e-06; gap = 2.1e-01 + 14: obj = 5.796553021e+03; rpi = 9.8e-05; rdi = 3.2e-06; gap = 1.0e-01 + 15: obj = 5.667032431e+03; rpi = 4.4e-05; rdi = 1.1e-06; gap = 5.6e-02 + 16: obj = 5.613911867e+03; rpi = 2.5e-05; rdi = 4.1e-07; gap = 3.5e-02 + 17: obj = 5.560572626e+03; rpi = 9.9e-06; rdi = 2.3e-07; gap = 2.1e-02 + 18: obj = 5.537276001e+03; rpi = 5.5e-06; rdi = 8.4e-08; gap = 1.1e-02 + 19: obj = 5.522746942e+03; rpi = 2.2e-06; rdi = 4.0e-08; gap = 6.7e-03 + 20: obj = 5.509956679e+03; rpi = 7.5e-07; rdi = 1.8e-08; gap = 2.9e-03 + 21: obj = 5.504571733e+03; rpi = 1.6e-07; rdi = 5.8e-09; gap = 1.1e-03 + 22: obj = 5.502576367e+03; rpi = 3.4e-08; rdi = 1.0e-09; gap = 2.5e-04 + 23: obj = 5.502057119e+03; rpi = 8.1e-09; rdi = 3.0e-10; gap = 7.7e-05 + 24: obj = 5.501885996e+03; rpi = 9.4e-10; rdi = 1.2e-10; gap = 2.4e-05 + 25: obj = 5.501852464e+03; rpi = 1.4e-10; rdi = 1.2e-11; gap = 3.0e-06 + 26: obj = 5.501846549e+03; rpi = 1.4e-11; rdi = 1.2e-12; gap = 3.0e-07 + 27: obj = 5.501845954e+03; rpi = 1.4e-12; rdi = 1.2e-13; gap = 3.0e-08 + 28: obj = 5.501845895e+03; rpi = 1.5e-13; rdi = 1.2e-14; gap = 3.0e-09 +OPTIMAL SOLUTION FOUND +Writing interior-point solution to `25fv47.txt'... +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_init\_iptcp --- initialize interior-point solver +control parameters} + +\synopsis + +\begin{verbatim} + int glp_init_iptcp(glp_iptcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_init_iptcp| initializes control parameters, which +are used by the interior-point solver, with default values. + +Default values of the control parameters are stored in the structure +\verb|glp_iptcp|, which the parameter \verb|parm| points to. + +\subsection{glp\_ipt\_status --- determine solution status} + +\synopsis + +\begin{verbatim} + int glp_ipt_status(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_status| reports the status of a solution +found by the interior-point solver as follows: + +\verb|GLP_UNDEF | --- interior-point solution is undefined; + +\verb|GLP_OPT | --- interior-point solution is optimal; + +\verb|GLP_INFEAS| --- interior-point solution is infeasible; + +\verb|GLP_NOFEAS| --- no feasible primal-dual solution exists. + +\subsection{glp\_ipt\_obj\_val --- retrieve objective value} + +\synopsis + +\begin{verbatim} + double glp_ipt_obj_val(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_obj_val| returns value of the objective +function for interior-point solution. + +\subsection{glp\_ipt\_row\_prim --- retrieve row primal value} + +\synopsis + +\begin{verbatim} + double glp_ipt_row_prim(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_row_prim| returns primal value of the +auxiliary variable associated with \verb|i|-th row. + +\newpage + +\subsection{glp\_ipt\_row\_dual --- retrieve row dual value} + +\synopsis + +\begin{verbatim} + double glp_ipt_row_dual(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_row_dual| returns dual value (i.e. reduced +cost) of the auxiliary variable associated with \verb|i|-th row. + +\subsection{glp\_ipt\_col\_prim --- retrieve column primal value} + +\synopsis + +\begin{verbatim} + double glp_ipt_col_prim(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_col_prim| returns primal value of the +structural variable associated with \verb|j|-th column. + +\subsection{glp\_ipt\_col\_dual --- retrieve column dual value} + +\synopsis + +\begin{verbatim} + double glp_ipt_col_dual(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_col_dual| returns dual value (i.e. reduced +cost) of the structural variable associated with \verb|j|-th column. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Mixed integer programming routines} + +\subsection{glp\_set\_col\_kind --- set (change) column kind} + +\synopsis + +\begin{verbatim} + void glp_set_col_kind(glp_prob *P, int j, int kind); +\end{verbatim} + +\description + +The routine \verb|glp_set_col_kind| sets (changes) the kind of +\verb|j|-th column (structural variable) as specified by the parameter +\verb|kind|: + +\verb|GLP_CV| --- continuous variable; + +\verb|GLP_IV| --- integer variable; + +\verb|GLP_BV| --- binary variable. + +Setting a column to \verb|GLP_BV| has the same effect as if it were +set to \verb|GLP_IV|, its lower bound were set 0, and its upper bound +were set to 1. + +\subsection{glp\_get\_col\_kind --- retrieve column kind} + +\synopsis + +\begin{verbatim} + int glp_get_col_kind(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_kind| returns the kind of \verb|j|-th +column (structural variable) as follows: + +\verb|GLP_CV| --- continuous variable; + +\verb|GLP_IV| --- integer variable; + +\verb|GLP_BV| --- binary variable. + +\subsection{glp\_get\_num\_int --- retrieve number of integer columns} + +\synopsis + +\begin{verbatim} + int glp_get_num_int(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_num_int| returns the number of columns +(structural variables), which are marked as integer. Note that this +number {\it does} include binary columns. + +\newpage + +\subsection{glp\_get\_num\_bin --- retrieve number of binary columns} + +\synopsis + +\begin{verbatim} + int glp_get_num_bin(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_num_bin| returns the number of columns +(structural variables), which are marked as integer and whose lower +bound is zero and upper bound is one. + +\subsection{glp\_intopt --- solve MIP problem with the branch-and-cut +method} + +\synopsis + +\begin{verbatim} + int glp_intopt(glp_prob *P, const glp_iocp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_intopt| is a driver to the MIP solver based on +the branch-and-cut method, which is a hybrid of branch-and-bound and +cutting plane methods. + +If the presolver is disabled (see paragraph ``Control parameters'' +below), on entry to the routine \verb|glp_intopt| the problem object, +which the parameter \verb|mip| points to, should contain optimal +solution to LP relaxation (it can be obtained, for example, with the +routine \verb|glp_simplex|). Otherwise, if the presolver is enabled, it +is not necessary. + +The MIP solver has a set of control parameters. Values of the control +parameters can be passed in the structure \verb|glp_iocp|, which the +parameter \verb|parm| points to. For detailed description of this +structure see paragraph ``Control parameters'' below. Before specifying +some control parameters the application program should initialize the +structure \verb|glp_iocp| by default values of all control parameters +using the routine \verb|glp_init_iocp| (see the next subsection). This +is needed for backward compatibility, because in the future there may +appear new members in the structure \verb|glp_iocp|. + +The parameter \verb|parm| can be specified as \verb|NULL|, in which case +the solver uses default settings. + +Note that the GLPK branch-and-cut solver is not perfect, so it is +unable to solve hard or very large scale MIP instances for a reasonable +time. + +\returns + +\begin{retlist} +0 & The MIP problem instance has been successfully solved. (This code +does {\it not} necessarily mean that the solver has found optimal +solution. It only means that the solution process was successful.) \\ + +\verb|GLP_EBOUND| & Unable to start the search, because some +double-bounded variables have incorrect bounds or some integer +variables have non-integer (fractional) bounds.\\ + +\verb|GLP_EROOT| & Unable to start the search, because optimal basis +for initial LP relaxation is not provided. (This code may appear only +if the presolver is disabled.)\\ + +\verb|GLP_ENOPFS| & Unable to start the search, because LP relaxation +of the MIP problem instance has no primal feasible solution. (This code +may appear only if the presolver is enabled.)\\ +\end{retlist} + +\newpage + +\begin{retlist} +\verb|GLP_ENODFS| & Unable to start the search, because LP relaxation +of the MIP problem instance has no dual feasible solution. In other +word, this code means that if the LP relaxation has at least one primal +feasible solution, its optimal solution is unbounded, so if the MIP +problem has at least one integer feasible solution, its (integer) +optimal solution is also unbounded. (This code may appear only if the +presolver is enabled.)\\ + +\verb|GLP_EFAIL| & The search was prematurely terminated due to the +solver failure.\\ + +\verb|GLP_EMIPGAP| & The search was prematurely terminated, because the +relative mip gap tolerance has been reached.\\ + +\verb|GLP_ETMLIM| & The search was prematurely terminated, because the +time limit has been exceeded.\\ + +\verb|GLP_ESTOP| & The search was prematurely terminated by application. +(This code may appear only if the advanced solver interface is used.)\\ +\end{retlist} + +\para{Built-in MIP presolver} + +The branch-and-cut solver has {\it built-in MIP presolver}. It is +a subprogram that transforms the original MIP problem specified in the +problem object to an equivalent MIP problem, which may be easier for +solving with the branch-and-cut method than the original one. For +example, the presolver can remove redundant constraints and variables, +whose optimal values are known, perform bound and coefficient reduction, +etc. Once the transformed MIP problem has been solved, the presolver +transforms its solution back to corresponding solution of the original +problem. + +Presolving is an optional feature of the routine \verb|glp_intopt|, and +by default it is disabled. In order to enable the MIP presolver, the +control parameter \verb|presolve| should be set to \verb|GLP_ON| (see +paragraph ``Control parameters'' below). + +\para{Advanced solver interface} + +The routine \verb|glp_intopt| allows the user to control the +branch-and-cut search by passing to the solver a user-defined callback +routine. For more details see Chapter ``Branch-and-Cut API Routines''. + +\para{Terminal output} + +Solving a MIP problem may take a long time, so the solver reports some +information about best known solutions, which is sent to the terminal. +This information has the following format: + +\begin{verbatim} ++nnn: mip = xxx <rho> yyy gap (ppp; qqq) +\end{verbatim} + +\noindent +where: `\verb|nnn|' is the simplex iteration number; `\verb|xxx|' is a +value of the objective function for the best known integer feasible +solution (if no integer feasible solution has been found yet, +`\verb|xxx|' is the text `\verb|not found yet|'); `\verb|rho|' is the +string `\verb|>=|' (in case of minimization) or `\verb|<=|' (in case of +maximization); `\verb|yyy|' is a global bound for exact integer optimum +(i.e. the exact integer optimum is always in the range from `\verb|xxx|' +to `\verb|yyy|'); `\verb|gap|' is the relative mip gap, in percents, +computed as $gap=|xxx-yyy|/(|xxx|+{\tt DBL\_EPSILON})\cdot 100\%$ (if +$gap$ is greater than $999.9\%$, it is not printed); `\verb|ppp|' is the +number of subproblems in the active list, `\verb|qqq|' is the number of +subproblems which have been already fathomed and therefore removed from +the branch-and-bound search tree. + +\newpage + +\subsubsection{Control parameters} + +This paragraph describes all control parameters currently used in the +MIP solver. Symbolic names of control parameters are names of +corresponding members in the structure \verb|glp_iocp|. + +\bigskip\vspace*{-2pt} + +{\tt int msg\_lev} (default: {\tt GLP\_MSG\_ALL}) + +Message level for terminal output: + +\verb|GLP_MSG_OFF| --- no output; + +\verb|GLP_MSG_ERR| --- error and warning messages only; + +\verb|GLP_MSG_ON | --- normal output; + +\verb|GLP_MSG_ALL| --- full output (including informational messages). + +\bigskip\vspace*{-2pt} + +{\tt int br\_tech} (default: {\tt GLP\_BR\_DTH}) + +Branching technique option: + +\verb|GLP_BR_FFV| --- first fractional variable; + +\verb|GLP_BR_LFV| --- last fractional variable; + +\verb|GLP_BR_MFV| --- most fractional variable; + +\verb|GLP_BR_DTH| --- heuristic by Driebeck and Tomlin; + +\verb|GLP_BR_PCH| --- hybrid pseudo-cost heuristic. + +\bigskip\vspace*{-2pt} + +{\tt int bt\_tech} (default: {\tt GLP\_BT\_BLB}) + +Backtracking technique option: + +\verb|GLP_BT_DFS| --- depth first search; + +\verb|GLP_BT_BFS| --- breadth first search; + +\verb|GLP_BT_BLB| --- best local bound; + +\verb|GLP_BT_BPH| --- best projection heuristic. + +\bigskip\vspace*{-2pt} + +{\tt int pp\_tech} (default: {\tt GLP\_PP\_ALL}) + +Preprocessing technique option: + +\verb|GLP_PP_NONE| --- disable preprocessing; + +\verb|GLP_PP_ROOT| --- perform preprocessing only on the root level; + +\verb|GLP_PP_ALL | --- perform preprocessing on all levels. + +\bigskip\vspace*{-2pt} + +{\tt int fp\_heur} (default: {\tt GLP\_OFF}) + +Feasibility pump heuristic option: + +\verb|GLP_ON | --- enable applying the feasibility pump heuristic; + +\verb|GLP_OFF| --- disable applying the feasibility pump heuristic. + +\newpage + +{\tt int ps\_heur} (default: {\tt GLP\_OFF}) + +Proximity search heuristic\footnote{The Fischetti--Monaci Proximity +Search (a.k.a. Proxy) heuristic. This algorithm is often capable of +rapidly improving a feasible solution of a MIP problem with binary +variables. It allows to quickly obtain suboptimal solutions in some +problems which take too long time to be solved to optimality.} option: + +\verb|GLP_ON | --- enable applying the proximity search heuristic; + +\verb|GLP_OFF| --- disable applying the proximity search pump heuristic. + +\bigskip + +{\tt int ps\_tm\_lim} (default: {\tt 60000}) + +Time limit, in milliseconds, for the proximity search heuristic (see +above). + +\bigskip + +{\tt int gmi\_cuts} (default: {\tt GLP\_OFF}) + +Gomory's mixed integer cut option: + +\verb|GLP_ON | --- enable generating Gomory's cuts; + +\verb|GLP_OFF| --- disable generating Gomory's cuts. + +\bigskip + +{\tt int mir\_cuts} (default: {\tt GLP\_OFF}) + +Mixed integer rounding (MIR) cut option: + +\verb|GLP_ON | --- enable generating MIR cuts; + +\verb|GLP_OFF| --- disable generating MIR cuts. + +\bigskip + +{\tt int cov\_cuts} (default: {\tt GLP\_OFF}) + +Mixed cover cut option: + +\verb|GLP_ON | --- enable generating mixed cover cuts; + +\verb|GLP_OFF| --- disable generating mixed cover cuts. + +\bigskip + +{\tt int clq\_cuts} (default: {\tt GLP\_OFF}) + +Clique cut option: + +\verb|GLP_ON | --- enable generating clique cuts; + +\verb|GLP_OFF| --- disable generating clique cuts. + +\bigskip + +{\tt double tol\_int} (default: {\tt 1e-5}) + +Absolute tolerance used to check if optimal solution to the current LP +relaxation is integer feasible. (Do not change this parameter without +detailed understanding its purpose.) + +\newpage + +{\tt double tol\_obj} (default: {\tt 1e-7}) + +Relative tolerance used to check if the objective value in optimal +solution to the current LP relaxation is not better than in the best +known integer feasible solution. (Do not change this parameter without +detailed understanding its purpose.) + +\bigskip + +{\tt double mip\_gap} (default: {\tt 0.0}) + +The relative mip gap tolerance. If the relative mip gap for currently +known best integer feasible solution falls below this tolerance, the +solver terminates the search. This allows obtainig suboptimal integer +feasible solutions if solving the problem to optimality takes too long +time. + +\bigskip + +{\tt int tm\_lim} (default: {\tt INT\_MAX}) + +Searching time limit, in milliseconds. + +\bigskip + +{\tt int out\_frq} (default: {\tt 5000}) + +Output frequency, in milliseconds. This parameter specifies how +frequently the solver sends information about the solution process to +the terminal. + +\bigskip + +{\tt int out\_dly} (default: {\tt 10000}) + +Output delay, in milliseconds. This parameter specifies how long the +solver should delay sending information about solution of the current +LP relaxation with the simplex method to the terminal. + +\bigskip + +{\tt void (*cb\_func)(glp\_tree *tree, void *info)} +(default: {\tt NULL}) + +Entry point to the user-defined callback routine. \verb|NULL| means +the advanced solver interface is not used. For more details see Chapter +``Branch-and-Cut API Routines''. + +\bigskip + +{\tt void *cb\_info} (default: {\tt NULL}) + +Transit pointer passed to the routine \verb|cb_func| (see above). + +\bigskip + +{\tt int cb\_size} (default: {\tt 0}) + +The number of extra (up to 256) bytes allocated for each node of the +branch-and-bound tree to store application-specific data. On creating +a node these bytes are initialized by binary zeros. + +\bigskip + +{\tt int presolve} (default: {\tt GLP\_OFF}) + +MIP presolver option: + +\verb|GLP_ON | --- enable using the MIP presolver; + +\verb|GLP_OFF| --- disable using the MIP presolver. + +\newpage + +{\tt int binarize} (default: {\tt GLP\_OFF}) + +Binarization option (used only if the presolver is enabled): + +\verb|GLP_ON | --- replace general integer variables by binary ones; + +\verb|GLP_OFF| --- do not use binarization. + +\subsection{glp\_init\_iocp --- initialize integer optimizer control +parameters} + +\synopsis + +\begin{verbatim} + void glp_init_iocp(glp_iocp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_init_iocp| initializes control parameters, which +are used by the branch-and-cut solver, with default values. + +Default values of the control parameters are stored in +a \verb|glp_iocp| structure, which the parameter \verb|parm| points to. + +\subsection{glp\_mip\_status --- determine status of MIP solution} + +\synopsis + +\begin{verbatim} + int glp_mip_status(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_mip_status| reports the status of a MIP solution +found by the MIP solver as follows: + +\verb|GLP_UNDEF | --- MIP solution is undefined; + +\verb|GLP_OPT | --- MIP solution is integer optimal; + +\verb|GLP_FEAS | --- MIP solution is integer feasible, however, its +optimality (or non-optimality) has not been proven, perhaps due to +premature termination of the search; + +\verb|GLP_NOFEAS| --- problem has no integer feasible solution (proven +by the solver). + +\subsection{glp\_mip\_obj\_val --- retrieve objective value} + +\synopsis + +\begin{verbatim} + double glp_mip_obj_val(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_mip_obj_val| returns value of the objective +function for MIP solution. + +\subsection{glp\_mip\_row\_val --- retrieve row value} + +\synopsis + +\begin{verbatim} + double glp_mip_row_val(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_mip_row_val| returns value of the auxiliary +variable associated with \verb|i|-th row for MIP solution. + +\subsection{glp\_mip\_col\_val --- retrieve column value} + +\synopsis + +\begin{verbatim} + double glp_mip_col_val(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_mip_col_val| returns value of the structural +variable associated with \verb|j|-th column for MIP solution. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Additional routines} + +\subsection{glp\_check\_kkt --- check feasibility/optimality +conditions} + +\synopsis + +{\parskip=0pt +\tt void glp\_check\_kkt(glp\_prob *P, int sol, int cond, +double *ae\_max, int *ae\_ind, + +\hspace{105pt}double *re\_max, int *re\_ind);} + +\description + +The routine \verb|glp_check_kkt| allows to check +feasibility/optimality conditions for the current solution stored in +the specified problem object. (For basic and interior-point solutions +these conditions are known as {\it Karush--Kuhn--Tucker optimality +conditions}.) + +The parameter \verb|sol| specifies which solution should be checked: + +\verb|GLP_SOL| --- basic solution; + +\verb|GLP_IPT| --- interior-point solution; + +\verb|GLP_MIP| --- mixed integer solution. + +The parameter \verb|cond| specifies which condition should be checked: + +\verb|GLP_KKT_PE| --- check primal equality constraints (KKT.PE); + +\verb|GLP_KKT_PB| --- check primal bound constraints (KKT.PB); + +\verb|GLP_KKT_DE| --- check dual equality constraints (KKT.DE). This +conditions can be checked only for basic or interior-point solution; + +\verb|GLP_KKT_DB| --- check dual bound constraints (KKT.DB). This +conditions can be checked only for basic or interior-point solution. + +Detailed explanations of these conditions are given below in paragraph +``Background''. + +On exit the routine stores the following information to locations +specified by parameters \verb|ae_max|, \verb|ae_ind|, \verb|re_max|, +and \verb|re_ind| (if some parameter is a null pointer, corresponding +information is not stored): + +\verb|ae_max| --- largest absolute error; + +\verb|ae_ind| --- number of row (KKT.PE), column (KKT.DE), or variable +(KKT.PB, KKT.DB) with the largest absolute error; + +\verb|re_max| --- largest relative error; + +\verb|re_ind| --- number of row (KKT.PE), column (KKT.DE), or variable +(KKT.PB, KKT.DB) with the largest relative error. + +Row (auxiliary variable) numbers are in the range 1 to $m$, where $m$ +is the number of rows in the problem object. Column (structural +variable) numbers are in the range 1 to $n$, where $n$ is the number +of columns in the problem object. Variable numbers are in the range +1 to $m+n$, where variables with numbers 1 to $m$ correspond to rows, +and variables with numbers $m+1$ to $m+n$ correspond to columns. If +the error reported is exact zero, corresponding row, column or variable +number is set to zero. + +\para{Background} + +\def\arraystretch{1.5} + +The first condition checked by the routine is the following: +$$x_R - A x_S = 0, \eqno{\rm (KKT.PE)}$$ +where $x_R$ is the subvector of auxiliary variables (rows), $x_S$ is +the subvector of structural variables (columns), $A$ is the constraint +matrix. This condition expresses the requirement that all primal +variables should satisfy to the system of equality constraints of the +original LP problem. In case of exact arithmetic this condition would +be satisfied for any basic solution; however, in case of inexact +(floating-point) arithmetic, this condition shows how accurate the +primal solution is, that depends on accuracy of a representation of the +basis matrix used by the simplex method, or on accuracy provided by the +interior-point method. + +To check the condition (KKT.PE) the routine computes the vector of +residuals: +$$g = x_R - A x_S,$$ +and determines component of this vector that correspond to largest +absolute and relative errors: +$${\tt ae\_max}=\max_{1\leq i\leq m}|g_i|,$$ +$${\tt re\_max}=\max_{1\leq i\leq m}\frac{|g_i|}{1+|(x_R)_i|}.$$ + +The second condition checked by the routine is the following: +$$l_k \leq x_k \leq u_k {\rm \ \ \ for\ all}\ k=1,\dots,m+n, +\eqno{\rm (KKT.PB)}$$ +where $x_k$ is auxiliary ($1\leq k\leq m$) or structural +($m+1\leq k\leq m+n$) variable, $l_k$ and $u_k$ are, respectively, +lower and upper bounds of the variable $x_k$ (including cases of +infinite bounds). This condition expresses the requirement that all +primal variables shoudl satisfy to bound constraints of the original +LP problem. In case of basic solution all non-basic variables are +placed on their active bounds, so actually the condition (KKT.PB) needs +to be checked for basic variables only. If the primal solution has +sufficient accuracy, this condition shows its primal feasibility. + +To check the condition (KKT.PB) the routine computes a vector of +residuals: +$$ +h_k = \left\{ +\begin{array}{ll} +0, & {\rm if}\ l_k \leq x_k \leq u_k \\ +x_k - l_k, & {\rm if}\ x_k < l_k \\ +x_k - u_k, & {\rm if}\ x_k > u_k \\ +\end{array} +\right. +$$ +for all $k=1,\dots,m+n$, and determines components of this vector that +correspond to largest absolute and relative errors: +$${\tt ae\_max}=\max_{1\leq k \leq m+n}|h_k|,$$ +$${\tt re\_max}=\max_{1\leq k \leq m+n}\frac{|h_k|}{1+|x_k|}.$$ + +The third condition checked by the routine is: +$${\rm grad}\;Z = c = (\tilde{A})^T \pi + d,$$ +where $Z$ is the objective function, $c$ is the vector of objective +coefficients, $(\tilde{A})^T$ is a matrix transposed to the expanded +constraint matrix $\tilde{A} = (I|-A)$, $\pi$ is a vector of Lagrange +multipliers that correspond to equality constraints of the original LP +problem, $d$ is a vector of Lagrange multipliers that correspond to +bound constraints for all (auxiliary and structural) variables of the +original LP problem. Geometrically the third condition expresses the +requirement that the gradient of the objective function should belong +to the orthogonal complement of a linear subspace defined by the +equality and active bound constraints, i.e. that the gradient is +a linear combination of normals to the constraint hyperplanes, where +Lagrange multipliers $\pi$ and $d$ are coefficients of that linear +combination. + +To eliminate the vector $\pi$ rewrite the third condition as: +$$ +\left(\begin{array}{@{}c@{}}I \\ -A^T\end{array}\right) \pi = +\left(\begin{array}{@{}c@{}}d_R \\ d_S\end{array}\right) + +\left(\begin{array}{@{}c@{}}c_R \\ c_S\end{array}\right), +$$ +or, equivalently, +$$ +\left\{ +\begin{array}{r@{}c@{}c} +\pi + d_R&\ =\ &c_R, \\ +-A^T\pi + d_S&\ =\ &c_S. \\ +\end{array} +\right. +$$ + +Then substituting the vector $\pi$ from the first equation into the +second we finally have: +$$A^T (d_R - c_R) + (d_S - c_S) = 0, \eqno{\rm(KKT.DE)}$$ +where $d_R$ is the subvector of reduced costs of auxiliary variables +(rows), $d_S$ is the subvector of reduced costs of structural variables +(columns), $c_R$ and $c_S$ are subvectors of objective coefficients at, +respectively, auxiliary and structural variables, $A^T$ is a matrix +transposed to the constraint matrix of the original LP problem. In case +of exact arithmetic this condition would be satisfied for any basic +solution; however, in case of inexact (floating-point) arithmetic, this +condition shows how accurate the dual solution is, that depends on +accuracy of a representation of the basis matrix used by the simplex +method, or on accuracy provided by the interior-point method. + +To check the condition (KKT.DE) the routine computes a vector of +residuals: +$$u = A^T (d_R - c_R) + (d_S - c_S),$$ +and determines components of this vector that correspond to largest +absolute and relative errors: +$${\tt ae\_max}=\max_{1\leq j\leq n}|u_j|,$$ +$${\tt re\_max}=\max_{1\leq j\leq n}\frac{|u_j|}{1+|(d_S)_j-(c_S)_j|}.$$ + +\newpage + +The fourth condition checked by the routine is the following: +$$ +\left\{ +\begin{array}{l@{\ }r@{\ }c@{\ }c@{\ }c@{\ }l@{\ }c@{\ }c@{\ }c@{\ }l} +{\rm if} & -\infty & < & x_k & < & +\infty, +& {\rm then} & d_k & = & 0 \\ +{\rm if} & l_k & \leq & x_k & < & +\infty, +& {\rm then} & d_k & \geq & 0\ {\rm(minimization)} \\ +&&&&&& & d_k & \leq & 0\ {\rm(maximization)} \\ +{\rm if} & -\infty & < & x_k & \leq & u_k, +& {\rm then} & d_k & \leq & 0\ {\rm(minimization)} \\ +&&&&&& & d_k & \geq & 0\ {\rm(maximization)} \\ +{\rm if} & l_k & \leq & x_k & \leq & u_k, +& {\rm then} & d_k & {\rm is} & {\rm of\ any\ sign} \\ +\end{array}\right.\eqno{\rm(KKT.DB)} +$$ +for all $k=1,\dots,m+n$, where $d_k$ is a reduced cost (Lagrange +multiplier) of auxiliary ($1\leq k\leq m$) or structural +($m+1\leq k\leq m+n$) variable $x_k$. Geometrically this condition +expresses the requirement that constraints of the original problem must +``hold'' the point preventing its movement along the anti-gradient (in +case of minimization) or the gradient (in case of maximization) of the +objective function. In case of basic solution reduced costs of all +basic variables are placed on their active (zero) bounds, so actually +the condition (KKT.DB) needs to be checked for non-basic variables +only. If the dual solution has sufficient accuracy, this condition +shows the dual feasibility of the solution. + +To check the condition (KKT.DB) the routine computes a vector of +residuals: +$$ +v_k = \left\{ +\begin{array}{ll} +0, & {\rm if}\ d_k\ {\rm has\ correct\ sign} \\ +|d_k|, & {\rm if}\ d_k\ {\rm has\ wrong\ sign} \\ +\end{array} +\right. +$$ +for all $k=1,\dots,m+n$, and determines components of this vector that +correspond to largest absolute and relative errors: +$${\tt ae\_max}=\max_{1\leq k\leq m+n}|v_k|,$$ +$${\tt re\_max}=\max_{1\leq k\leq m+n}\frac{|v_k|}{1+|d_k - c_k|}.$$ + +Note that the complete set of Karush-Kuhn-Tucker optimality conditions +also includes the fifth, so called {\it complementary slackness +condition}, which expresses the requirement that at least either +a primal variable $x_k$ or its dual counterpart $d_k$ should be on its +bound for all $k=1,\dots,m+n$. Currently checking this condition is +not implemented yet. + +\def\arraystretch{1} + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk03.tex b/resources/3rdparty/glpk-4.53/doc/glpk03.tex new file mode 100644 index 000000000..82848a14b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk03.tex @@ -0,0 +1,1572 @@ +%* glpk03.tex *% + +\chapter{Utility API routines} + +\section{Problem data reading/writing routines} + +\subsection{glp\_read\_mps --- read problem data in MPS format} + +\synopsis + +\begin{verbatim} + int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_mps| reads problem data in MPS format from a +text file. (The MPS format is described in Appendix \ref{champs}, page +\pageref{champs}.) + +The parameter \verb|fmt| specifies the MPS format version as follows: + +\verb|GLP_MPS_DECK| --- fixed (ancient) MPS format; + +\verb|GLP_MPS_FILE| --- free (modern) MPS format. + +The parameter \verb|parm| is reserved for use in the future and should +be specified as \verb|NULL|. + +The character string \verb|fname| specifies a name of the text file to +be read in. (If the file name ends with suffix `\verb|.gz|', the file +is assumed to be compressed, in which case the routine +\verb|glp_read_mps| decompresses it ``on the fly''.) + +Note that before reading data the current content of the problem object +is completely erased with the routine \verb|glp_erase_prob|. + +\returns + +If the operation was successful, the routine \verb|glp_read_mps| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\newpage + +\subsection{glp\_write\_mps --- write problem data in MPS format} + +\synopsis + +\begin{verbatim} + int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_mps| writes problem data in MPS format to +a text file. (The MPS format is described in Appendix \ref{champs}, +page \pageref{champs}.) + +The parameter \verb|fmt| specifies the MPS format version as follows: + +\verb|GLP_MPS_DECK| --- fixed (ancient) MPS format; + +\verb|GLP_MPS_FILE| --- free (modern) MPS format. + +The parameter \verb|parm| is reserved for use in the future and should +be specified as \verb|NULL|. + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine +\verb|glp_write_mps| performs automatic compression on writing it.) + +\returns + +If the operation was successful, the routine \verb|glp_write_mps| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\subsection{glp\_read\_lp --- read problem data in CPLEX LP format} + +\synopsis + +{\tt int glp\_read\_lp(glp\_prob *P, const glp\_cpxcp *parm, +const char *fname);} + +\description + +The routine \verb|glp_read_lp| reads problem data in CPLEX LP format +from a text file. (The CPLEX LP format is described in Appendix +\ref{chacplex}, page \pageref{chacplex}.) + +The parameter \verb|parm| is reserved for use in the future and should +be specified as \verb|NULL|. + +The character string \verb|fname| specifies a name of the text file to +be read in. (If the file name ends with suffix `\verb|.gz|', the file +is assumed to be compressed, in which case the routine +\verb|glp_read_lp| decompresses it ``on the fly''.) + +Note that before reading data the current content of the problem object +is completely erased with the routine \verb|glp_erase_prob|. + +\returns + +If the operation was successful, the routine \verb|glp_read_lp| returns +zero. Otherwise, it prints an error message and returns non-zero. + +\newpage + +\subsection{glp\_write\_lp --- write problem data in CPLEX LP format} + +\synopsis + +{\tt int glp\_write\_lp(glp\_prob *P, const glp\_cpxcp *parm, +const char *fname);} + +\description + +The routine \verb|glp_write_lp| writes problem data in CPLEX LP format +to a text file. (The CPLEX LP format is described in Appendix +\ref{chacplex}, page \pageref{chacplex}.) + +The parameter \verb|parm| is reserved for use in the future and should +be specified as \verb|NULL|. + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine +\verb|glp_write_lp| performs automatic compression on writing it.) + +\returns + +If the operation was successful, the routine \verb|glp_write_lp| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\subsection{glp\_read\_prob --- read problem data in GLPK format} + +\synopsis + +\begin{verbatim} + int glp_read_prob(glp_prob *P, int flags, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_prob| reads problem data in the GLPK LP/MIP +format from a text file. (For description of the GLPK LP/MIP format see +below.) + +The parameter \verb|flags| is reserved for use in the future and should +be specified as zero. + +The character string \verb|fname| specifies a name of the text file to +be read in. (If the file name ends with suffix `\verb|.gz|', the file +is assumed to be compressed, in which case the routine +\verb|glp_read_prob| decompresses it ``on the fly''.) + +Note that before reading data the current content of the problem object +is completely erased with the routine \verb|glp_erase_prob|. + +\returns + +If the operation was successful, the routine \verb|glp_read_prob| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\newpage + +\para{GLPK LP/MIP format} + +The GLPK LP/MIP format is a DIMACS-like format.\footnote{The DIMACS +formats were developed by the Center for Discrete Mathematics and +Theoretical Computer Science (DIMACS) to facilitate exchange of problem +data. For details see: {\tt <http://dimacs.rutgers.edu/Challenges/>}. } +The file in this format is a plain ASCII text file containing lines of +several types described below. A line is terminated with the +end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +The first line of the data file must be the problem line (except +optional comment lines, which may precede the problem line). The last +line of the data file must be the end line. Other lines may follow in +arbitrary order, however, duplicate lines are not allowed. + +\para{Comment lines.} Comment lines give human-readable +information about the data file and are ignored by GLPK routines. +Comment lines can appear anywhere in the data file. Each comment line +begins with the lower-case character \verb|c|. + +\begin{verbatim} + c This is an example of comment line +\end{verbatim} + +\para{Problem line.} There must be exactly one problem line in the +data file. This line must appear before any other lines except comment +lines and has the following format: + +\begin{verbatim} + p CLASS DIR ROWS COLS NONZ +\end{verbatim} + +The lower-case letter \verb|p| specifies that this is the problem line. + +The \verb|CLASS| field defines the problem class and can contain either +the keyword \verb|lp| (that means linear programming problem) or +\verb|mip| (that means mixed integer programming problem). + +The \verb|DIR| field defines the optimization direction (that is, the +objective function sense) and can contain either the keyword \verb|min| +(that means minimization) or \verb|max| (that means maximization). + +The \verb|ROWS|, \verb|COLS|, and \verb|NONZ| fields contain +non-negative integer values specifying, respectively, the number of +rows (constraints), columns (variables), and non-zero constraint +coefficients in the problem instance. Note that \verb|NONZ| value does +not account objective coefficients. + +\para{Row descriptors.} There must be at most one row descriptor line +in the data file for each row (constraint). This line has one of the +following formats: + +\begin{verbatim} + i ROW f + i ROW l RHS + i ROW u RHS + i ROW d RHS1 RHS2 + i ROW s RHS +\end{verbatim} + +The lower-case letter \verb|i| specifies that this is the row +descriptor line. + +The \verb|ROW| field specifies the row ordinal number, an integer +between 1 and $m$, where $m$ is the number of rows in the problem +instance. + +The next lower-case letter specifies the row type as follows: + +\verb|f| --- free (unbounded) row: $-\infty<\sum a_jx_j<+\infty$; + +\verb|l| --- inequality constraint of `$\geq$' type: +$\sum a_jx_j\geq b$; + +\verb|u| --- inequality constraint of `$\leq$' type: +$\sum a_jx_j\leq b$; + +\verb|d| --- double-sided inequality constraint: +$b_1\leq\sum a_jx_j\leq b_2$; + +\verb|s| --- equality constraint: $\sum a_jx_j=b$. + +The \verb|RHS| field contains a floaing-point value specifying the +row right-hand side. The \verb|RHS1| and \verb|RHS2| fields contain +floating-point values specifying, respectively, the lower and upper +right-hand sides for the double-sided row. + +If for some row its descriptor line does not appear in the data file, +by default that row is assumed to be an equality constraint with zero +right-hand side. + +\para{Column descriptors.} There must be at most one column descriptor +line in the data file for each column (variable). This line has one of +the following formats depending on the problem class specified in the +problem line: + +\begin{tabular}{@{}l@{\hspace*{40pt}}l} +LP class & MIP class \\ +\hline +\verb|j COL f| & \verb|j COL KIND f| \\ +\verb|j COL l BND| & \verb|j COL KIND l BND| \\ +\verb|j COL u BND| & \verb|j COL KIND u BND| \\ +\verb|j COL d BND1 BND2| & \verb|j COL KIND d BND1 BND2| \\ +\verb|j COL s BND| & \verb|j COL KIND s BND| \\ +\end{tabular} + +The lower-case letter \verb|j| specifies that this is the column +descriptor line. + +The \verb|COL| field specifies the column ordinal number, an integer +between 1 and $n$, where $n$ is the number of columns in the problem +instance. + +The \verb|KIND| field is used only for MIP problems and specifies the +column kind as follows: + +\verb|c| --- continuous column; + +\verb|i| --- integer column; + +\verb|b| --- binary column (in this case all remaining fields must be +omitted). + +The next lower-case letter specifies the column type as follows: + +\verb|f| --- free (unbounded) column: $-\infty<x<+\infty$; + +\verb|l| --- column with lower bound: $x\geq l$; + +\verb|u| --- column with upper bound: $x\leq u$; + +\verb|d| --- double-bounded column: $l\leq x\leq u$; + +\verb|s| --- fixed column: $x=s$. + +The \verb|BND| field contains a floating-point value that specifies the +column bound. The \verb|BND1| and \verb|BND2| fields contain +floating-point values specifying, respectively, the lower and upper +bounds for the double-bounded column. + +If for some column its descriptor line does not appear in the file, by +default that column is assumed to be non-negative (in case of LP class) +or binary (in case of MIP class). + +\para{Coefficient descriptors.} There must be exactly one coefficient +descriptor line in the data file for each non-zero objective or +constraint coefficient. This line has the following format: + +\begin{verbatim} + a ROW COL VAL +\end{verbatim} + +The lower-case letter \verb|a| specifies that this is the coefficient +descriptor line. + +For objective coefficients the \verb|ROW| field must contain 0. For +constraint coefficients the \verb|ROW| field specifies the row ordinal +number, an integer between 1 and $m$, where $m$ is the number of rows +in the problem instance. + +The \verb|COL| field specifies the column ordinal number, an integer +between 1 and $n$, where $n$ is the number of columns in the problem +instance. + +If both the \verb|ROW| and \verb|COL| fields contain 0, the line +specifies the constant term (``shift'') of the objective function +rather than objective coefficient. + +The \verb|VAL| field contains a floating-point coefficient value (it is +allowed to specify zero value in this field). + +The number of constraint coefficient descriptor lines must be exactly +the same as specified in the field \verb|NONZ| of the problem line. + +\para{Symbolic name descriptors.} There must be at most one symbolic +name descriptor line for the problem instance, objective function, each +row (constraint), and each column (variable). This line has one of the +following formats: + +\begin{verbatim} + n p NAME + n z NAME + n i ROW NAME + n j COL NAME +\end{verbatim} + +The lower-case letter \verb|n| specifies that this is the symbolic name +descriptor line. + +The next lower-case letter specifies which object should be assigned a +symbolic name: + +\verb|p| --- problem instance; + +\verb|z| --- objective function; + +\verb|i| --- row (constraint); + +\verb|j| --- column (variable). + +The \verb|ROW| field specifies the row ordinal number, an integer +between 1 and $m$, where $m$ is the number of rows in the problem +instance. + +The \verb|COL| field specifies the column ordinal number, an integer +between 1 and $n$, where $n$ is the number of columns in the problem +instance. + +The \verb|NAME| field contains the symbolic name, a sequence from 1 to +255 arbitrary graphic ASCII characters, assigned to corresponding +object. + +\para{End line.} There must be exactly one end line in the data file. +This line must appear last in the file and has the following format: + +\begin{verbatim} + e +\end{verbatim} + +The lower-case letter \verb|e| specifies that this is the end line. +Anything that follows the end line is ignored by GLPK routines. + +\newpage + +\para{Example of data file in GLPK LP/MIP format} + +The following example of a data file in GLPK LP/MIP format specifies +the same LP problem as in Subsection ``Example of MPS file''. + +\bigskip + +\begin{center} +\footnotesize\tt +\begin{tabular}{l@{\hspace*{50pt}}} +p lp min 8 7 48 \\ +n p PLAN \\ +n z VALUE \\ +i 1 f \\ +n i 1 VALUE \\ +i 2 s 2000 \\ +n i 2 YIELD \\ +i 3 u 60 \\ +n i 3 FE \\ +i 4 u 100 \\ +n i 4 CU \\ +i 5 u 40 \\ +n i 5 MN \\ +i 6 u 30 \\ +n i 6 MG \\ +i 7 l 1500 \\ +n i 7 AL \\ +i 8 d 250 300 \\ +n i 8 SI \\ +j 1 d 0 200 \\ +n j 1 BIN1 \\ +j 2 d 0 2500 \\ +n j 2 BIN2 \\ +j 3 d 400 800 \\ +n j 3 BIN3 \\ +j 4 d 100 700 \\ +n j 4 BIN4 \\ +j 5 d 0 1500 \\ +n j 5 BIN5 \\ +n j 6 ALUM \\ +n j 7 SILICON \\ +a 0 1 0.03 \\ +a 0 2 0.08 \\ +a 0 3 0.17 \\ +a 0 4 0.12 \\ +a 0 5 0.15 \\ +a 0 6 0.21 \\ +a 0 7 0.38 \\ +a 1 1 0.03 \\ +a 1 2 0.08 \\ +a 1 3 0.17 \\ +a 1 4 0.12 \\ +a 1 5 0.15 \\ +a 1 6 0.21 \\ +\end{tabular} +\begin{tabular}{|@{\hspace*{80pt}}l} +a 1 7 0.38 \\ +a 2 1 1 \\ +a 2 2 1 \\ +a 2 3 1 \\ +a 2 4 1 \\ +a 2 5 1 \\ +a 2 6 1 \\ +a 2 7 1 \\ +a 3 1 0.15 \\ +a 3 2 0.04 \\ +a 3 3 0.02 \\ +a 3 4 0.04 \\ +a 3 5 0.02 \\ +a 3 6 0.01 \\ +a 3 7 0.03 \\ +a 4 1 0.03 \\ +a 4 2 0.05 \\ +a 4 3 0.08 \\ +a 4 4 0.02 \\ +a 4 5 0.06 \\ +a 4 6 0.01 \\ +a 5 1 0.02 \\ +a 5 2 0.04 \\ +a 5 3 0.01 \\ +a 5 4 0.02 \\ +a 5 5 0.02 \\ +a 6 1 0.02 \\ +a 6 2 0.03 \\ +a 6 5 0.01 \\ +a 7 1 0.7 \\ +a 7 2 0.75 \\ +a 7 3 0.8 \\ +a 7 4 0.75 \\ +a 7 5 0.8 \\ +a 7 6 0.97 \\ +a 8 1 0.02 \\ +a 8 2 0.06 \\ +a 8 3 0.08 \\ +a 8 4 0.12 \\ +a 8 5 0.02 \\ +a 8 6 0.01 \\ +a 8 7 0.97 \\ +e o f \\ +\\ +\end{tabular} +\end{center} + +\newpage + +\subsection{glp\_write\_prob --- write problem data in GLPK format} + +\synopsis + +\begin{verbatim} +int glp_write_prob(glp_prob *P, int flags, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_prob| writes problem data in the GLPK +LP/MIP format to a text file. (For description of the GLPK LP/MIP +format see Subsection ``Read problem data in GLPK format''.) + +The parameter \verb|flags| is reserved for use in the future and should +be specified as zero. + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine +\verb|glp_write_prob| performs automatic compression on writing it.) + +\returns + +If the operation was successful, the routine \verb|glp_read_prob| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Routines for processing MathProg models} + +\subsection{Introduction} + +GLPK supports the {\it GNU MathProg modeling language}.\footnote{The +GNU MathProg modeling language is a subset of the AMPL language. For +its detailed description see the document ``Modeling Language GNU +MathProg: Language Reference'' included in the GLPK distribution.} +As a rule, models written in MathProg are solved with the GLPK LP/MIP +stand-alone solver \verb|glpsol| (see Appendix D) and do not need any +programming with API routines. However, for various reasons the user +may need to process MathProg models directly in his/her application +program, in which case he/she may use API routines described in this +section. These routines provide an interface to the {\it MathProg +translator}, a component of GLPK, which translates MathProg models into +an internal code and then interprets (executes) this code. + +The processing of a model written in GNU MathProg includes several +steps, which should be performed in the following order: + +\vspace*{-8pt} + +\begin{enumerate} +\item{\it Allocating the workspace.} +The translator allocates the workspace, an internal data structure used +on all subsequent steps. + +\item{\it Reading model section.} The translator reads model section +and, optionally, data section from a specified text file and translates +them into the internal code. If necessary, on this step data section +may be ignored. + +\item{\it Reading data section(s).} The translator reads one or more +data sections from specified text file(s) and translates them into the +internal code. + +\item{\it Generating the model.} The translator executes the internal +code to evaluate the content of the model objects such as sets, +parameters, variables, constraints, and objectives. On this step the +execution is suspended at the solve statement. + +\item {\it Building the problem object.} The translator obtains all +necessary information from the workspace and builds the standard +problem object (that is, the program object of type \verb|glp_prob|). + +\item{\it Solving the problem.} On this step the problem object built +on the previous step is passed to a solver, which solves the problem +instance and stores its solution back to the problem object. + +\item{\it Postsolving the model.} The translator copies the solution +from the problem object to the workspace and then executes the internal +code from the solve statement to the end of the model. (If model has +no solve statement, the translator does nothing on this step.) + +\item{\it Freeing the workspace.} The translator frees all the memory +allocated to the workspace. +\end{enumerate} + +\vspace*{-8pt} + +Note that the MathProg translator performs no error correction, so if +any of steps 2 to 7 fails (due to errors in the model), the application +program should terminate processing and go to\linebreak step 8. + +\newpage + +\para{Example 1} + +In this example the program reads model and data sections from input +file \verb|egypt.mod|\footnote{This is an example model included in +the GLPK distribution.} and writes the model to output file +\verb|egypt.mps| in free MPS format (see Appendix B). No solution is +performed. + +\bigskip + +\begin{small} +\begin{verbatim} +/* mplsamp1.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *lp; + glp_tran *tran; + int ret; + lp = glp_create_prob(); + tran = glp_mpl_alloc_wksp(); + ret = glp_mpl_read_model(tran, "egypt.mod", 0); + if (ret != 0) + { fprintf(stderr, "Error on translating model\n"); + goto skip; + } + ret = glp_mpl_generate(tran, NULL); + if (ret != 0) + { fprintf(stderr, "Error on generating model\n"); + goto skip; + } + glp_mpl_build_prob(tran, lp); + ret = glp_write_mps(lp, GLP_MPS_FILE, NULL, "egypt.mps"); + if (ret != 0) + fprintf(stderr, "Error on writing MPS file\n"); +skip: glp_mpl_free_wksp(tran); + glp_delete_prob(lp); + return 0; +} + +/* eof */ +\end{verbatim} +\end{small} + +\newpage + +\subsubsection*{Example 2} + +In this example the program reads model section from file +\verb|sudoku.mod|\footnote{This is an example model which is included +in the GLPK distribution along with alternative data file +{\tt sudoku.dat}.} ignoring data section in this file, reads alternative +data section from file \verb|sudoku.dat|, solves the problem instance +and passes the solution found back to the model. + +\bigskip + +\begin{small} +\begin{verbatim} +/* mplsamp2.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *mip; + glp_tran *tran; + int ret; + mip = glp_create_prob(); + tran = glp_mpl_alloc_wksp(); + ret = glp_mpl_read_model(tran, "sudoku.mod", 1); + if (ret != 0) + { fprintf(stderr, "Error on translating model\n"); + goto skip; + } + ret = glp_mpl_read_data(tran, "sudoku.dat"); + if (ret != 0) + { fprintf(stderr, "Error on translating data\n"); + goto skip; + } + ret = glp_mpl_generate(tran, NULL); + if (ret != 0) + { fprintf(stderr, "Error on generating model\n"); + goto skip; + } + glp_mpl_build_prob(tran, mip); + glp_simplex(mip, NULL); + glp_intopt(mip, NULL); + ret = glp_mpl_postsolve(tran, mip, GLP_MIP); + if (ret != 0) + fprintf(stderr, "Error on postsolving model\n"); +skip: glp_mpl_free_wksp(tran); + glp_delete_prob(mip); + return 0; +} + +/* eof */ +\end{verbatim} +\end{small} + +\newpage + +\subsection{glp\_mpl\_alloc\_wksp --- allocate the translator +workspace} + +\synopsis + +\begin{verbatim} + glp_tran *glp_mpl_alloc_wksp(void); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_alloc_wksp| allocates the MathProg translator +work\-space. (Note that multiple instances of the workspace may be +allocated, if necessary.) + +\returns + +The routine returns a pointer to the workspace, which should be used in +all subsequent operations. + +\subsection{glp\_mpl\_read\_model --- read and translate model section} + +\synopsis + +\begin{verbatim} + int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_read_model| reads model section and, +optionally, data section, which may follow the model section, from a +text file, whose name is the character string \verb|fname|, performs +translation of model statements and data blocks, and stores all the +information in the workspace. + +The parameter \verb|skip| is a flag. If the input file contains the +data section and this flag is non-zero, the data section is not read as +if there were no data section and a warning message is printed. This +allows reading data section(s) from other file(s). + +\returns + +If the operation is successful, the routine returns zero. Otherwise +the routine prints an error message and returns non-zero. + +\subsection{glp\_mpl\_read\_data --- read and translate data section} + +\synopsis + +\begin{verbatim} + int glp_mpl_read_data(glp_tran *tran, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_read_data| reads data section from a text +file, whose name is the character string \verb|fname|, performs +translation of data blocks, and stores the data read in the translator +workspace. If necessary, this routine may be called more than once. + +\returns + +If the operation is successful, the routine returns zero. Otherwise +the routine prints an error message and returns non-zero. + +\newpage + +\subsection{glp\_mpl\_generate --- generate the model} + +\synopsis + +\begin{verbatim} + int glp_mpl_generate(glp_tran *tran, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_generate| generates the model using its +description stored in the translator workspace. This operation means +generating all variables, constraints, and objectives, executing check +and display statements, which precede the solve statement (if it is +presented). + +The character string \verb|fname| specifies the name of an output text +file, to which output produced by display statements should be written. +If \verb|fname| is \verb|NULL|, the output is sent to the terminal. + +\returns + +If the operation is successful, the routine returns zero. Otherwise +the routine prints an error message and returns non-zero. + +\vspace*{-6pt} + +\subsection{glp\_mpl\_build\_prob --- build problem instance from the +model} + +\synopsis + +\begin{verbatim} + void glp_mpl_build_prob(glp_tran *tran, glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_build_prob| obtains all necessary information +from the translator work\-space and stores it in the specified problem +object \verb|P|. Note that before building the current content of the +problem object is erased with the routine \verb|glp_erase_prob|. + +\vspace*{-6pt} + +\subsection{glp\_mpl\_postsolve --- postsolve the model} + +\synopsis + +\begin{verbatim} + int glp_mpl_postsolve(glp_tran *tran, glp_prob *P, int sol); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_postsolve| copies the solution from the +specified problem object \verb|prob| to the translator workspace and +then executes all the remaining model statements, which follow the +solve statement. + +The parameter \verb|sol| specifies which solution should be copied +from the problem object to the workspace as follows: + +\verb|GLP_SOL| --- basic solution; + +\verb|GLP_IPT| --- interior-point solution; + +\verb|GLP_MIP| --- mixed integer solution. + +\returns + +If the operation is successful, the routine returns zero. Otherwise +the routine prints an error message and returns non-zero. + +\subsection{glp\_mpl\_free\_wksp --- free the translator workspace} + +\synopsis + +\begin{verbatim} + void glp_mpl_free_wksp(glp_tran *tran); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_free_wksp| frees all the memory allocated to +the translator workspace. It also frees all other resources, which are +still used by the translator. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Problem solution reading/writing routines} + +\subsection{glp\_print\_sol --- write basic solution in printable +format} + +\synopsis + +\begin{verbatim} + int glp_print_sol(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_print_sol writes| the current basic solution of +an LP problem, which is specified by the pointer \verb|P|, to a text +file, whose name is the character string \verb|fname|, in printable +format. + +Information reported by the routine \verb|glp_print_sol| is intended +mainly for visual analysis. + +\returns + +If no errors occurred, the routine returns zero. Otherwise the routine +prints an error message and returns non-zero. + +\subsection{glp\_read\_sol --- read basic solution from text file} + +\synopsis + +\begin{verbatim} + int glp_read_sol(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_sol| reads basic solution from a text file +whose name is specified by the parameter \verb|fname| into the problem +object. + +For the file format see description of the routine +\verb|glp_write_sol|. + +\returns + +On success the routine returns zero, otherwise non-zero. + +\subsection{glp\_write\_sol --- write basic solution to text file} + +\synopsis + +\begin{verbatim} + int glp_write_sol(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_sol| writes the current basic solution to +a text file whose name is specified by the parameter \verb|fname|. This +file can be read back with the routine \verb|glp_read_sol|. + +\returns + +On success the routine returns zero, otherwise non-zero. + +\newpage + +\para{File format} + +The file created by the routine \verb|glp_write_sol| is a plain text +file, which contains the following information: + +\begin{verbatim} + m n + p_stat d_stat obj_val + r_stat[1] r_prim[1] r_dual[1] + . . . + r_stat[m] r_prim[m] r_dual[m] + c_stat[1] c_prim[1] c_dual[1] + . . . + c_stat[n] c_prim[n] c_dual[n] +\end{verbatim} + +\noindent +where: + +\noindent +$m$ is the number of rows (auxiliary variables); + +\noindent +$n$ is the number of columns (structural variables); + +\noindent +\verb|p_stat| is the primal status of the basic solution\\ +(\verb|GLP_UNDEF| = 1, \verb|GLP_FEAS| = 2, \verb|GLP_INFEAS| = 3, or +\verb|GLP_NOFEAS| = 4); + +\noindent +\verb|d_stat| is the dual status of the basic solution\\ +(\verb|GLP_UNDEF| = 1, \verb|GLP_FEAS| = 2, \verb|GLP_INFEAS| = 3, or +\verb|GLP_NOFEAS| = 4); + +\noindent +\verb|obj_val| is the objective value; + +\noindent +\verb|r_stat[i]|, $i=1,\dots,m$, is the status of $i$-th row\\ +(\verb|GLP_BS| = 1, \verb|GLP_NL| = 2, \verb|GLP_NU| = 3, +\verb|GLP_NF| = 4, or \verb|GLP_NS| = 5); + +\noindent +\verb|r_prim[i]|, $i=1,\dots,m$, is the primal value of $i$-th row; + +\noindent +\verb|r_dual[i]|, $i=1,\dots,m$, is the dual value of $i$-th row; + +\noindent +\verb|c_stat[j]|, $j=1,\dots,n$, is the status of $j$-th column\\ +(\verb|GLP_BS| = 1, \verb|GLP_NL| = 2, \verb|GLP_NU| = 3, +\verb|GLP_NF| = 4, or \verb|GLP_NS| = 5); + +\noindent +\verb|c_prim[j]|, $j=1,\dots,n$, is the primal value of $j$-th column; + +\noindent +\verb|c_dual[j]|, $j=1,\dots,n$, is the dual value of $j$-th column. + +\subsection{glp\_print\_ipt --- write interior-point solution in +printable format} + +\synopsis + +\begin{verbatim} + int glp_print_ipt(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_print_ipt| writes the current interior point +solution of an LP problem, which the parameter \verb|P| points to, to +a text file, whose name is the character string \verb|fname|, in +printable format. + +Information reported by the routine \verb|glp_print_ipt| is intended +mainly for visual analysis. + +\newpage + +\returns + +If no errors occurred, the routine returns zero. Otherwise the routine +prints an error message and returns non-zero. + +\subsection{glp\_read\_ipt --- read interior-point solution from text +file} + +\synopsis + +\begin{verbatim} + int glp_read_ipt(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_ipt| reads interior-point solution from +a text file whose name is specified by the parameter \verb|fname| into +the problem object. + +For the file format see description of the routine +\verb|glp_write_ipt|. + +\returns + +On success the routine returns zero, otherwise non-zero. + +\subsection{glp\_write\_ipt --- write interior-point solution to text +file} + +\synopsis + +\begin{verbatim} + int glp_write_ipt(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_ipt| writes the current interior-point +solution to a text file whose name is specified by the parameter +\verb|fname|. This file can be read back with the routine +\verb|glp_read_ipt|. + +\returns + +On success the routine returns zero, otherwise non-zero. + +\para{File format} + +The file created by the routine \verb|glp_write_ipt| is a plain text +file, which contains the following information: + +\begin{verbatim} + m n + stat obj_val + r_prim[1] r_dual[1] + . . . + r_prim[m] r_dual[m] + c_prim[1] c_dual[1] + . . . + c_prim[n] c_dual[n] +\end{verbatim} + +\noindent +where: + +\noindent +$m$ is the number of rows (auxiliary variables); + +\noindent +$n$ is the number of columns (structural variables); + +\noindent +\verb|stat| is the solution status (\verb|GLP_UNDEF| = 1 or +\verb|GLP_OPT| = 5); + +\noindent +\verb|obj_val| is the objective value; + +\noindent +\verb|r_prim[i]|, $i=1,\dots,m$, is the primal value of $i$-th row; + +\noindent +\verb|r_dual[i]|, $i=1,\dots,m$, is the dual value of $i$-th row; + +\noindent +\verb|c_prim[j]|, $j=1,\dots,n$, is the primal value of $j$-th column; + +\noindent +\verb|c_dual[j]|, $j=1,\dots,n$, is the dual value of $j$-th column. + +\subsection{glp\_print\_mip --- write MIP solution in printable format} + +\synopsis + +\begin{verbatim} + int glp_print_mip(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_print_mip| writes a best known integer solution +of a MIP problem, which is specified by the pointer \verb|P|, to +a text file, whose name is the character string \verb|fname|, in +printable format. + +Information reported by the routine \verb|glp_print_mip| is intended +mainly for visual analysis. + +\returns + +If no errors occurred, the routine returns zero. Otherwise the routine +prints an error message and returns non-zero. + +\subsection{glp\_read\_mip --- read MIP solution from text file} + +\synopsis + +\begin{verbatim} + int glp_read_mip(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_mip| reads MIP solution from a text file +whose name is specified by the parameter \verb|fname| into the problem +object. + +For the file format see description of the routine +\verb|glp_write_mip|. + +\returns + +On success the routine returns zero, otherwise non-zero. + +\newpage + +\subsection{glp\_write\_mip --- write MIP solution to text file} + +\synopsis + +\begin{verbatim} + int glp_write_mip(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_mip| writes the current MIP solution to +a text file whose name is specified by the parameter \verb|fname|. This +file can be read back with the routine \verb|glp_read_mip|. + +\returns + +On success the routine returns zero, otherwise non-zero. + +\para{File format} + +The file created by the routine \verb|glp_write_sol| is a plain text +file, which contains the following information: + +\begin{verbatim} + m n + stat obj_val + r_val[1] + . . . + r_val[m] + c_val[1] + . . . + c_val[n] +\end{verbatim} + +\noindent +where: + +\noindent +$m$ is the number of rows (auxiliary variables); + +\noindent +$n$ is the number of columns (structural variables); + +\noindent +\verb|stat| is the solution status\\(\verb|GLP_UNDEF| = 1, +\verb|GLP_FEAS| = 2, \verb|GLP_NOFEAS| = 4, or \verb|GLP_OPT| = 5); + +\noindent +\verb|obj_val| is the objective value; + +\noindent +\verb|r_val[i]|, $i=1,\dots,m$, is the value of $i$-th row; + +\noindent +\verb|c_val[j]|, $j=1,\dots,n$, is the value of $j$-th column. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Post-optimal analysis routines} + +\subsection{glp\_print\_ranges --- print sensitivity analysis report} + +\synopsis + +{\tt int glp\_print\_ranges(glp\_prob *P, int len, const int list[], +int flags,\\ +\hspace*{134pt}const char *fname);} + +\description + +The routine \verb|glp_print_ranges| performs sensitivity analysis of +current optimal basic solution and writes the analysis report in +human-readable format to a text file, whose name is the character +string {\it fname}. (Detailed description of the report structure is +given below.) + +The parameter {\it len} specifies the length of the row/column list. + +The array {\it list} specifies ordinal number of rows and columns to be +analyzed. The ordinal numbers should be passed in locations +{\it list}[1], {\it list}[2], \dots, {\it list}[{\it len}]. Ordinal +numbers from 1 to $m$ refer to rows, and ordinal numbers from $m+1$ to +$m+n$ refer to columns, where $m$ and $n$ are, resp., the total number +of rows and columns in the problem object. Rows and columns appear in +the analysis report in the same order as they follow in the array list. + +It is allowed to specify $len=0$, in which case the array {\it list} is +not used (so it can be specified as \verb|NULL|), and the routine +performs analysis for all rows and columns of the problem object. + +The parameter {\it flags} is reserved for use in the future and must be +specified as zero. + +On entry to the routine \verb|glp_print_ranges| the current basic +solution must be optimal and the basis factorization must exist. +The application program can check that with the routine +\verb|glp_bf_exists|, and if the factorization does +not exist, compute it with the routine \verb|glp_factorize|. Note that +if the LP preprocessor is not used, on normal exit from the simplex +solver routine \verb|glp_simplex| the basis factorization always exists. + +\returns + +If the operation was successful, the routine \verb|glp_print_ranges| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\para{Analysis report example} + +An example of the sensitivity analysis report is shown on the next two +pages. This example corresponds to the example of LP problem described +in Subsection ``Example of MPS file''. + +\para{Structure of the analysis report} + +For each row and column specified in the array {\it list} the routine +prints two lines containing generic information and analysis +information, which depends on the status of corresponding row or column. + +Note that analysis of a row is analysis of its auxiliary variable, +which is equal to the row linear form $\sum a_jx_j$, and analysis of +a column is analysis of corresponding structural variable. Therefore, +formally, on performing the sensitivity analysis there is no difference +between rows and columns. + +\newpage + +\begin{landscape} +\begin{footnotesize} +\begin{verbatim} +GLPK 4.42 - SENSITIVITY ANALYSIS REPORT Page 1 + +Problem: PLAN +Objective: VALUE = 296.2166065 (MINimum) + + No. Row name St Activity Slack Lower bound Activity Obj coef Obj value at Limiting + Marginal Upper bound range range break point variable +------ ------------ -- ------------- ------------- ------------- ------------- ------------- ------------- ------------ + 1 VALUE BS 296.21661 -296.21661 -Inf 299.25255 -1.00000 . MN + . +Inf 296.21661 +Inf +Inf + + 2 YIELD NS 2000.00000 . 2000.00000 1995.06864 -Inf 296.28365 BIN3 + -.01360 2000.00000 2014.03479 +Inf 296.02579 CU + + 3 FE NU 60.00000 . -Inf 55.89016 -Inf 306.77162 BIN4 + -2.56823 60.00000 62.69978 2.56823 289.28294 BIN3 + + 4 CU BS 83.96751 16.03249 -Inf 93.88467 -.30613 270.51157 MN + . 100.00000 79.98213 .21474 314.24798 BIN5 + + 5 MN NU 40.00000 . -Inf 34.42336 -Inf 299.25255 BIN4 + -.54440 40.00000 41.68691 .54440 295.29825 BIN3 + + 6 MG BS 19.96029 10.03971 -Inf 24.74427 -1.79618 260.36433 BIN1 + . 30.00000 9.40292 .28757 301.95652 MN + + 7 AL NL 1500.00000 . 1500.00000 1485.78425 -.25199 292.63444 CU + .25199 +Inf 1504.92126 +Inf 297.45669 BIN3 + + 8 SI NL 250.00000 50.00000 250.00000 235.32871 -.48520 289.09812 CU + .48520 300.00000 255.06073 +Inf 298.67206 BIN3 +\end{verbatim} +\end{footnotesize} +\end{landscape} + +\newpage + +\begin{landscape} +\begin{footnotesize} +\begin{verbatim} +GLPK 4.42 - SENSITIVITY ANALYSIS REPORT Page 2 + +Problem: PLAN +Objective: VALUE = 296.2166065 (MINimum) + + No. Column name St Activity Obj coef Lower bound Activity Obj coef Obj value at Limiting + Marginal Upper bound range range break point variable +------ ------------ -- ------------- ------------- ------------- ------------- ------------- ------------- ------------ + 1 BIN1 NL . .03000 . -28.82475 -.22362 288.90594 BIN4 + .25362 200.00000 33.88040 +Inf 304.80951 BIN4 + + 2 BIN2 BS 665.34296 .08000 . 802.22222 .01722 254.44822 BIN1 + . 2500.00000 313.43066 .08863 301.95652 MN + + 3 BIN3 BS 490.25271 .17000 400.00000 788.61314 .15982 291.22807 MN + . 800.00000 -347.42857 .17948 300.86548 BIN5 + + 4 BIN4 BS 424.18773 .12000 100.00000 710.52632 .10899 291.54745 MN + . 700.00000 -256.15524 .14651 307.46010 BIN1 + + 5 BIN5 NL . .15000 . -201.78739 .13544 293.27940 BIN3 + .01456 1500.00000 58.79586 +Inf 297.07244 BIN3 + + 6 ALUM BS 299.63899 .21000 . 358.26772 .18885 289.87879 AL + . +Inf 112.40876 .22622 301.07527 MN + + 7 SILICON BS 120.57762 .38000 . 124.27093 .14828 268.27586 BIN5 + . +Inf 85.54745 .46667 306.66667 MN + +End of report +\end{verbatim} +\end{footnotesize} +\end{landscape} + +\newpage + +\noindent +{\it Generic information} + +{\tt No.} is the row or column ordinal number in the problem object. +Rows are numbered from 1 to $m$, and columns are numbered from 1 to $n$, +where $m$ and $n$ are, resp., the total number of rows and columns in +the problem object. + +{\tt Row name} is the symbolic name assigned to the row. If the row has +no name assigned, this field contains blanks. + +{\tt Column name} is the symbolic name assigned to the column. If the +column has no name assigned, this field contains blanks. + +{\tt St} is the status of the row or column in the optimal solution: + +{\tt BS} --- non-active constraint (row), basic column; + +{\tt NL} --- inequality constraint having its lower right-hand side +active (row), non-basic column having its lower bound active; + +{\tt NU} --- inequality constraint having its upper right-hand side +active (row), non-basic column having its upper bound active; + +{\tt NS} --- active equality constraint (row), non-basic fixed column. + +{\tt NF} --- active free row, non-basic free (unbounded) column. (This +case means that the optimal solution is dual degenerate.) + +{\tt Activity} is the (primal) value of the auxiliary variable (row) or +structural variable (column) in the optimal solution. + +{\tt Slack} is the (primal) value of the row slack variable. + +{\tt Obj coef} is the objective coefficient of the column (structural +variable). + +{\tt Marginal} is the reduced cost (dual activity) of the auxiliary +variable (row) or structural variable (column). + +{\tt Lower bound} is the lower right-hand side (row) or lower bound +(column). If the row or column has no lower bound, this field contains +{\tt -Inf}. + +{\tt Upper bound} is the upper right-hand side (row) or upper bound +(column). If the row or column has no upper bound, this field contains +{\tt +Inf}. + +\noindent +{\it Sensitivity analysis of active bounds} + +The sensitivity analysis of active bounds is performed only for rows, +which are active constraints, and only for non-basic columns, because +inactive constraints and basic columns have no active bounds. + +For every auxiliary (row) or structural (column) non-basic variable the +routine starts changing its active bound in both direction. The first +of the two lines in the report corresponds to decreasing, and the +second line corresponds to increasing of the active bound. Since the +variable being analyzed is non-basic, its activity, which is equal to +its active bound, also starts changing. This changing leads to changing +of basic (auxiliary and structural) variables, which depend on the +non-basic variable. The current basis remains primal feasible and +therefore optimal while values of all basic variables are primal +feasible, i.e. are within their bounds. Therefore, if some basic +variable called the {\it limiting variable} reaches its (lower or +upper) bound first, before any other basic variables, it thereby limits +further changing of the non-basic variable, because otherwise the +current basis would become primal infeasible. The point, at which this +happens, is called the {\it break point}. Note that there are two break +points: the lower break point, which corresponds to decreasing of the +non-basic variable, and the upper break point, which corresponds to +increasing of the non-basic variable. + +In the analysis report values of the non-basic variable (i.e. of its +active bound) being analyzed at both lower and upper break points are +printed in the field `{\tt Activity range}'. Corresponding values of +the objective function are printed in the field `{\tt Obj value at +break point}', and symbolic names of corresponding limiting basic +variables are printed in the field `{\tt Limiting variable}'. +If the active bound can decrease or/and increase unlimitedly, the field +`{\tt Activity range}' contains {\tt -Inf} or/and {\tt +Inf}, resp. + +For example (see the example report above), row SI is a double-sided +constraint, which is active on its lower bound (right-hand side), and +its activity in the optimal solution being equal to the lower bound is +250. The activity range for this row is $[235.32871,255.06073]$. This +means that the basis remains optimal while the lower bound is +increasing up to 255.06073, and further increasing is limited by +(structural) variable BIN3. If the lower bound reaches this upper break +point, the objective value becomes equal to 298.67206. + +Note that if the basis does not change, the objective function depends +on the non-basic variable linearly, and the per-unit change of the +objective function is the reduced cost (marginal value) of the +non-basic variable. + +\noindent +{\it Sensitivity analysis of objective coefficients at non-basic +variables} + +The sensitivity analysis of the objective coefficient at a non-basic +variable is quite simple, because in this case change in the objective +coefficient leads to equivalent change in the reduced cost (marginal +value). + +For every auxiliary (row) or structural (column) non-basic variable the +routine starts changing its objective coefficient in both direction. +(Note that auxiliary variables are not included in the objective +function and therefore always have zero objective coefficients.) The +first of the two lines in the report corresponds to decreasing, and the +second line corresponds to increasing of the objective coefficient. +This changing leads to changing of the reduced cost of the non-basic +variable to be analyzed and does affect reduced costs of all other +non-basic variables. The current basis remains dual feasible and +therefore optimal while the reduced cost keeps its sign. Therefore, if +the reduced cost reaches zero, it limits further changing of the +objective coefficient (if only the non-basic variable is non-fixed). + +In the analysis report minimal and maximal values of the objective +coefficient, on which the basis remains optimal, are printed in the +field `\verb|Obj coef range|'. If the objective coefficient can +decrease or/and increase unlimitedly, this field contains {\tt -Inf} +or/and {\tt +Inf}, resp. + +For example (see the example report above), column BIN5 is non-basic +having its lower bound active. Its objective coefficient is 0.15, and +reduced cost in the optimal solution 0.01456. The column lower bound +remains active while the column reduced cost remains non-negative, +thus, minimal value of the objective coefficient, on which the current +basis still remains optimal, is $0.15-0.01456=0.13644$, that is +indicated in the field `\verb|Obj coef range|'. + +\newpage + +{\parskip=0pt +\noindent +{\it Sensitivity analysis of objective coefficients at basic variables} + +\medskip + +To perform sensitivity analysis for every auxiliary (row) or structural +(column) variable the routine starts changing its objective coefficient +in both direction. (Note that auxiliary variables are not included in +the objective function and therefore always have zero objective +coefficients.) The first of the two lines in the report corresponds to +decreasing, and the second line corresponds to increasing of the +objective coefficient. This changing leads to changing of reduced costs +of non-basic variables. The current basis remains dual feasible and +therefore optimal while reduced costs of all non-basic variables +(except fixed variables) keep their signs. Therefore, if the reduced +cost of some non-basic non-fixed variable called the {\it limiting +variable} reaches zero first, before reduced cost of any other +non-basic non-fixed variable, it thereby limits further changing of the +objective coefficient, because otherwise the current basis would become +dual infeasible (non-optimal). The point, at which this happens, is +called the {\it break point}. Note that there are two break points: the +lower break point, which corresponds to decreasing of the objective +coefficient, and the upper break point, which corresponds to increasing +of the objective coefficient. Let the objective coefficient reach its +limit value and continue changing a bit further in the same direction +that makes the current basis dual infeasible (non-optimal). Then the +reduced cost of the non-basic limiting variable becomes ``a bit'' dual +infeasible that forces the limiting variable to enter the basis +replacing there some basic variable, which leaves the basis to keep its +primal feasibility. It should be understood that if we change the +current basis in this way exactly at the break point, both the current +and adjacent bases will be optimal with the same objective value, +because at the break point the limiting variable has zero reduced cost. +On the other hand, in the adjacent basis the value of the limiting +variable changes, because there it becomes basic, that leads to +changing of the value of the basic variable being analyzed. Note that +on determining the adjacent basis the bounds of the analyzed basic +variable are ignored as if it were a free (unbounded) variable, so it +cannot leave the current basis. + +In the analysis report lower and upper limits of the objective +coefficient at the basic variable being analyzed, when the basis +remains optimal, are printed in the field `{\tt Obj coef range}'. +Corresponding values of the objective function at both lower and upper +break points are printed in the field `{\tt Obj value at break point}', +symbolic names of corresponding non-basic limiting variables are +printed in the field `{\tt Limiting variable}', and values of the basic +variable, which it would take on in the adjacent bases (as was +explained above) are printed in the field `{\tt Activity range}'. +If the objective coefficient can increase or/and decrease unlimitedly, +the field `{\tt Obj coef range}' contains {\tt -Inf} and/or {\tt +Inf}, +resp. It also may happen that no dual feasible adjacent basis exists +(i.e. on entering the basis the limiting variable can increase or +decrease unlimitedly), in which case the field `{\tt Activity range}' +contains {\tt -Inf} and/or {\tt +Inf}. + +For example (see the example report above), structural variable +(column) BIN3 is basic, its optimal value is 490.25271, and its +objective coefficient is 0.17. The objective coefficient range for this +column is $[0.15982,0.17948]$. This means that the basis remains +optimal while the objective coefficient is decreasing down to 0.15982, +and further decreasing is limited by (auxiliary) variable MN. If we +make the objective coefficient a bit less than 0.15982, the limiting +variable MN will enter the basis, and in that adjacent basis the +structural variable BIN3 will take on new optimal value 788.61314. At +the lower break point, where the objective coefficient is exactly +0.15982, the objective function takes on the value 291.22807 in both +the current and adjacent bases. + +Note that if the basis does not change, the objective function depends +on the objective coefficient at the basic variable linearly, and the +per-unit change of the objective function is the value of the basic +variable. +} + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk04.tex b/resources/3rdparty/glpk-4.53/doc/glpk04.tex new file mode 100644 index 000000000..5c5ed3073 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk04.tex @@ -0,0 +1,1385 @@ +%* glpk04.tex *% + +\chapter{Advanced API Routines} + +\section{Background} +\label{basbgd} + +Using vector and matrix notations the LP problem (1.1)---(1.3) (see +Section \ref{seclp}, page \pageref{seclp}) can be stated as follows: + +\noindent +\hspace{.5in} minimize (or maximize) +$$z=c^Tx_S+c_0\eqno(3.1)$$ +\hspace{.5in} subject to linear constraints +$$x_R=Ax_S\eqno(3.2)$$ +\hspace{.5in} and bounds of variables +$$ +\begin{array}{l@{\ }c@{\ }l@{\ }c@{\ }l} +l_R&\leq&x_R&\leq&u_R\\ +l_S&\leq&x_S&\leq&u_S\\ +\end{array}\eqno(3.3) +$$ +where: + +$x_R=(x_1,\dots,x_m)$ is the vector of auxiliary variables; + +$x_S=(x_{m+1},\dots,x_{m+n})$ is the vector of structural variables; + +$z$ is the objective function; + +$c=(c_1,\dots,c_n)$ is the vector of objective coefficients; + +$c_0$ is the constant term (``shift'') of the objective function; + +$A=(a_{11},\dots,a_{mn})$ is the constraint matrix; + +$l_R=(l_1,\dots,l_m)$ is the vector of lower bounds of auxiliary +variables; + +$u_R=(u_1,\dots,u_m)$ is the vector of upper bounds of auxiliary +variables; + +$l_S=(l_{m+1},\dots,l_{m+n})$ is the vector of lower bounds of +structural variables; + +$u_S=(u_{m+1},\dots,u_{m+n})$ is the vector of upper bounds of +structural variables. + +From the simplex method's standpoint there is no difference between +auxiliary and structural variables. This allows combining all these +variables into one vector that leads to the following problem +statement: + +\noindent +\hspace{.5in} minimize (or maximize) +$$z=(0\ |\ c)^Tx+c_0\eqno(3.4)$$ +\hspace{.5in} subject to linear constraints +$$(I\ |-\!A)x=0\eqno(3.5)$$ +\hspace{.5in} and bounds of variables +$$l\leq x\leq u\eqno(3.6)$$ +where: + +$x=(x_R\ |\ x_S)$ is the $(m+n)$-vector of (all) variables; + +$(0\ |\ c)$ is the $(m+n)$-vector of objective +coefficients;\footnote{Subvector 0 corresponds to objective +coefficients at auxiliary variables.} + +$(I\ |-\!A)$ is the {\it augmented} constraint +$m\times(m+n)$-matrix;\footnote{Note that due to auxiliary variables +matrix $(I\ |-\!A)$ contains the unity submatrix and therefore has full +rank. This means, in particular, that the system (3.5) has no linearly +dependent constraints.} + +$l=(l_R\ |\ l_S)$ is the $(m+n)$-vector of lower bounds of (all) +variables; + +$u=(u_R\ |\ u_S)$ is the $(m+n)$-vector of upper bounds of (all) +variables. + +By definition an {\it LP basic solution} geometrically is a point in +the space of all variables, which is the intersection of hyperplanes +corresponding to active constraints\footnote{A constraint is called +{\it active} if at a given point it is satisfied as equality, otherwise +it is called {\it inactive}.}. The space of all variables has the +dimension $m+n$, therefore, to define some basic solution we have to +define $m+n$ active constraints. Note that $m$ constraints (3.5) being +linearly independent equalities are always active, so remaining $n$ +active constraints can be chosen only from bound constraints (3.6). + +A variable is called {\it non-basic}, if its (lower or upper) bound is +active, otherwise it is called {\it basic}. Since, as was said above, +exactly $n$ bound constraints must be active, in any basic solution +there are always $n$ non-basic variables and $m$ basic variables. +(Note that a free variable also can be non-basic. Although such +variable has no bounds, we can think it as the difference between two +non-negative variables, which both are non-basic in this case.) + +Now consider how to determine numeric values of all variables for a +given basic solution. + +Let $\Pi$ be an appropriate permutation matrix of the order $(m+n)$. +Then we can write: +$$\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right)= +\Pi\left(\begin{array}{@{}c@{}}x_R\\x_S\\\end{array}\right)=\Pi x, +\eqno(3.7)$$ +where $x_B$ is the vector of basic variables, $x_N$ is the vector of +non-basic variables, $x=(x_R\ |\ x_S)$ is the vector of all variables +in the original order. In this case the system of linear constraints +(3.5) can be rewritten as follows: +$$(I\ |-\!A)\Pi^T\Pi x=0\ \ \ \Rightarrow\ \ \ (B\ |\ N) +\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right)=0,\eqno(3.8)$$ +where +$$(B\ |\ N)=(I\ |-\!A)\Pi^T.\eqno(3.9)$$ + +\newpage + +Matrix $B$ is a square non-singular $m\times m$-matrix, which is +composed from columns of the augmented constraint matrix corresponding +to basic variables. It is called the {\it basis matrix} or simply the +{\it basis}. Matrix $N$ is a rectangular $m\times n$-matrix, which is +composed from columns of the augmented constraint matrix corresponding +to non-basic variables. + +From (3.8) it follows that: +$$Bx_B+Nx_N=0,\eqno(3.10)$$ +therefore, +$$x_B=-B^{-1}Nx_N.\eqno(3.11)$$ +Thus, the formula (3.11) shows how to determine numeric values of basic +variables $x_B$ assuming that non-basic variables $x_N$ are fixed on +their active bounds. + +The $m\times n$-matrix +$$\Xi=-B^{-1}N,\eqno(3.12)$$ +which appears in (3.11), is called the {\it simplex +tableau}.\footnote{This definition corresponds to the GLPK +implementation.} It shows how basic variables depend on non-basic +variables: +$$x_B=\Xi x_N.\eqno(3.13)$$ + +The system (3.13) is equivalent to the system (3.5) in the sense that +they both define the same set of points in the space of (primal) +variables, which satisfy to these systems. If, moreover, values of all +basic variables satisfy to their bound constraints (3.3), the +corresponding basic solution is called {\it (primal) feasible}, +otherwise {\it (primal) infeasible}. It is understood that any (primal) +feasible basic solution satisfy to all constraints (3.2) and (3.3). + +The LP theory says that if LP has optimal solution, it has (at least +one) basic feasible solution, which corresponds to the optimum. And the +most natural way to determine whether a given basic solution is optimal +or not is to use the Karush---Kuhn---Tucker optimality conditions. + +\def\arraystretch{1.5} + +For the problem statement (3.4)---(3.6) the optimality conditions are +the following:\footnote{These conditions can be appiled to any solution, +not only to a basic solution.} +$$(I\ |-\!A)x=0\eqno(3.14)$$ +$$(I\ |-\!A)^T\pi+\lambda_l+\lambda_u=\nabla z=(0\ |\ c)^T\eqno(3.15)$$ +$$l\leq x\leq u\eqno(3.16)$$ +$$\lambda_l\geq 0,\ \ \lambda_u\leq 0\ \ \mbox{(minimization)} +\eqno(3.17)$$ +$$\lambda_l\leq 0,\ \ \lambda_u\geq 0\ \ \mbox{(maximization)} +\eqno(3.18)$$ +$$(\lambda_l)_k(x_k-l_k)=0,\ \ (\lambda_u)_k(x_k-u_k)=0,\ \ k=1,2,\dots, +m+n\eqno(3.19)$$ +where: +$\pi=(\pi_1,\pi_2,\dots,\pi_m)$ is a $m$-vector of Lagrange +multipliers for equality constraints (3.5); +$\lambda_l=[(\lambda_l)_1,(\lambda_l)_2,\dots,(\lambda_l)_n]$ is a +$n$-vector of Lagrange multipliers for lower bound constraints (3.6); +$\lambda_u=[(\lambda_u)_1,(\lambda_u)_2,\dots,(\lambda_u)_n]$ is a +$n$-vector of Lagrange multipliers for upper bound constraints (3.6). + +\newpage + +Condition (3.14) is the {\it primal} (original) system of equality +constraints (3.5). + +Condition (3.15) is the {\it dual} system of equality constraints. +It requires the gradient of the objective function to be a linear +combination of normals to the planes defined by constraints of the +original problem. + +Condition (3.16) is the primal (original) system of bound constraints +(3.6). + +Condition (3.17) (or (3.18) in case of maximization) is the dual system +of bound constraints. + +Condition (3.19) is the {\it complementary slackness condition}. It +requires, for each original (auxiliary or structural) variable $x_k$, +that either its (lower or upper) bound must be active, or zero bound of +the corresponding Lagrange multiplier ($(\lambda_l)_k$ or +$(\lambda_u)_k$) must be active. + +In GLPK two multipliers $(\lambda_l)_k$ and $(\lambda_u)_k$ for each +primal (original) variable $x_k$, $k=1,2,\dots,\linebreak m+n$, are +combined into one multiplier: +$$\lambda_k=(\lambda_l)_k+(\lambda_u)_k,\eqno(3.20)$$ +which is called a {\it dual variable} for $x_k$. This {\it cannot} lead +to the ambiguity, because both lower and upper bounds of $x_k$ cannot be +active at the same time,\footnote{If $x_k$ is a fixed variable, we can +think it as double-bounded variable $l_k\leq x_k\leq u_k$, where +$l_k=u_k.$} so at least one of $(\lambda_l)_k$ and $(\lambda_u)_k$ must +be equal to zero, and because these multipliers have different signs, +the combined multiplier, which is their sum, uniquely defines each of +them. + +\def\arraystretch{1} + +Using dual variables $\lambda_k$ the dual system of bound constraints +(3.17) and (3.18) can be written in the form of so called {\it ``rule of +signs''} as follows: + +\medskip + +\begin{center} +\begin{tabular}{|@{\,}c@{$\,$}|@{$\,$}c@{$\,$}|@{$\,$}c@{$\,$}| +@{$\,$}c|c@{$\,$}|@{$\,$}c@{$\,$}|@{$\,$}c@{$\,$}|} +\hline +Original bound&\multicolumn{3}{c|}{Minimization}&\multicolumn{3}{c|} +{Maximization}\\ +\cline{2-7} +constraint&$(\lambda_l)_k$&$(\lambda_u)_k$&$(\lambda_l)_k+ +(\lambda_u)_k$&$(\lambda_l)_k$&$(\lambda_u)_k$&$(\lambda_l)_k+ +(\lambda_u)_k$\\ +\hline +$-\infty<x_k<+\infty$&$=0$&$=0$&$\lambda_k=0$&$=0$&$=0$&$\lambda_k=0$\\ +$x_k\geq l_k$&$\geq 0$&$=0$&$\lambda_k\geq 0$&$\leq 0$&$=0$&$\lambda_k +\leq0$\\ +$x_k\leq u_k$&$=0$&$\leq 0$&$\lambda_k\leq 0$&$=0$&$\geq 0$&$\lambda_k +\geq0$\\ +$l_k\leq x_k\leq u_k$&$\geq 0$& $\leq 0$& $-\infty\!<\!\lambda_k\!< +\!+\infty$ +&$\leq 0$& $\geq 0$& $-\infty\!<\!\lambda_k\!<\!+\infty$\\ +$x_k=l_k=u_k$&$\geq 0$& $\leq 0$& $-\infty\!<\!\lambda_k\!<\!+\infty$& +$\leq 0$& +$\geq 0$& $-\infty\!<\!\lambda_k\!<\!+\infty$\\ +\hline +\end{tabular} +\end{center} + +\medskip + +May note that each primal variable $x_k$ has its dual counterpart +$\lambda_k$ and vice versa. This allows applying the same partition for +the vector of dual variables as (3.7): +$$\left(\begin{array}{@{}c@{}}\lambda_B\\\lambda_N\\\end{array}\right)= +\Pi\lambda,\eqno(3.21)$$ +where $\lambda_B$ is a vector of dual variables for basic variables +$x_B$, $\lambda_N$ is a vector of dual variables for non-basic variables +$x_N$. + +By definition, bounds of basic variables are inactive constraints, so in +any basic solution $\lambda_B=0$. Corresponding values of dual variables +$\lambda_N$ for non-basic variables $x_N$ can be determined in the +following way. From the dual system (3.15) we have: +$$(I\ |-\!A)^T\pi+\lambda=(0\ |\ c)^T,\eqno(3.22)$$ + +\newpage + +\noindent +so multiplying both sides of (3.22) by matrix $\Pi$ gives: +$$\Pi(I\ |-\!A)^T\pi+\Pi\lambda=\Pi(0\ |\ c)^T.\eqno(3.23)$$ +From (3.9) it follows that +$$\Pi(I\ |-\!A)^T=[(I\ |-\!A)\Pi^T]^T=(B\ |\ N)^T.\eqno(3.24)$$ +Further, we can apply the partition (3.7) also to the vector of +objective coefficients (see (3.4)): +$$\left(\begin{array}{@{}c@{}}c_B\\c_N\\\end{array}\right)= +\Pi\left(\begin{array}{@{}c@{}}0\\c\\\end{array}\right),\eqno(3.25)$$ +where $c_B$ is a vector of objective coefficients at basic variables, +$c_N$ is a vector of objective coefficients at non-basic variables. +Now, substituting (3.24), (3.21), and (3.25) into (3.23), leads to: +$$(B\ |\ N)^T\pi+(\lambda_B\ |\ \lambda_N)^T=(c_B\ |\ c_N)^T, +\eqno(3.26)$$ +and transposing both sides of (3.26) gives the system: +$$\left(\begin{array}{@{}c@{}}B^T\\N^T\\\end{array}\right)\pi+ +\left(\begin{array}{@{}c@{}}\lambda_B\\\lambda_N\\\end{array}\right)= +\left(\begin{array}{@{}c@{}}c_B\\c_T\\\end{array}\right),\eqno(3.27)$$ +which can be written as follows: +$$\left\{ +\begin{array}{@{\ }r@{\ }c@{\ }r@{\ }c@{\ }l@{\ }} +B^T\pi&+&\lambda_B&=&c_B\\ +N^T\pi&+&\lambda_N&=&c_N\\ +\end{array} +\right.\eqno(3.28) +$$ +Lagrange multipliers $\pi=(\pi_i)$ correspond to equality constraints +(3.5) and therefore can have any sign. This allows resolving the first +subsystem of (3.28) as follows:\footnote{$B^{-T}$ means $(B^T)^{-1}= +(B^{-1})^T$.} +$$\pi=B^{-T}(c_B-\lambda_B)=-B^{-T}\lambda_B+B^{-T}c_B,\eqno(3.29)$$ +and substitution of $\pi$ from (3.29) into the second subsystem of +(3.28) gives: +$$\lambda_N=-N^T\pi+c_N=N^TB^{-T}\lambda_B+(c_N-N^TB^{-T}c_B). +\eqno(3.30)$$ +The latter system can be written in the following final form: +$$\lambda_N=-\Xi^T\lambda_B+d,\eqno(3.31)$$ +where $\Xi$ is the simplex tableau (see (3.12)), and +$$d=c_N-N^TB^{-T}c_B=c_N+\Xi^Tc_B\eqno(3.32)$$ +is the vector of so called {\it reduced costs} of non-basic variables. + +Above it was said that in any basic solution $\lambda_B=0$, so +$\lambda_N=d$ as it follows from (3.31). + +The system (3.31) is equivalent to the system (3.15) in the sense that +they both define the same set of points in the space of dual variables +$\lambda$, which satisfy to these systems. If, moreover, values of all +dual variables $\lambda_N$ (i.e. reduced costs $d$) satisfy to their +bound constraints (i.e. to the ``rule of signs''; see the table above), +the corresponding basic solution is called {\it dual feasible}, +otherwise {\it dual infeasible}. It is understood that any dual feasible +solution satisfy to all constraints (3.15) and (3.17) (or (3.18) in case +of maximization). + +It can be easily shown that the complementary slackness condition +(3.19) is always satisfied for {\it any} basic solution.\footnote{Until +double-bounded variables appear.} Therefore, a basic +solution\footnote{It is assumed that a complete basic solution has the +form $(x,\lambda)$, i.e. it includes primal as well as dual variables.} +is {\it optimal} if and only if it is primal and dual feasible, because +in this case it satifies to all the optimality conditions +(3.14)---(3.19). + +\def\arraystretch{1.5} + +The meaning of reduced costs $d=(d_j)$ of non-basic variables can be +explained in the following way. From (3.4), (3.7), and (3.25) it follows +that: +$$z=c_B^Tx_B+c_N^Tx_N+c_0.\eqno(3.33)$$ +Substituting $x_B$ from (3.11) into (3.33) we can eliminate basic +variables and express the objective only through non-basic variables: +$$ +\begin{array}{r@{\ }c@{\ }l} +z&=&c_B^T(-B^{-1}Nx_N)+c_N^Tx_N+c_0=\\ +&=&(c_N^T-c_B^TB^{-1}N)x_N+c_0=\\ +&=&(c_N-N^TB^{-T}c_B)^Tx_N+c_0=\\ +&=&d^Tx_N+c_0. +\end{array}\eqno(3.34) +$$ +From (3.34) it is seen that reduced cost $d_j$ shows how the objective +function $z$ depends on non-basic variable $(x_N)_j$ in the neighborhood +of the current basic solution, i.e. while the current basis remains +unchanged. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{LP basis routines} +\label{lpbasis} + +\subsection{glp\_bf\_exists --- check if the basis factorization +exists} + +\synopsis + +\begin{verbatim} + int glp_bf_exists(glp_prob *P); +\end{verbatim} + +\returns + +If the basis factorization for the current basis associated with the +specified problem object exists and therefore is available for +computations, the routine \verb|glp_bf_exists| returns non-zero. +Otherwise the routine returns zero. + +\para{Comments} + +Let the problem object have $m$ rows and $n$ columns. In GLPK the +{\it basis matrix} $B$ is a square non-singular matrix of the order $m$, +whose columns correspond to basic (auxiliary and/or structural) +variables. It is defined by the following main +equality:\footnote{For more details see Subsection \ref{basbgd}, +page \pageref{basbgd}.} +$$(B\ |\ N)=(I\ |-\!A)\Pi^T,$$ +where $I$ is the unity matrix of the order $m$, whose columns correspond +to auxiliary variables; $A$ is the original constraint +$m\times n$-matrix, whose columns correspond to structural variables; +$(I\ |-\!A)$ is the augmented constraint $m\times(m+n)$-matrix, whose +columns correspond to all (auxiliary and structural) variables +following in the original order; $\Pi$ is a permutation matrix of the +order $m+n$; and $N$ is a rectangular $m\times n$-matrix, whose columns +correspond to non-basic (auxiliary and/or structural) variables. + +For various reasons it may be necessary to solve linear systems with +matrix $B$. To provide this possibility the GLPK implementation +maintains an invertable form of $B$ (that is, some representation of +$B^{-1}$) called the {\it basis factorization}, which is an internal +component of the problem object. Typically, the basis factorization is +computed by the simplex solver, which keeps it in the problem object +to be available for other computations. + +Should note that any changes in the problem object, which affects the +basis matrix (e.g. changing the status of a row or column, changing +a basic column of the constraint matrix, removing an active constraint, +etc.), invalidates the basis factorization. So before calling any API +routine, which uses the basis factorization, the application program +must make sure (using the routine \verb|glp_bf_exists|) that the +factorization exists and therefore available for computations. + +\newpage + +\subsection{glp\_factorize --- compute the basis factorization} + +\synopsis + +\begin{verbatim} + int glp_factorize(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_factorize| computes the basis factorization for +the current basis associated with the specified problem +object.\footnote{The current basis is defined by the current statuses +of rows (auxiliary variables) and columns (structural variables).} + +The basis factorization is computed from ``scratch'' even if it exists, +so the application program may use the routine \verb|glp_bf_exists|, +and, if the basis factorization already exists, not to call the routine +\verb|glp_factorize| to prevent an extra work. + +The routine \verb|glp_factorize| {\it does not} compute components of +the basic solution (i.e. primal and dual values). + +\returns + +\begin{retlist} +0 & The basis factorization has been successfully computed.\\ +\verb|GLP_EBADB| & The basis matrix is invalid, because the number of +basic (auxiliary and structural) variables is not the same as the number +of rows in the problem object.\\ + +\verb|GLP_ESING| & The basis matrix is singular within the working +precision.\\ + +\verb|GLP_ECOND| & The basis matrix is ill-conditioned, i.e. its +condition number is too large.\\ +\end{retlist} + +\subsection{glp\_bf\_updated --- check if the basis factorization has +been updated} + +\synopsis + +\begin{verbatim} + int glp_bf_updated(glp_prob *P); +\end{verbatim} + +\returns + +If the basis factorization has been just computed from ``scratch'', the +routine \verb|glp_bf_updated| returns zero. Otherwise, if the +factorization has been updated at least once, the routine returns +non-zero. + +\para{Comments} + +{\it Updating} the basis factorization means recomputing it to reflect +changes in the basis matrix. For example, on every iteration of the +simplex method some column of the current basis matrix is replaced by +a new column that gives a new basis matrix corresponding to the +adjacent basis. In this case computing the basis factorization for the +adjacent basis from ``scratch'' (as the routine \verb|glp_factorize| +does) would be too time-consuming. + +On the other hand, since the basis factorization update is a numeric +computational procedure, applying it many times may lead to +accumulating round-off errors. Therefore the basis is periodically +refactorized (reinverted) from ``scratch'' (with the routine +\verb|glp_factorize|) that allows improving its numerical properties. + +The routine \verb|glp_bf_updated| allows determining if the basis +factorization has been updated at least once since it was computed from +``scratch''. + +\subsection{glp\_get\_bfcp --- retrieve basis factorization control +parameters} + +\synopsis + +\begin{verbatim} + void glp_get_bfcp(glp_prob *P, glp_bfcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_get_bfcp| retrieves control parameters, which are +used on computing and updating the basis factorization associated with +the specified problem object. + +Current values of the control parameters are stored in +a \verb|glp_bfcp| structure, which the parameter \verb|parm| points to. +For a detailed description of the structure \verb|glp_bfcp| see +comments to the routine \verb|glp_set_bfcp| in the next subsection. + +\para{Comments} + +The purpose of the routine \verb|glp_get_bfcp| is two-fold. First, it +allows the application program obtaining current values of control +parameters used by internal GLPK routines, which compute and update the +basis factorization. + +The second purpose of this routine is to provide proper values for all +fields of the structure \verb|glp_bfcp| in the case when the +application program needs to change some control parameters. + +\subsection{glp\_set\_bfcp --- change basis factorization control +parameters} + +\synopsis + +\begin{verbatim} + void glp_set_bfcp(glp_prob *P, const glp_bfcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_set_bfcp| changes control parameters, which are +used by internal GLPK routines on computing and updating the basis +factorization associated with the specified problem object. + +New values of the control parameters should be passed in a structure +\verb|glp_bfcp|, which the parameter \verb|parm| points to. For a +detailed description of the structure \verb|glp_bfcp| see paragraph +``Control parameters'' below. + +The parameter \verb|parm| can be specified as \verb|NULL|, in which +case all control parameters are reset to their default values. + +\para{Comments} + +Before changing some control parameters with the routine +\verb|glp_set_bfcp| the application program should retrieve current +values of all control parameters with the routine \verb|glp_get_bfcp|. +This is needed for backward compatibility, because in the future there +may appear new members in the structure \verb|glp_bfcp|. + +Note that new values of control parameters come into effect on a next +computation of the basis factorization, not immediately. + +\para{Example} + +\begin{footnotesize} +\begin{verbatim} +glp_prob *lp; +glp_bfcp parm; +. . . +/* retrieve current values of control parameters */ +glp_get_bfcp(lp, &parm); +/* change the threshold pivoting tolerance */ +parm.piv_tol = 0.05; +/* set new values of control parameters */ +glp_set_bfcp(lp, &parm); +. . . +\end{verbatim} +\end{footnotesize} + +\para{Control parameters} + +This paragraph describes all basis factorization control parameters +currently used in the package. Symbolic names of control parameters are +names of corresponding members in the structure \verb|glp_bfcp|. + +\medskip + +{\tt int type} (default: {\tt GLP\_BF\_FT}) + +Basis factorization type: + +\verb|GLP_BF_FT|---$LU$ + Forrest--Tomlin update; + +\verb|GLP_BF_BG|---$LU$ + Schur complement + Bartels--Golub update; + +\verb|GLP_BF_GR|---$LU$ + Schur complement + Givens rotation update. + +In case of \verb|GLP_BF_FT| the update is applied to matrix $U$, while +in cases of \verb|GLP_BF_BG| and \verb|GLP_BF_GR| the update is applied +to the Schur complement. + +\medskip + +{\tt int lu\_size} (default: {\tt 0}) + +The initial size of the Sparse Vector Area, in non-zeros, used on +computing $LU$-factorization of the basis matrix for the first time. +If this parameter is set to 0, the initial SVA size is determined +automatically. + +\medskip + +{\tt double piv\_tol} (default: {\tt 0.10}) + +Threshold pivoting (Markowitz) tolerance, 0 $<$ \verb|piv_tol| $<$ 1, +used on computing $LU$-factoriza\-tion of the basis matrix. Element +$u_{ij}$ of the active submatrix of factor $U$ fits to be pivot if it +satisfies to the stability criterion +$|u_{ij}| >= {\tt piv\_tol}\cdot\max|u_{i*}|$, i.e. if it is not very +small in the magnitude among other elements in the same row. Decreasing +this parameter may lead to better sparsity at the expense of numerical +accuracy, and vice versa. + +\medskip + +{\tt int piv\_lim} (default: {\tt 4}) + +This parameter is used on computing $LU$-factorization of the basis +matrix and specifies how many pivot candidates needs to be considered +on choosing a pivot element, \verb|piv_lim| $\geq$ 1. If \verb|piv_lim| +candidates have been considered, the pivoting routine prematurely +terminates the search with the best candidate found. + +\newpage + +{\tt int suhl} (default: {\tt GLP\_ON}) + +This parameter is used on computing $LU$-factorization of the basis +matrix. Being set to {\tt GLP\_ON} it enables applying the following +heuristic proposed by Uwe Suhl: if a column of the active submatrix has +no eligible pivot candidates, it is no more considered until it becomes +a column singleton. In many cases this allows reducing the time needed +for pivot searching. To disable this heuristic the parameter +\verb|suhl| should be set to {\tt GLP\_OFF}. + +\medskip + +{\tt double eps\_tol} (default: {\tt 1e-15}) + +Epsilon tolerance, \verb|eps_tol| $\geq$ 0, used on computing +$LU$-factorization of the basis matrix. If an element of the active +submatrix of factor $U$ is less than \verb|eps_tol| in the magnitude, +it is replaced by exact zero. + +\medskip + +{\tt double max\_gro} (default: {\tt 1e+10}) + +Maximal growth of elements of factor $U$, \verb|max_gro| $\geq$ 1, +allowable on computing $LU$-factorization of the basis matrix. If on +some elimination step the ratio $u_{big}/b_{max}$ (where $u_{big}$ is +the largest magnitude of elements of factor $U$ appeared in its active +submatrix during all the factorization process, $b_{max}$ is the +largest magnitude of elements of the basis matrix to be factorized), +the basis matrix is considered as ill-conditioned. + +\medskip + +{\tt int nfs\_max} (default: {\tt 100}) + +Maximal number of additional row-like factors (entries of the eta +file), \verb|nfs_max| $\geq$ 1, which can be added to +$LU$-factorization of the basis matrix on updating it with the +Forrest--Tomlin technique. This parameter is used only once, before +$LU$-factorization is computed for the first time, to allocate working +arrays. As a rule, each update adds one new factor (however, some +updates may need no addition), so this parameter limits the number of +updates between refactorizations. + +\medskip + +{\tt double upd\_tol} (default: {\tt 1e-6}) + +Update tolerance, 0 $<$ \verb|upd_tol| $<$ 1, used on updating +$LU$-factorization of the basis matrix with the Forrest--Tomlin +technique. If after updating the magnitude of some diagonal element +$u_{kk}$ of factor $U$ becomes less than +${\tt upd\_tol}\cdot\max(|u_{k*}|, |u_{*k}|)$, the factorization is +considered as inaccurate. + +\medskip + +{\tt int nrs\_max} (default: {\tt 100}) + +Maximal number of additional rows and columns, \verb|nrs_max| $\geq$ 1, +which can be added to $LU$-factorization of the basis matrix on +updating it with the Schur complement technique. This parameter is used +only once, before $LU$-factorization is computed for the first time, to +allocate working arrays. As a rule, each update adds one new row and +column (however, some updates may need no addition), so this parameter +limits the number of updates between refactorizations. + +\medskip + +{\tt int rs\_size} (default: {\tt 0}) + +The initial size of the Sparse Vector Area, in non-zeros, used to +store non-zero elements of additional rows and columns introduced on +updating $LU$-factorization of the basis matrix with the Schur +complement technique. If this parameter is set to 0, the initial SVA +size is determined automatically. + +\newpage + +\subsection{glp\_get\_bhead --- retrieve the basis header information} + +\synopsis + +\begin{verbatim} + int glp_get_bhead(glp_prob *P, int k); +\end{verbatim} + +\description + +The routine \verb|glp_get_bhead| returns the basis header information +for the current basis associated with the specified problem object. + +\returns + +If basic variable $(x_B)_k$, $1\leq k\leq m$, is $i$-th auxiliary +variable ($1\leq i\leq m$), the routine returns $i$. Otherwise, if +$(x_B)_k$ is $j$-th structural variable ($1\leq j\leq n$), the routine +returns $m+j$. Here $m$ is the number of rows and $n$ is the number of +columns in the problem object. + +\para{Comments} + +Sometimes the application program may need to know which original +(auxiliary and structural) variable correspond to a given basic +variable, or, that is the same, which column of the augmented +constraint matrix $(I\ |-\!A)$ correspond to a given column of the +basis matrix $B$. + +\def\arraystretch{1} + +The correspondence is defined as follows:\footnote{For more details see +Subsection \ref{basbgd}, page \pageref{basbgd}.} +$$\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right)= +\Pi\left(\begin{array}{@{}c@{}}x_R\\x_S\\\end{array}\right) +\ \ \Leftrightarrow +\ \ \left(\begin{array}{@{}c@{}}x_R\\x_S\\\end{array}\right)= +\Pi^T\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right),$$ +where $x_B$ is the vector of basic variables, $x_N$ is the vector of +non-basic variables, $x_R$ is the vector of auxiliary variables +following in their original order,\footnote{The original order of +auxiliary and structural variables is defined by the ordinal numbers +of corresponding rows and columns in the problem object.} $x_S$ is the +vector of structural variables following in their original order, $\Pi$ +is a permutation matrix (which is a component of the basis +factorization). + +Thus, if $(x_B)_k=(x_R)_i$ is $i$-th auxiliary variable, the routine +returns $i$, and if $(x_B)_k=(x_S)_j$ is $j$-th structural variable, +the routine returns $m+j$, where $m$ is the number of rows in the +problem object. + +\subsection{glp\_get\_row\_bind --- retrieve row index in the basis +header} + +\synopsis + +\begin{verbatim} + int glp_get_row_bind(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_bind| returns the index $k$ of basic +variable $(x_B)_k$, $1\leq k\leq m$, which is $i$-th auxiliary variable +(that is, the auxiliary variable corresponding to $i$-th row), +$1\leq i\leq m$, in the current basis associated with the specified +problem object, where $m$ is the number of rows. However, if $i$-th +auxiliary variable is non-basic, the routine returns zero. + +\newpage + +\para{Comments} + +The routine \verb|glp_get_row_bind| is an inversion of the routine +\verb|glp_get_bhead|; that is, if \linebreak +\verb|glp_get_bhead|$(P,k)$ returns $i$, +\verb|glp_get_row_bind|$(P,i)$ returns $k$, and vice versa. + +\subsection{glp\_get\_col\_bind --- retrieve column index in the basis +header} + +\synopsis + +\begin{verbatim} + int glp_get_col_bind(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_bind| returns the index $k$ of basic +variable $(x_B)_k$, $1\leq k\leq m$, which is $j$-th structural +variable (that is, the structural variable corresponding to $j$-th +column), $1\leq j\leq n$, in the current basis associated with the +specified problem object, where $m$ is the number of rows, $n$ is the +number of columns. However, if $j$-th structural variable is non-basic, +the routine returns zero. + +\para{Comments} + +The routine \verb|glp_get_col_bind| is an inversion of the routine +\verb|glp_get_bhead|; that is, if \linebreak +\verb|glp_get_bhead|$(P,k)$ returns $m+j$, +\verb|glp_get_col_bind|$(P,j)$ returns $k$, and vice versa. + +\subsection{glp\_ftran --- perform forward transformation} + +\synopsis + +\begin{verbatim} + void glp_ftran(glp_prob *P, double x[]); +\end{verbatim} + +\description + +The routine \verb|glp_ftran| performs forward transformation (FTRAN), +i.e. it solves the system $Bx=b$, where $B$ is the basis matrix +associated with the specified problem object, $x$ is the vector of +unknowns to be computed, $b$ is the vector of right-hand sides. + +On entry to the routine elements of the vector $b$ should be stored in +locations \verb|x[1]|, \dots, \verb|x[m]|, where $m$ is the number of +rows. On exit the routine stores elements of the vector $x$ in the same +locations. + +\subsection{glp\_btran --- perform backward transformation} + +\synopsis + +\begin{verbatim} + void glp_btran(glp_prob *P, double x[]); +\end{verbatim} + +\description + +The routine \verb|glp_btran| performs backward transformation (BTRAN), +i.e. it solves the system $B^Tx=b$, where $B^T$ is a matrix transposed +to the basis matrix $B$ associated with the specified problem object, +$x$ is the vector of unknowns to be computed, $b$ is the vector of +right-hand sides. + +\newpage + +On entry to the routine elements of the vector $b$ should be stored in +locations \verb|x[1]|, \dots, \verb|x[m]|, where $m$ is the number of +rows. On exit the routine stores elements of the vector $x$ in the same +locations. + +\subsection{glp\_warm\_up --- ``warm up'' LP basis} + +\synopsis + +\begin{verbatim} + int glp_warm_up(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_warm_up| ``warms up'' the LP basis for the +specified problem object using current statuses assigned to rows and +columns (that is, to auxiliary and structural variables). + +This operation includes computing factorization of the basis matrix +(if it does not exist), computing primal and dual components of basic +solution, and determining the solution status. + +\returns + +\begin{retlist} +0 & The operation has been successfully performed.\\ + +\verb|GLP_EBADB| & The basis matrix is invalid, because the number of +basic (auxiliary and structural) variables is not the same as the +number of rows in the problem object.\\ + +\verb|GLP_ESING| & The basis matrix is singular within the working +precision.\\ + +\verb|GLP_ECOND| & The basis matrix is ill-conditioned, i.e. its +condition number is too large.\\ +\end{retlist} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Simplex tableau routines} + +\subsection{glp\_eval\_tab\_row --- compute row of the tableau} + +\synopsis + +\begin{verbatim} + int glp_eval_tab_row(glp_prob *P, int k, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_eval_tab_row| computes a row of the current +simplex tableau (see Subsection 3.1.1, formula (3.12)), which (row) +corresponds to some basic variable specified by the parameter $k$ as +follows: if $1\leq k\leq m$, the basic variable is $k$-th auxiliary +variable, and if $m+1\leq k\leq m+n$, the basic variable is $(k-m)$-th +structural variable, where $m$ is the number of rows and $n$ is the +number of columns in the specified problem object. The basis +factorization must exist. + +The computed row shows how the specified basic variable depends on +non-basic variables: +$$x_k=(x_B)_i=\xi_{i1}(x_N)_1+\xi_{i2}(x_N)_2+\dots+\xi_{in}(x_N)_n,$$ +where $\xi_{i1}$, $\xi_{i2}$, \dots, $\xi_{in}$ are elements of the +simplex table row, $(x_N)_1$, $(x_N)_2$, \dots, $(x_N)_n$ are non-basic +(auxiliary and structural) variables. + +The routine stores column indices and corresponding numeric values of +non-zero elements of the computed row in unordered sparse format in +locations \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, +\dots, \verb|val[len]|, respectively, where $0\leq{\tt len}\leq n$ is +the number of non-zero elements in the row returned on exit. + +Element indices stored in the array \verb|ind| have the same sense as +index $k$, i.e. indices 1 to $m$ denote auxiliary variables while +indices $m+1$ to $m+n$ denote structural variables (all these variables +are obviously non-basic by definition). + +\returns + +The routine \verb|glp_eval_tab_row| returns \verb|len|, which is the +number of non-zero elements in the simplex table row stored in the +arrays \verb|ind| and \verb|val|. + +\para{Comments} + +A row of the simplex table is computed as follows. At first, the +routine checks that the specified variable $x_k$ is basic and uses the +permutation matrix $\Pi$ (3.7) to determine index $i$ of basic variable +$(x_B)_i$, which corresponds to $x_k$. + +The row to be computed is $i$-th row of the matrix $\Xi$ (3.12), +therefore: +$$\xi_i=e_i^T\Xi=-e_i^TB^{-1}N=-(B^{-T}e_i)^TN,$$ +where $e_i$ is $i$-th unity vector. So the routine performs BTRAN to +obtain $i$-th row of the inverse $B^{-1}$: +$$\varrho_i=B^{-T}e_i,$$ +and then computes elements of the simplex table row as inner products: +$$\xi_{ij}=-\varrho_i^TN_j,\ \ j=1,2,\dots,n,$$ +where $N_j$ is $j$-th column of matrix $N$ (3.9), which (column) +corresponds to non-basic variable $(x_N)_j$. The permutation matrix +$\Pi$ is used again to convert indices $j$ of non-basic columns to +original ordinal numbers of auxiliary and structural variables. + +\subsection{glp\_eval\_tab\_col --- compute column of the tableau} + +\synopsis + +\begin{verbatim} + int glp_eval_tab_col(glp_prob *P, int k, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_eval_tab_col| computes a column of the current +simplex tableau (see Subsection 3.1.1, formula (3.12)), which (column) +corresponds to some non-basic variable specified by the parameter $k$: +if $1\leq k\leq m$, the non-basic variable is $k$-th auxiliary +variable, and if $m+1\leq k\leq m+n$, the non-basic variable is +$(k-m)$-th structural variable, where $m$ is the number of rows and $n$ +is the number of columns in the specified problem object. The basis +factorization must exist. + +The computed column shows how basic variables depends on the specified +non-basic variable $x_k=(x_N)_j$: +$$ +\begin{array}{r@{\ }c@{\ }l@{\ }l} +(x_B)_1&=&\dots+\xi_{1j}(x_N)_j&+\dots\\ +(x_B)_2&=&\dots+\xi_{2j}(x_N)_j&+\dots\\ +.\ \ .&.&.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\\ +(x_B)_m&=&\dots+\xi_{mj}(x_N)_j&+\dots\\ +\end{array} +$$ +where $\xi_{1j}$, $\xi_{2j}$, \dots, $\xi_{mj}$ are elements of the +simplex table column, $(x_B)_1$, $(x_B)_2$, \dots, $(x_B)_m$ are basic +(auxiliary and structural) variables. + +The routine stores row indices and corresponding numeric values of +non-zero elements of the computed column in unordered sparse format in +locations \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, +\dots, \verb|val[len]|, respectively, where $0\leq{\tt len}\leq m$ is +the number of non-zero elements in the column returned on exit. + +Element indices stored in the array \verb|ind| have the same sense as +index $k$, i.e. indices 1 to $m$ denote auxiliary variables while +indices $m+1$ to $m+n$ denote structural variables (all these variables +are obviously basic by definition). + +\returns + +The routine \verb|glp_eval_tab_col| returns \verb|len|, which is the +number of non-zero elements in the simplex table column stored in the +arrays \verb|ind| and \verb|val|. + +\para{Comments} + +A column of the simplex table is computed as follows. At first, the +routine checks that the specified variable $x_k$ is non-basic and uses +the permutation matrix $\Pi$ (3.7) to determine index $j$ of non-basic +variable $(x_N)_j$, which corresponds to $x_k$. + +The column to be computed is $j$-th column of the matrix $\Xi$ (3.12), +therefore: +$$\Xi_j=\Xi e_j=-B^{-1}Ne_j=-B^{-1}N_j,$$ +where $e_j$ is $j$-th unity vector, $N_j$ is $j$-th column of matrix +$N$ (3.9). So the routine performs FTRAN to transform $N_j$ to the +simplex table column $\Xi_j=(\xi_{ij})$ and uses the permutation matrix +$\Pi$ to convert row indices $i$ to original ordinal numbers of +auxiliary and structural variables. + +\subsection{glp\_transform\_row --- transform explicitly specified row} + +\synopsis + +\begin{verbatim} + int glp_transform_row(glp_prob *P, int len, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_transform_row| performs the same operation as the +routine \verb|glp_eval_tab_row| with exception that the row to be +transformed is specified explicitly as a sparse vector. + +The explicitly specified row may be thought as a linear form: +$$x=a_1x_{m+1}+a_2x_{m+2}+\dots+a_nx_{m+n},$$ +where $x$ is an auxiliary variable for this row, $a_j$ are coefficients +of the linear form, $x_{m+j}$ are structural variables. + +On entry column indices and numerical values of non-zero coefficients +$a_j$ of the specified row should be placed in locations \verb|ind[1]|, +\dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, where +\verb|len| is number of non-zero coefficients. + +This routine uses the system of equality constraints and the current +basis in order to express the auxiliary variable $x$ through the current +non-basic variables (as if the transformed row were added to the problem +object and the auxiliary variable $x$ were basic), i.e. the resultant +row has the form: +$$x=\xi_1(x_N)_1+\xi_2(x_N)_2+\dots+\xi_n(x_N)_n,$$ +where $\xi_j$ are influence coefficients, $(x_N)_j$ are non-basic +(auxiliary and structural) variables, $n$ is the number of columns in +the problem object. + +On exit the routine stores indices and numerical values of non-zero +coefficients $\xi_j$ of the resultant row in locations \verb|ind[1]|, +\dots, \verb|ind[len']| and \verb|val[1]|, \dots, \verb|val[len']|, +where $0\leq{\tt len'}\leq n$ is the number of non-zero coefficients in +the resultant row returned by the routine. Note that indices of +non-basic variables stored in the array \verb|ind| correspond to +original ordinal numbers of variables: indices 1 to $m$ mean auxiliary +variables and indices $m+1$ to $m+n$ mean structural ones. + +\returns + +The routine \verb|glp_transform_row| returns \verb|len'|, the number of +non-zero coefficients in the resultant row stored in the arrays +\verb|ind| and \verb|val|. + +\newpage + +\subsection{glp\_transform\_col --- transform explicitly specified +column} + +\synopsis + +\begin{verbatim} + int glp_transform_col(glp_prob *P, int len, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_transform_col| performs the same operation as the +routine \verb|glp_eval_tab_col| with exception that the column to be +transformed is specified explicitly as a sparse vector. + +The explicitly specified column may be thought as it were added to +the original system of equality constraints: +$$ +\begin{array}{l@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r} +x_1&=&a_{11}x_{m+1}&+\dots+&a_{1n}x_{m+n}&+&a_1x \\ +x_2&=&a_{21}x_{m+1}&+\dots+&a_{2n}x_{m+n}&+&a_2x \\ +\multicolumn{7}{c} +{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +x_m&=&a_{m1}x_{m+1}&+\dots+&a_{mn}x_{m+n}&+&a_mx \\ +\end{array} +$$ +where $x_i$ are auxiliary variables, $x_{m+j}$ are structural variables +(presented in the problem object), $x$ is a structural variable for the +explicitly specified column, $a_i$ are constraint coefficients at $x$. + +On entry row indices and numerical values of non-zero coefficients +$a_i$ of the specified column should be placed in locations +\verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, +\verb|val[len]|, where \verb|len| is number of non-zero coefficients. + +This routine uses the system of equality constraints and the current +basis in order to express the current basic variables through the +structural variable $x$ (as if the transformed column were added to the +problem object and the variable $x$ were non-basic): +$$ +\begin{array}{l@{\ }c@{\ }r} +(x_B)_1&=\dots+&\xi_{1}x\\ +(x_B)_2&=\dots+&\xi_{2}x\\ +\multicolumn{3}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +(x_B)_m&=\dots+&\xi_{m}x\\ +\end{array} +$$ +where $\xi_i$ are influence coefficients, $x_B$ are basic (auxiliary +and structural) variables, $m$ is the number of rows in the problem +object. + +On exit the routine stores indices and numerical values of non-zero +coefficients $\xi_i$ of the resultant column in locations \verb|ind[1]|, +\dots, \verb|ind[len']| and \verb|val[1]|, \dots, \verb|val[len']|, +where $0\leq{\tt len'}\leq m$ is the number of non-zero coefficients in +the resultant column returned by the routine. Note that indices of basic +variables stored in the array \verb|ind| correspond to original ordinal +numbers of variables, i.e. indices 1 to $m$ mean auxiliary variables, +indices $m+1$ to $m+n$ mean structural ones. + +\returns + +The routine \verb|glp_transform_col| returns \verb|len'|, the number of +non-zero coefficients in the resultant column stored in the arrays +\verb|ind| and \verb|val|. + +\newpage + +\subsection{glp\_prim\_rtest --- perform primal ratio test} + +\synopsis + +\begin{verbatim} + int glp_prim_rtest(glp_prob *P, int len, const int ind[], const double val[], + int dir, double eps); +\end{verbatim} + +\description + +The routine \verb|glp_prim_rtest| performs the primal ratio test using +an explicitly specified column of the simplex table. + +The current basic solution associated with the LP problem object must +be primal feasible. + +The explicitly specified column of the simplex table shows how the +basic variables $x_B$ depend on some non-basic variable $x$ (which is +not necessarily presented in the problem object): +$$ +\begin{array}{l@{\ }c@{\ }r} +(x_B)_1&=\dots+&\xi_{1}x\\ +(x_B)_2&=\dots+&\xi_{2}x\\ +\multicolumn{3}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +(x_B)_m&=\dots+&\xi_{m}x\\ +\end{array} +$$ + +The column is specifed on entry to the routine in sparse format. +Ordinal numbers of basic variables $(x_B)_i$ should be placed in +locations \verb|ind[1]|, \dots, \verb|ind[len]|, where ordinal number +1 to $m$ denote auxiliary variables, and ordinal numbers $m+1$ to $m+n$ +denote structural variables. The corresponding non-zero coefficients +$\xi_i$ should be placed in locations +\verb|val[1]|, \dots, \verb|val[len]|. The arrays \verb|ind| and +\verb|val| are not changed by the routine. + +The parameter \verb|dir| specifies direction in which the variable $x$ +changes on entering the basis: $+1$ means increasing, $-1$ means +decreasing. + +The parameter \verb|eps| is an absolute tolerance (small positive +number, say, $10^{-9}$) used by the routine to skip $\xi_i$'s whose +magnitude is less than \verb|eps|. + +The routine determines which basic variable (among those specified in +\verb|ind[1]|, \dots, \verb|ind[len]|) reaches its (lower or upper) +bound first before any other basic variables do, and which, therefore, +should leave the basis in order to keep primal feasibility. + +\returns + +The routine \verb|glp_prim_rtest| returns the index, \verb|piv|, in the +arrays \verb|ind| and \verb|val| corresponding to the pivot element +chosen, $1\leq$ \verb|piv| $\leq$ \verb|len|. If the adjacent basic +solution is primal unbounded, and therefore the choice cannot be made, +the routine returns zero. + +\para{Comments} + +If the non-basic variable $x$ is presented in the LP problem object, +the input column can be computed with the routine +\verb|glp_eval_tab_col|; otherwise, it can be computed with the routine +\verb|glp_transform_col|. + +\newpage + +\subsection{glp\_dual\_rtest --- perform dual ratio test} + +\synopsis + +\begin{verbatim} + int glp_dual_rtest(glp_prob *P, int len, const int ind[], const double val[], + int dir, double eps); +\end{verbatim} + +\description + +The routine \verb|glp_dual_rtest| performs the dual ratio test using +an explicitly specified row of the simplex table. + +The current basic solution associated with the LP problem object must +be dual feasible. + +The explicitly specified row of the simplex table is a linear form +that shows how some basic variable $x$ (which is not necessarily +presented in the problem object) depends on non-basic variables $x_N$: +$$x=\xi_1(x_N)_1+\xi_2(x_N)_2+\dots+\xi_n(x_N)_n.$$ + +The row is specified on entry to the routine in sparse format. Ordinal +numbers of non-basic variables $(x_N)_j$ should be placed in locations +\verb|ind[1]|, \dots, \verb|ind[len]|, where ordinal numbers 1 to $m$ +denote auxiliary variables, and ordinal numbers $m+1$ to $m+n$ denote +structural variables. The corresponding non-zero coefficients $\xi_j$ +should be placed in locations \verb|val[1]|, \dots, \verb|val[len]|. +The arrays \verb|ind| and \verb|val| are not changed by the routine. + +The parameter \verb|dir| specifies direction in which the variable $x$ +changes on leaving the basis: $+1$ means that $x$ goes on its lower +bound, so its reduced cost (dual variable) is increasing (minimization) +or decreasing (maximization); $-1$ means that $x$ goes on its upper +bound, so its reduced cost is decreasing (minimization) or increasing +(maximization). + +The parameter \verb|eps| is an absolute tolerance (small positive +number, say, $10^{-9}$) used by the routine to skip $\xi_j$'s whose +magnitude is less than \verb|eps|. + +The routine determines which non-basic variable (among those specified +in \verb|ind[1]|, \dots,\linebreak \verb|ind[len]|) should enter the +basis in order to keep dual feasibility, because its reduced cost +reaches the (zero) bound first before this occurs for any other +non-basic variables. + +\returns + +The routine \verb|glp_dual_rtest| returns the index, \verb|piv|, in the +arrays \verb|ind| and \verb|val| corresponding to the pivot element +chosen, $1\leq$ \verb|piv| $\leq$ \verb|len|. If the adjacent basic +solution is dual unbounded, and therefore the choice cannot be made, +the routine returns zero. + +\para{Comments} + +If the basic variable $x$ is presented in the LP problem object, the +input row can be computed\linebreak with the routine +\verb|glp_eval_tab_row|; otherwise, it can be computed with the routine +\linebreak \verb|glp_transform_row|. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Post-optimal analysis routines} + +\subsection{glp\_analyze\_bound --- analyze active bound of non-basic +variable} + +\synopsis + +\begin{verbatim} + void glp_analyze_bound(glp_prob *P, int k, double *limit1, int *var1, + double *limit2, int *var2); +\end{verbatim} + +\description + +The routine \verb|glp_analyze_bound| analyzes the effect of varying the +active bound of specified non-basic variable. + +The non-basic variable is specified by the parameter $k$, where +$1\leq k\leq m$ means auxiliary variable of corresponding row, and +$m+1\leq k\leq m+n$ means structural variable (column). + +Note that the current basic solution must be optimal, and the basis +factorization must exist. + +Results of the analysis have the following meaning. + +\verb|value1| is the minimal value of the active bound, at which the +basis still remains primal feasible and thus optimal. \verb|-DBL_MAX| +means that the active bound has no lower limit. + +\verb|var1| is the ordinal number of an auxiliary (1 to $m$) or +structural ($m+1$ to $m+n$) basic variable, which reaches its bound +first and thereby limits further decreasing the active bound being +analyzed. if \verb|value1| = \verb|-DBL_MAX|, \verb|var1| is set to 0. + +\verb|value2| is the maximal value of the active bound, at which the +basis still remains primal feasible and thus optimal. \verb|+DBL_MAX| +means that the active bound has no upper limit. + +\verb|var2| is the ordinal number of an auxiliary (1 to $m$) or +structural ($m+1$ to $m+n$) basic variable, which reaches its bound +first and thereby limits further increasing the active bound being +analyzed. if \verb|value2| = \verb|+DBL_MAX|, \verb|var2| is set to 0. + +The parameters \verb|value1|, \verb|var1|, \verb|value2|, \verb|var2| +can be specified as \verb|NULL|, in which case corresponding information +is not stored. + +\subsection{glp\_analyze\_coef --- analyze objective coefficient at +basic variable} + +\synopsis + +\begin{verbatim} + void glp_analyze_coef(glp_prob *P, int k, + double *coef1, int *var1, double *value1, + double *coef2, int *var2, double *value2); +\end{verbatim} + +\description + +The routine \verb|glp_analyze_coef| analyzes the effect of varying the +objective coefficient at specified basic variable. + +The basic variable is specified by the parameter $k$, where +$1\leq k\leq m$ means auxiliary variable of corresponding row, and +$m+1\leq k\leq m+n$ means structural variable (column). + +Note that the current basic solution must be optimal, and the basis +factorization must exist. + +Results of the analysis have the following meaning. + +\verb|coef1| is the minimal value of the objective coefficient, at +which the basis still remains dual feasible and thus optimal. +\verb|-DBL_MAX| means that the objective coefficient has no lower +limit. + +\verb|var1| is the ordinal number of an auxiliary (1 to $m$) or +structural ($m+1$ to $m+n$) non-basic variable, whose reduced cost +reaches its zero bound first and thereby limits further decreasing the +objective coefficient being analyzed. +If \verb|coef1| = \verb|-DBL_MAX|, \verb|var1| is set to 0. + +\verb|value1| is value of the basic variable being analyzed in an +adjacent basis, which is defined as follows. Let the objective +coefficient reach its minimal value (\verb|coef1|) and continue +decreasing. Then the reduced cost of the limiting non-basic variable +(\verb|var1|) becomes dual infeasible and the current basis becomes +non-optimal that forces the limiting non-basic variable to enter the +basis replacing there some basic variable that leaves the basis to keep +primal feasibility. Should note that on determining the adjacent basis +current bounds of the basic variable being analyzed are ignored as if +it were free (unbounded) variable, so it cannot leave the basis. It may +happen that no dual feasible adjacent basis exists, in which case +\verb|value1| is set to \verb|-DBL_MAX| or \verb|+DBL_MAX|. + +\verb|coef2| is the maximal value of the objective coefficient, at +which the basis still remains dual feasible and thus optimal. +\verb|+DBL_MAX| means that the objective coefficient has no upper +limit. + +\verb|var2| is the ordinal number of an auxiliary (1 to $m$) or +structural ($m+1$ to $m+n$) non-basic variable, whose reduced cost +reaches its zero bound first and thereby limits further increasing the +objective coefficient being analyzed. +If \verb|coef2| = \verb|+DBL_MAX|, \verb|var2| is set to 0. + +\verb|value2| is value of the basic variable being analyzed in an +adjacent basis, which is defined exactly in the same way as +\verb|value1| above with exception that now the objective coefficient +is increasing. + +The parameters \verb|coef1|, \verb|var1|, \verb|value1|, \verb|coef2|, +\verb|var2|, \verb|value2| can be specified as \verb|NULL|, in which +case corresponding information is not stored. + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk05.tex b/resources/3rdparty/glpk-4.53/doc/glpk05.tex new file mode 100644 index 000000000..d15123e3f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk05.tex @@ -0,0 +1,1090 @@ +%* glpk05.tex *% + +\chapter{Branch-and-Cut API Routines} + +\section{Introduction} + +\subsection{Using the callback routine} + +The GLPK MIP solver based on the branch-and-cut method allows the +application program to control the solution process. This is attained +by means of the user-defined callback routine, which is called by the +solver at various points of the branch-and-cut algorithm. + +The callback routine passed to the MIP solver should be written by the +user and has the following specification:\footnote{The name +{\tt foo\_bar} used here is a placeholder for the callback routine +name.} + +\begin{verbatim} + void foo_bar(glp_tree *T, void *info); +\end{verbatim} + +\noindent +where \verb|tree| is a pointer to the data structure \verb|glp_tree|, +which should be used on subsequent calls to branch-and-cut interface +routines, and \verb|info| is a transit pointer passed to the routine +\verb|glp_intopt|, which may be used by the application program to pass +some external data to the callback routine. + +The callback routine is passed to the MIP solver through the control +parameter structure \verb|glp_iocp| (see Chapter ``Basic API +Routines'', Section ``Mixed integer programming routines'', Subsection +``Solve MIP problem with the branch-and-cut method'') as follows: + +\begin{verbatim} + glp_prob *mip; + glp_iocp parm; + . . . + glp_init_iocp(&parm); + . . . + parm.cb_func = foo_bar; + parm.cb_info = ... ; + ret = glp_intopt(mip, &parm); + . . . +\end{verbatim} + +To determine why it is being called by the MIP solver the callback +routine should use the routine \verb|glp_ios_reason| (described in this +section below), which returns a code indicating the reason for calling. +Depending on the reason the callback routine may perform necessary +actions to control the solution process. + +The reason codes, which correspond to various point of the +branch-and-cut algorithm implemented in the MIP solver, are described +in Subsection ``Reasons for calling the callback routine'' below. + +To ignore calls for reasons, which are not processed by the callback +routine, it should simply return to the MIP solver doing nothing. For +example: + +\begin{verbatim} +void foo_bar(glp_tree *T, void *info) +{ . . . + switch (glp_ios_reason(T)) + { case GLP_IBRANCH: + . . . + break; + case GLP_ISELECT: + . . . + break; + default: + /* ignore call for other reasons */ + break; + } + return; +} +\end{verbatim} + +To control the solution process as well as to obtain necessary +information the callback routine may use the branch-and-cut API +routines described in this chapter. Names of all these routines begin +with `\verb|glp_ios_|'. + +\subsection{Branch-and-cut algorithm} + +This section gives a schematic description of the branch-and-cut +algorithm as it is implemented in the GLPK MIP solver. + +{\it 1. Initialization} + +Set $L:=\{P_0\}$, where $L$ is the {\it active list} (i.e. the list of +active subproblems), $P_0$ is the original MIP problem to be solved. + +Set $z^{\it best}:=+\infty$ (in case of minimization) or +$z^{\it best}:=-\infty$ (in case of maximization), where $z^{\it best}$ +is {\it incumbent value}, i.e. an upper (minimization) or lower +(maximization) global bound for $z^{\it opt}$, the optimal objective +value for $P^0$. + +{\it 2. Subproblem selection} + +If $L=\varnothing$ then GO TO 9. + +Select $P\in L$, i.e. make active subproblem $P$ current. + +\newpage + +{\it 3. Solving LP relaxation} + +Solve $P^{\it LP}$, which is LP relaxation of $P$. + +If $P^{\it LP}$ has no primal feasible solution then GO TO 8. + +Let $z^{\it LP}$ be the optimal objective value for $P^{\it LP}$. + +If $z^{\it LP}\geq z^{\it best}$ (minimization) or +$z^{\it LP}\leq z^{\rm best}$ (), GO TO 8. + +{\it 4. Adding ``lazy'' constraints} + +Let $x^{\it LP}$ be the optimal solution to $P^{\it LP}$. + +If there are ``lazy'' constraints (i.e. essential constraints not +included in the original MIP problem $P_0$), which are violated at the +optimal point $x^{\it LP}$, add them to $P$, and GO TO 3. + +{\it 5. Check for integrality} + +Let $x_j$ be a variable, which is required to be integer, and let +$x^{\it LP}_j\in x^{\it LP}$ be its value in the optimal solution to +$P^{\it LP}$. + +If $x^{\it LP}_j$ are integral for all integer variables, then a better +integer feasible solution is found. Store its components, set +$z^{\it best}:=z^{\it LP}$, and GO TO 8. + +{\it 6. Adding cutting planes} + +If there are cutting planes (i.e. valid constraints for $P$), +which are violated at the optimal point $x^{\it LP}$, add them to $P$, +and GO TO 3. + +{\it 7. Branching} + +Select {\it branching variable} $x_j$, i.e. a variable, which is +required to be integer, and whose value $x^{\it LP}_j\in x^{\it LP}$ is +fractional in the optimal solution to $P^{\it LP}$. + +Create new subproblem $P^D$ (so called {\it down branch}), which is +identical to the current subproblem $P$ with exception that the upper +bound of $x_j$ is replaced by $\lfloor x^{\it LP}_j\rfloor$. (For +example, if $x^{\it LP}_j=3.14$, the new upper bound of $x_j$ in the +down branch will be $\lfloor 3.14\rfloor=3$.) + +Create new subproblem $P^U$ (so called {\it up branch}), which is +identical to the current subproblem $P$ with exception that the lower +bound of $x_j$ is replaced by $\lceil x^{\it LP}_j\rceil$. (For example, +if $x^{\it LP}_j=3.14$, the new lower bound of $x_j$ in the up branch +will be $\lceil 3.14\rceil=4$.) + +Set $L:=(L\backslash\{P\})\cup\{P^D,P^U\}$, i.e. remove the current +subproblem $P$ from the active list $L$ and add two new subproblems +$P^D$ and $P^U$ to it. Then GO TO 2. + +{\it 8. Pruning} + +Remove from the active list $L$ all subproblems (including the current +one), whose local bound $\widetilde{z}$ is not better than the global +bound $z^{\it best}$, i.e. set $L:=L\backslash\{P\}$ for all $P$, where +$\widetilde{z}\geq z^{\it best}$ (in case of minimization) or +$\widetilde{z}\leq z^{\it best}$ (in case of maximization), and then +GO TO 2. + +The local bound $\widetilde{z}$ for subproblem $P$ is an lower +(minimization) or upper (maximization) bound for integer optimal +solution to {\it this} subproblem (not to the original problem). This +bound is local in the sense that only subproblems in the subtree rooted +at node $P$ cannot have better integer feasible solutions. Note that +the local bound is not necessarily the optimal objective value to LP +relaxation $P^{\it LP}$. + +{\it 9. Termination} + +If $z^{\it best}=+\infty$ (in case of minimization) or +$z^{\it best}=-\infty$ (in case of maximization), the original problem +$P_0$ has no integer feasible solution. Otherwise, the last integer +feasible solution stored on step 5 is the integer optimal solution to +the original problem $P_0$ with $z^{\it opt}=z^{\it best}$. STOP. + +\subsection{The search tree} + +On the branching step of the branch-and-cut algorithm the current +subproblem is divided into two\footnote{In more general cases the +current subproblem may be divided into more than two subproblems. +However, currently such feature is not used in GLPK.} new subproblems, +so the set of all subproblems can be represented in the form of a rooted +tree, which is called the {\it search} or {\it branch-and-bound} tree. +An example of the search tree is shown on Fig.~1. Each node of the +search tree corresponds to a subproblem, so the terms `node' and +`subproblem' may be used synonymously. + +\begin{figure}[t] +\noindent\hfil +\xymatrix @R=20pt @C=10pt +{&&&&&&*+<14pt>[o][F=]{A}\ar@{-}[dllll]\ar@{-}[dr]\ar@{-}[drrrr]&&&&\\ +&&*+<14pt>[o][F=]{B}\ar@{-}[dl]\ar@{-}[dr]&&&&&*+<14pt>[o][F=]{C} +\ar@{-}[dll]\ar@{-}[dr]\ar@{-}[drrr]&&&*+<14pt>[o][F-]{\times}\\ +&*+<14pt>[o][F-]{\times}\ar@{-}[dl]\ar@{-}[d]\ar@{-}[dr]&& +*+<14pt>[o][F-]{D}&&*+<14pt>[o][F=]{E}\ar@{-}[dl]\ar@{-}[dr]&&& +*+<14pt>[o][F=]{F}\ar@{-}[dl]\ar@{-}[dr]&&*+<14pt>[o][F-]{G}\\ +*+<14pt>[o][F-]{\times}&*+<14pt>[o][F-]{\times}&*+<14pt>[o][F-]{\times} +&&*+<14pt>[][F-]{H}&&*+<14pt>[o][F-]{I}&*+<14pt>[o][F-]{\times}&& +*+<14pt>[o][F-]{J}&\\} + +\bigskip + +\noindent\hspace{.8in} +\xymatrix @R=11pt +{*+<20pt>[][F-]{}&*\txt{\makebox[1in][l]{Current}}&& +*+<20pt>[o][F-]{}&*\txt{\makebox[1in][l]{Active}}\\ +*+<20pt>[o][F=]{}&*\txt{\makebox[1in][l]{Non-active}}&& +*+<14pt>[o][F-]{\times}&*\txt{\makebox[1in][l]{Fathomed}}\\ +} + +\bigskip + +\begin{center} +Fig. 1. An example of the search tree. +\end{center} +\end{figure} + +In GLPK each node may have one of the following four statuses: + +\vspace*{-8pt} + +\begin{itemize} +\item {\it current node} is the active node currently being +processed; + +\item {\it active node} is a leaf node, which still has to be +processed; + +\item {\it non-active node} is a node, which has been processed, +but not fathomed; + +\item {\it fathomed node} is a node, which has been processed and +fathomed. +\end{itemize} + +\vspace*{-8pt} + +In the data structure representing the search tree GLPK keeps only +current, active, and non-active nodes. Once a node has been fathomed, +it is removed from the tree data structure. + +Being created each node of the search tree is assigned a distinct +positive integer called the {\it subproblem reference number}, which +may be used by the application program to specify a particular node of +the tree. The root node corresponding to the original problem to be +solved is always assigned the reference number 1. + +\subsection{Current subproblem} + +The current subproblem is a MIP problem corresponding to the current +node of the search tree. It is represented as the GLPK problem object +(\verb|glp_prob|) that allows the application program using API +routines to access its content in the standard way. If the MIP +presolver is not used, it is the original problem object passed to the +routine \verb|glp_intopt|; otherwise, it is an internal problem object +built by the MIP presolver. + +Note that the problem object is used by the MIP solver itself during +the solution process for various purposes (to solve LP relaxations, to +perfom branching, etc.), and even if the MIP presolver is not used, the +current content of the problem object may differ from its original +content. For example, it may have additional rows, bounds of some rows +and columns may be changed, etc. In particular, LP segment of the +problem object corresponds to LP relaxation of the current subproblem. +However, on exit from the MIP solver the content of the problem object +is restored to its original state. + +To obtain information from the problem object the application program +may use any API routines, which do not change the object. Using API +routines, which change the problem object, is restricted to stipulated +cases. + +\subsection{The cut pool} + +The {\it cut pool} is a set of cutting plane constraints maintained by +the MIP solver. It is used by the GLPK cut generation routines and may +be used by the application program in the same way, i.e. rather than +to add cutting plane constraints directly to the problem object the +application program may store them to the cut pool. In the latter case +the solver looks through the cut pool, selects efficient constraints, +and adds them to the problem object. + +\subsection{Reasons for calling the callback routine} + +The callback routine may be called by the MIP solver for the following +reasons. + +\para{Request for subproblem selection} + +The callback routine is called with the reason code \verb|GLP_ISELECT| +if the current subproblem has been fathomed and therefore there is no +current subproblem. + +In response the callback routine may select some subproblem from the +active list and pass its reference number to the solver using the +routine \verb|glp_ios_select_node|, in which case the solver continues +the search from the specified active subproblem. If no selection is +made by the callback routine, the solver uses a backtracking technique +specified by the control parameter \verb|bt_tech|. + +To explore the active list (i.e. active nodes of the branch-and-bound +tree) the callback routine may use the routines \verb|glp_ios_next_node| +and \verb|glp_ios_prev_node|. + +\para{Request for preprocessing} + +The callback routine is called with the reason code \verb|GLP_IPREPRO| +if the current subproblem has just been selected from the active list +and its LP relaxation is not solved yet. + +In response the callback routine may perform some preprocessing of the +current subproblem like tightening bounds of some variables or removing +bounds of some redundant constraints. + +\para{Request for row generation} + +The callback routine is called with the reason code \verb|GLP_IROWGEN| +if LP relaxation of the current subproblem has just been solved to +optimality and its objective value is better than the best known +integer feasible solution. + +In response the callback routine may add one or more ``lazy'' +constraints (rows), which are violated by the current optimal solution +of LP relaxation, using API routines \verb|glp_add_rows|, +\verb|glp_set_row_name|, \verb|glp_set_row_bnds|, and +\verb|glp_set_mat_row|, in which case the solver will perform +re-optimization of LP relaxation. If there are no violated constraints, +the callback routine should just return. + +Note that components of optimal solution to LP relaxation can be +obtained with API\linebreak routines \verb|glp_get_obj_val|, +\verb|glp_get_row_prim|, \verb|glp_get_row_dual|, +\verb|glp_get_col_prim|, and\linebreak \verb|glp_get_col_dual|. + +\para{Request for heuristic solution} + +The callback routine is called with the reason code \verb|GLP_IHEUR| +if LP relaxation of the current subproblem being solved to optimality +is integer infeasible (i.e. values of some structural variables of +integer kind are fractional), though its objective value is better than +the best known integer feasible solution. + +In response the callback routine may try applying a primal heuristic +to find an integer feasible solution,\footnote{Integer feasible to the +original MIP problem, not to the current subproblem.} which is better +than the best known one. In case of success the callback routine may +store such better solution in the problem object using the routine +\verb|glp_ios_heur_sol|. + +\para{Request for cut generation} + +The callback routine is called with the reason code \verb|GLP_ICUTGEN| +if LP relaxation of the current subproblem being solved to optimality +is integer infeasible (i.e. values of some structural variables of +integer kind are fractional), though its objective value is better than +the best known integer feasible solution. + +In response the callback routine may reformulate the {\it current} +subproblem (before it will be splitted up due to branching) by adding +to the problem object one or more {\it cutting plane constraints}, +which cut off the fractional optimal point from the MIP +polytope.\footnote{Since these constraints are added to the current +subproblem, they may be globally as well as locally valid.} + +Adding cutting plane constraints may be performed in two ways. +One way is the same as for the reason code \verb|GLP_IROWGEN| (see +above), in which case the callback routine adds new rows corresponding +to cutting plane constraints directly to the current subproblem. + +The other way is to add cutting plane constraints to the +{\it cut pool}, a set of cutting plane constraints maintained by the +solver, rather than directly to the current subproblem. In this case +after return from the callback routine the solver looks through the +cut pool, selects efficient cutting plane constraints, adds them to the +current subproblem, drops other constraints, and then performs +re-optimization. + +\para{Request for branching} + +The callback routine is called with the reason code \verb|GLP_IBRANCH| +if LP relaxation of the current subproblem being solved to optimality +is integer infeasible (i.e. values of some structural variables of +integer kind are fractional), though its objective value is better than +the best known integer feasible solution. + +In response the callback routine may choose some variable suitable for +branching (i.e. integer variable, whose value in optimal solution to +LP relaxation of the current subproblem is fractional) and pass its +ordinal number to the solver using the routine +\verb|glp_ios_branch_upon|, in which case the solver splits the current +subproblem in two new subproblems and continues the search. +If no choice is made by the callback routine, the solver uses +a branching technique specified by the control parameter \verb|br_tech|. + +\para{Better integer solution found} + +The callback routine is called with the reason code \verb|GLP_IBINGO| +if LP relaxation of the current subproblem being solved to optimality +is integer feasible (i.e. values of all structural variables of integer +kind are integral within the working precision) and its objective value +is better than the best known integer feasible solution. + +Optimal solution components for LP relaxation can be obtained in the +same way as for the reason code \verb|GLP_IROWGEN| (see above). + +Components of the new MIP solution can be obtained with API routines +\verb|glp_mip_obj_val|, \verb|glp_mip_row_val|, and +\verb|glp_mip_col_val|. Note, however, that due to row/cut generation +there may be additional rows in the problem object. + +The difference between optimal solution to LP relaxation and +corresponding MIP solution is that in the former case some structural +variables of integer kind (namely, basic variables) may have values, +which are close to nearest integers within the working precision, while +in the latter case all such variables have exact integral values. + +The reason \verb|GLP_IBINGO| is intended only for informational +purposes, so the callback routine should not modify the problem object +in this case. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Basic routines} + +\subsection{glp\_ios\_reason --- determine reason for calling the +callback routine} + +\synopsis + +\begin{verbatim} + int glp_ios_reason(glp_tree *T); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_reason| returns a code, which indicates why +the user-defined callback routine is being called: + +\verb|GLP_ISELECT| --- request for subproblem selection; + +\verb|GLP_IPREPRO| --- request for preprocessing; + +\verb|GLP_IROWGEN| --- request for row generation; + +\verb|GLP_IHEUR | --- request for heuristic solution; + +\verb|GLP_ICUTGEN| --- request for cut generation; + +\verb|GLP_IBRANCH| --- request for branching; + +\verb|GLP_IBINGO | --- better integer solution found. + +\subsection{glp\_ios\_get\_prob --- access the problem object} + +\synopsis + +\begin{verbatim} + glp_prob *glp_ios_get_prob(glp_tree *T); +\end{verbatim} + +\description + +The routine \verb|glp_ios_get_prob| can be called from the user-defined +callback routine to access the problem object, which is used by the MIP +solver. It is the original problem object passed to the routine +\verb|glp_intopt| if the MIP presolver is not used; otherwise it is an +internal problem object built by the presolver. + +\returns + +The routine \verb|glp_ios_get_prob| returns a pointer to the problem +object used by the MIP solver. + +\para{Comments} + +To obtain various information about the problem instance the callback +routine can access the problem object (i.e. the object of type +\verb|glp_prob|) using the routine \verb|glp_ios_get_prob|. It is the +original problem object passed to the routine \verb|glp_intopt| if the +MIP presolver is not used; otherwise it is an internal problem object +built by the presolver. + +\newpage + +\subsection{glp\_ios\_row\_attr --- determine additional row +attributes} + +\synopsis + +\begin{verbatim} + void glp_ios_row_attr(glp_tree *T, int i, glp_attr *attr); +\end{verbatim} + +\description + +The routine \verb|glp_ios_row_attr| retrieves additional attributes of +$i$-th row of the current subproblem and stores them in the structure +\verb|glp_attr|, which the parameter \verb|attr| points to. + +The structure \verb|glp_attr| has the following fields: + +\medskip + +{\tt int level} + +Subproblem level at which the row was created. (If \verb|level| = 0, +the row was added either to the original problem object passed to the +routine \verb|glp_intopt| or to the root subproblem on generating +``lazy'' or/and cutting plane constraints.) + +\medskip + +{\tt int origin} + +The row origin flag: + +\verb|GLP_RF_REG | --- regular constraint; + +\verb|GLP_RF_LAZY| --- ``lazy'' constraint; + +\verb|GLP_RF_CUT | --- cutting plane constraint. + +\medskip + +{\tt int klass} + +The row class descriptor, which is a number passed to the routine +\verb|glp_ios_add_row| as its third parameter. If the row is a cutting +plane constraint generated by the solver, its class may be the +following: + +\verb|GLP_RF_GMI | --- Gomory's mixed integer cut; + +\verb|GLP_RF_MIR | --- mixed integer rounding cut; + +\verb|GLP_RF_COV | --- mixed cover cut; + +\verb|GLP_RF_CLQ | --- clique cut. + +\subsection{glp\_ios\_mip\_gap --- compute relative MIP gap} + +\synopsis + +\begin{verbatim} + double glp_ios_mip_gap(glp_tree *T); +\end{verbatim} + +\description + +The routine \verb|glp_ios_mip_gap| computes the relative MIP gap (also +called {\it duality gap}) with the following formula: +$${\tt gap} = \frac{|{\tt best\_mip} - {\tt best\_bnd}|} +{|{\tt best\_mip}| + {\tt DBL\_EPSILON}}$$ +where \verb|best_mip| is the best integer feasible solution found so +far, \verb|best_bnd| is the best (global) bound. If no integer feasible +solution has been found yet, \verb|gap| is set to \verb|DBL_MAX|. + +\returns + +The routine \verb|glp_ios_mip_gap| returns the relative MIP gap. + +\para{Comments} + +The relative MIP gap is used to measure the quality of the best integer +feasible solution found so far, because the optimal solution value +$z^*$ for the original MIP problem always lies in the range +$${\tt best\_bnd}\leq z^*\leq{\tt best\_mip}$$ +in case of minimization, or in the range +$${\tt best\_mip}\leq z^*\leq{\tt best\_bnd}$$ +in case of maximization. + +To express the relative MIP gap in percents the value returned by the +routine \verb|glp_ios_mip_gap| should be multiplied by 100\%. + +\subsection{glp\_ios\_node\_data --- access application-specific data} + +\synopsis + +\begin{verbatim} + void *glp_ios_node_data(glp_tree *T, int p); +\end{verbatim} + +\description + +The routine \verb|glp_ios_node_data| allows the application accessing +a memory block allocated for the subproblem (which may be active or +inactive), whose reference number is $p$. + +The size of the block is defined by the control parameter +\verb|cb_size| passed to the routine \verb|glp_intopt|. The block is +initialized by binary zeros on creating corresponding subproblem, and +its contents is kept until the subproblem will be removed from the +tree. + +The application may use these memory blocks to store specific data for +each subproblem. + +\returns + +The routine \verb|glp_ios_node_data| returns a pointer to the memory +block for the specified subproblem. Note that if \verb|cb_size| = 0, +the routine returns a null pointer. + +\subsection{glp\_ios\_select\_node --- select subproblem to continue +the search} + +\synopsis + +\begin{verbatim} + void glp_ios_select_node(glp_tree *T, int p); +\end{verbatim} + +\description + +The routine \verb|glp_ios_select_node| can be called from the +user-defined callback routine in response to the reason +\verb|GLP_ISELECT| to select an active subproblem, whose reference +number\linebreak is $p$. The search will be continued from the +subproblem selected. + +\newpage + +\subsection{glp\_ios\_heur\_sol --- provide solution found by +heuristic} + +\synopsis + +\begin{verbatim} + int glp_ios_heur_sol(glp_tree *T, const double x[]); +\end{verbatim} + +\description + +The routine \verb|glp_ios_heur_sol| can be called from the user-defined +callback routine in response to the reason \verb|GLP_IHEUR| to provide +an integer feasible solution found by a primal heuristic. + +Primal values of {\it all} variables (columns) found by the heuristic +should be placed in locations $x[1]$, \dots, $x[n]$, where $n$ is the +number of columns in the original problem object. Note that the routine +\verb|glp_ios_heur_sol| does {\it not} check primal feasibility of the +solution provided. + +Using the solution passed in the array $x$ the routine computes value +of the objective function. If the objective value is better than the +best known integer feasible solution, the routine computes values of +auxiliary variables (rows) and stores all solution components in the +problem object. + +\returns + +If the provided solution is accepted, the routine +\verb|glp_ios_heur_sol| returns zero. Otherwise, if the provided +solution is rejected, the routine returns non-zero. + +\vspace*{-5pt} + +\subsection{glp\_ios\_can\_branch --- check if can branch upon +specified variable} + +\synopsis + +\begin{verbatim} + int glp_ios_can_branch(glp_tree *T, int j); +\end{verbatim} + +\returns + +If $j$-th variable (column) can be used to branch upon, the routine +returns non-zero, otherwise zero. + +\vspace*{-5pt} + +\subsection{glp\_ios\_branch\_upon --- choose variable to branch upon} + +\synopsis + +\begin{verbatim} + void glp_ios_branch_upon(glp_tree *T, int j, int sel); +\end{verbatim} + +\description + +The routine \verb|glp_ios_branch_upon| can be called from the +user-defined callback routine in response to the reason +\verb|GLP_IBRANCH| to choose a branching variable, whose ordinal number +\linebreak is $j$. Should note that only variables, for which the +routine \verb|glp_ios_can_branch| returns non-zero, can be used to +branch upon. + +The parameter \verb|sel| is a flag that indicates which branch +(subproblem) should be selected next to continue the search: + +\verb|GLP_DN_BRNCH| --- select down-branch; + +\verb|GLP_UP_BRNCH| --- select up-branch; + +\verb|GLP_NO_BRNCH| --- use general selection technique. + +\para{Comments} + +On branching the solver removes the current active subproblem from the +active list and creates two new subproblems ({\it down-} and {\it +up-branches}), which are added to the end of the active list. Note that +the down-branch is created before the up-branch, so the last active +subproblem will be the up-branch. + +The down- and up-branches are identical to the current subproblem with +exception that in the down-branch the upper bound of $x_j$, the variable +chosen to branch upon, is replaced by $\lfloor x_j^*\rfloor$, while in +the up-branch the lower bound of $x_j$ is replaced by +$\lceil x_j^*\rceil$, where $x_j^*$ is the value of $x_j$ in optimal +solution to LP relaxation of the current subproblem. For example, if +$x_j^*=3.14$, the new upper bound of $x_j$ in the down-branch is +$\lfloor 3.14\rfloor=3$, and the new lower bound in the up-branch is +$\lceil 3.14\rceil=4$.) + +Additionally the callback routine may select either down- or up-branch, +from which the solver will continue the search. If none of the branches +is selected, a general selection technique will be used. + +\subsection{glp\_ios\_terminate --- terminate the solution process} + +\synopsis + +\begin{verbatim} + void glp_ios_terminate(glp_tree *T); +\end{verbatim} + +\description + +The routine \verb|glp_ios_terminate| sets a flag indicating that the +MIP solver should prematurely terminate the search. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{The search tree exploring routines} + +\subsection{glp\_ios\_tree\_size --- determine size of the search tree} + +\synopsis + +\begin{verbatim} + void glp_ios_tree_size(glp_tree *T, int *a_cnt, int *n_cnt, int *t_cnt); +\end{verbatim} + +\description + +The routine \verb|glp_ios_tree_size| stores the following three counts +which characterize the current size of the search tree: + +\verb|a_cnt| is the current number of active nodes, i.e. the current +size of the active list; + +\verb|n_cnt| is the current number of all (active and inactive) nodes; + +\verb|t_cnt| is the total number of nodes including those which have +been already removed from the tree. This count is increased whenever +a new node appears in the tree and never decreased. + +If some of the parameters \verb|a_cnt|, \verb|n_cnt|, \verb|t_cnt| is +a null pointer, the corresponding count is not stored. + +\subsection{glp\_ios\_curr\_node --- determine current active +subproblem} + +\synopsis + +\begin{verbatim} + int glp_ios_curr_node(glp_tree *T); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_curr_node| returns the reference number of +the current active subproblem. However, if the current subproblem does +not exist, the routine returns zero. + +\subsection{glp\_ios\_next\_node --- determine next active subproblem} + +\synopsis + +\begin{verbatim} + int glp_ios_next_node(glp_tree *T, int p); +\end{verbatim} + +\returns + +If the parameter $p$ is zero, the routine \verb|glp_ios_next_node| +returns the reference number of the first active subproblem. However, +if the tree is empty, zero is returned. + +If the parameter $p$ is not zero, it must specify the reference number +of some active subproblem, in which case the routine returns the +reference number of the next active subproblem. However, if there is +no next active subproblem in the list, zero is returned. + +All subproblems in the active list are ordered chronologically, i.e. +subproblem $A$ precedes subproblem $B$ if $A$ was created before $B$. + +\newpage + +\subsection{glp\_ios\_prev\_node --- determine previous active +subproblem} + +\synopsis + +\begin{verbatim} + int glp_ios_prev_node(glp_tree *T, int p); +\end{verbatim} + +\returns + +If the parameter $p$ is zero, the routine \verb|glp_ios_prev_node| +returns the reference number of the last active subproblem. However, if +the tree is empty, zero is returned. + +If the parameter $p$ is not zero, it must specify the reference number +of some active subproblem, in which case the routine returns the +reference number of the previous active subproblem. However, if there +is no previous active subproblem in the list, zero is returned. + +All subproblems in the active list are ordered chronologically, i.e. +subproblem $A$ precedes subproblem $B$ if $A$ was created before $B$. + +\subsection{glp\_ios\_up\_node --- determine parent subproblem} + +\synopsis + +\begin{verbatim} + int glp_ios_up_node(glp_tree *T, int p); +\end{verbatim} + +\returns + +The parameter $p$ must specify the reference number of some (active or +inactive) subproblem, in which case the routine \verb|iet_get_up_node| +returns the reference number of its parent subproblem. However, if the +specified subproblem is the root of the tree and, therefore, has +no parent, the routine returns zero. + +\subsection{glp\_ios\_node\_level --- determine subproblem level} + +\synopsis + +\begin{verbatim} + int glp_ios_node_level(glp_tree *T, int p); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_node_level| returns the level of the +subproblem, whose reference number is $p$, in the branch-and-bound +tree. (The root subproblem has level 0, and the level of any other +subproblem is the level of its parent plus one.) + +\subsection{glp\_ios\_node\_bound --- determine subproblem local bound} + +\synopsis + +\begin{verbatim} + double glp_ios_node_bound(glp_tree *T, int p); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_node_bound| returns the local bound for +(active or inactive) subproblem, whose reference number is $p$. + +\para{Comments} + +The local bound for subproblem $p$ is an lower (minimization) or upper +(maximization) bound for integer optimal solution to {\it this} +subproblem (not to the original problem). This bound is local in the +sense that only subproblems in the subtree rooted at node $p$ cannot +have better integer feasible solutions. + +On creating a subproblem (due to the branching step) its local bound is +inherited from its parent and then may get only stronger (never weaker). +For the root subproblem its local bound is initially set to +\verb|-DBL_MAX| (minimization) or \verb|+DBL_MAX| (maximization) and +then improved as the root LP relaxation has been solved. + +Note that the local bound is not necessarily the optimal objective +value to corresponding LP relaxation. + +\subsection{glp\_ios\_best\_node --- find active subproblem with best +local bound} + +\synopsis + +\begin{verbatim} + int glp_ios_best_node(glp_tree *T); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_best_node| returns the reference number of +the active subproblem, whose local bound is best (i.e. smallest in case +of minimization or largest in case of maximization). However, if the +tree is empty, the routine returns zero. + +\para{Comments} + +The best local bound is an lower (minimization) or upper (maximization) +bound for integer optimal solution to the original MIP problem. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{The cut pool routines} + +\subsection{glp\_ios\_pool\_size --- determine current size of the cut +pool} + +\synopsis + +\begin{verbatim} + int glp_ios_pool_size(glp_tree *T); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_pool_size| returns the current size of the +cut pool, that is, the number of cutting plane constraints currently +added to it. + +\subsection{glp\_ios\_add\_row --- add constraint to the cut pool} + +\synopsis + +\begin{verbatim} + int glp_ios_add_row(glp_tree *T, const char *name, int klass, int flags, + int len, const int ind[], const double val[], int type, double rhs); +\end{verbatim} + +\description + +The routine \verb|glp_ios_add_row| adds specified row (cutting plane +constraint) to the cut pool. + +The cutting plane constraint should have the following format: +$$\sum_{j\in J}a_jx_j\left\{\begin{array}{@{}c@{}}\geq\\\leq\\ +\end{array}\right\}b,$$ +where $J$ is a set of indices (ordinal numbers) of structural +variables, $a_j$ are constraint coefficients, $x_j$ are structural +variables, $b$ is the right-hand side. + +The parameter \verb|name| specifies a symbolic name assigned to the +constraint (1 up to 255 characters). If it is \verb|NULL| or an empty +string, no name is assigned. + +The parameter \verb|klass| specifies the constraint class, which must +be either zero or a number in the range from 101 to 200. +The application may use this attribute to distinguish between cutting +plane constraints of different classes.\footnote{Constraint classes +numbered from 1 to 100 are reserved for GLPK cutting plane generators.} + +The parameter \verb|flags| currently is not used and must be zero. + +Ordinal numbers of structural variables (i.e. column indices) $j\in J$ +and numerical values of corresponding constraint coefficients $a_j$ +should be placed in locations \verb|ind[1]|, \dots, \verb|ind[len]| and +\verb|val[1]|, \dots, \verb|val[len]|, respectively, where +${\tt len}=|J|$ is the number of constraint coefficients, +$0\leq{\tt len}\leq n$, and $n$ is the number of columns in the problem +object. Coefficients with identical column indices are not allowed. +Zero coefficients are allowed, however, they are ignored. + +The parameter \verb|type| specifies the constraint type as follows: + +\verb|GLP_LO| means inequality constraint $\Sigma a_jx_j\geq b$; + +\verb|GLP_UP| means inequality constraint $\Sigma a_jx_j\leq b$; + +The parameter \verb|rhs| specifies the right-hand side $b$. + +All cutting plane constraints in the cut pool are identified by their +ordinal numbers 1, 2, \dots, $size$, where $size$ is the current size +of the cut pool. New constraints are always added to the end of the cut +pool, thus, ordinal numbers of previously added constraints are not +changed. + +\returns + +The routine \verb|glp_ios_add_row| returns the ordinal number of the +cutting plane constraint added, which is the new size of the cut pool. + +\para{Example} + +\begin{verbatim} +/* generate triangle cutting plane: + x[i] + x[j] + x[k] <= 1 */ +. . . +/* add the constraint to the cut pool */ +ind[1] = i, val[1] = 1.0; +ind[2] = j, val[2] = 1.0; +ind[3] = k, val[3] = 1.0; +glp_ios_add_row(tree, NULL, TRIANGLE_CUT, 0, 3, ind, val, GLP_UP, 1.0); +\end{verbatim} + +\para{Comments} + +Cutting plane constraints added to the cut pool are intended to be then +added only to the {\it current} subproblem, so these constraints can be +globally as well as locally valid. However, adding a constraint to the +cut pool does not mean that it will be added to the current +subproblem---it depends on the solver's decision: if the constraint +seems to be efficient, it is moved from the pool to the current +subproblem, otherwise it is simply dropped.\footnote{Globally valid +constraints could be saved and then re-used for other subproblems, but +currently such feature is not implemented.} + +Normally, every time the callback routine is called for cut generation, +the cut pool is empty. On the other hand, the solver itself can +generate cutting plane constraints (like Gomory's or mixed integer +rounding cuts), in which case the cut pool may be non-empty. + +\subsection{glp\_ios\_del\_row --- remove constraint from the cut pool} + +\synopsis + +\begin{verbatim} + void glp_ios_del_row(glp_tree *T, int i); +\end{verbatim} + +\description + +The routine \verb|glp_ios_del_row| deletes $i$-th row (cutting plane +constraint) from the cut pool, where $1\leq i\leq size$ is the ordinal +number of the constraint in the pool, $size$ is the current size of the +cut pool. + +Note that deleting a constraint from the cut pool leads to changing +ordinal numbers of other constraints remaining in the pool. New ordinal +numbers of the remaining constraints are assigned under assumption that +the original order of constraints is not changed. Let, for example, +there be four constraints $a$, $b$, $c$ and $d$ in the cut pool, which +have ordinal numbers 1, 2, 3 and 4, respectively, and let constraint +$b$ have been deleted. Then after deletion the remaining constraint $a$, +$c$ and $d$ are assigned new ordinal numbers 1, 2 and 3, respectively. + +To find the constraint to be deleted the routine \verb|glp_ios_del_row| +uses ``smart'' linear search, so it is recommended to remove +constraints in a natural or reverse order and avoid removing them in +a random order. + +\para{Example} + +\begin{verbatim} +/* keep first 10 constraints in the cut pool and remove other + constraints */ +while (glp_ios_pool_size(tree) > 10) + glp_ios_del_row(tree, glp_ios_pool_size(tree)); +\end{verbatim} + +\subsection{glp\_ios\_clear\_pool --- remove all constraints from the +cut pool} + +\synopsis + +\begin{verbatim} + void glp_ios_clear_pool(glp_tree *T); +\end{verbatim} + +\description + +The routine \verb|glp_ios_clear_pool| makes the cut pool empty deleting +all existing rows (cutting plane constraints) from it. + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk06.tex b/resources/3rdparty/glpk-4.53/doc/glpk06.tex new file mode 100644 index 000000000..71eb8197d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk06.tex @@ -0,0 +1,441 @@ +%* glpk06.tex *% + +\chapter{Miscellaneous API Routines} + +\section{GLPK environment routines} + +\subsection{glp\_init\_env --- initialize GLPK environment} + +\synopsis + +\begin{verbatim} + int glp_init_env(void); +\end{verbatim} + +\description + +The routine \verb|glp_init_env| initializes the GLPK environment. +Normally the application program does not need to call this routine, +because it is called automatically on the first call to any API +routine. + +\returns + +\begin{retlist} +0 & initialization successful;\\ +1 & environment is already initialized;\\ +2 & initialization failed (insufficient memory);\\ +3 & initialization failed (unsupported programming model).\\ +\end{retlist} + +\subsection{glp\_version --- determine library version} + +\synopsis + +\begin{verbatim} + const char *glp_version(void); +\end{verbatim} + +\returns + +The routine \verb|glp_version| returns a pointer to a null-terminated +character string, which specifies the version of the GLPK library in +the form \verb|"X.Y"|, where `\verb|X|' is the major version number, +and `\verb|Y|' is the minor version number, for example, \verb|"4.16"|. + +\newpage + +\subsection{glp\_free\_env --- free GLPK environment} + +\synopsis + +\begin{verbatim} + int glp_free_env(void); +\end{verbatim} + +\description + +The routine \verb|glp_free_env| frees all resources used by GLPK +routines (memory blocks, etc.) which are currently still in use. + +Normally the application program does not need to call this routine, +because GLPK routines always free all unused resources. However, if +the application program even has deleted all problem objects, there +will be several memory blocks still allocated for the internal library +needs. For some reasons the application program may want GLPK to free +this memory, in which case it should call \verb|glp_free_env|. + +Note that a call to \verb|glp_free_env| invalidates all problem objects +which still exist. + +\returns + +\begin{retlist} +0 & termination successful;\\ +1 & environment is inactive (was not initialized).\\ +\end{retlist} + +\subsection{glp\_printf --- write formatted output to terminal} + +\synopsis + +\begin{verbatim} + void glp_printf(const char *fmt, ...); +\end{verbatim} + +\description + +The routine \verb|glp_printf| uses the format control string +\verb|fmt| to format its parameters and writes the formatted output to +the terminal. + +This routine is a replacement of the standard C function +\verb|printf| and used by all GLPK routines to perform terminal +output. The application program may use \verb|glp_printf| for the same +purpose that allows controlling its terminal output with the routines +\verb|glp_term_out| and \verb|glp_term_hook|. + +\subsection{glp\_vprintf --- write formatted output to terminal} + +\synopsis + +\begin{verbatim} + void glp_vprintf(const char *fmt, va_list arg); +\end{verbatim} + +\description + +The routine \verb|glp_vprintf| uses the format control string +\verb|fmt| to format its parameters specified by the list \verb|arg| +and writes the formatted output to the terminal. + +This routine is a replacement of the standard C function +\verb|vprintf| and used by all GLPK routines to perform terminal +output. The application program may use \verb|glp_vprintf| for the same +purpose that allows controlling its terminal output with the routines +\verb|glp_term_out| and \verb|glp_term_hook|. + +\newpage + +\subsection{glp\_term\_out --- enable/disable terminal output} + +\synopsis + +\begin{verbatim} + int glp_term_out(int flag); +\end{verbatim} + +\description + +Depending on the parameter flag the routine \verb|glp_term_out| enables +or disables terminal output performed by glpk routines: + +\verb|GLP_ON | --- enable terminal output; + +\verb|GLP_OFF| --- disable terminal output. + +\returns + +The routine \verb|glp_term_out| returns the previous value of the +terminal output flag. + +\subsection{glp\_term\_hook --- intercept terminal output} + +\synopsis + +\begin{verbatim} + void glp_term_hook(int (*func)(void *info, const char *s), void *info); +\end{verbatim} + +\description + +The routine \verb|glp_term_hook| installs the user-defined hook routine +to intercept all terminal output performed by GLPK routines. + +%This feature can be used to redirect the terminal output to other +%destination, for example, to a file or a text window. + +The parameter {\it func} specifies the user-defined hook routine. It is +called from an internal printing routine, which passes to it two +parameters: {\it info} and {\it s}. The parameter {\it info} is a +transit pointer specified in corresponding call to the routine +\verb|glp_term_hook|; it may be used to pass some additional information +to the hook routine. The parameter {\it s} is a pointer to the null +terminated character string, which is intended to be written to the +terminal. If the hook routine returns zero, the printing routine writes +the string {\it s} to the terminal in a usual way; otherwise, if the +hook routine returns non-zero, no terminal output is performed. + +To uninstall the hook routine both parameters {\it func} and {\it info} +should be specified as \verb|NULL|. + +\para{Example} + +\begin{footnotesize} +\begin{verbatim} +static int hook(void *info, const char *s) +{ FILE *foo = info; + fputs(s, foo); + return 1; +} + +int main(void) +{ FILE *foo; + . . . + glp_term_hook(hook, foo); /* redirect terminal output */ + . . . + glp_term_hook(NULL, NULL); /* resume terminal output */ + . . . +} +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_open\_tee --- start copying terminal output} + +\synopsis + +\begin{verbatim} + int glp_open_tee(const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_open_tee| starts copying all the terminal output +to an output text file, whose name is specified by the character string +\verb|fname|. + +\returns + +\begin{retlist} +0 & operation successful;\\ +1 & copying terminal output is already active;\\ +2 & unable to create output file.\\ +\end{retlist} + +\subsection{glp\_close\_tee --- stop copying terminal output} + +\synopsis + +\begin{verbatim} + int glp_close_tee(void); +\end{verbatim} + +\description + +The routine \verb|glp_close_tee| stops copying the terminal output to +the output text file previously open by the routine \verb|glp_open_tee| +closing that file. + +\returns + +\begin{retlist} +0 & operation successful;\\ +1 & copying terminal output was not started.\\ +\end{retlist} + +\subsection{glp\_error --- display error message and terminate +execution} + +\synopsis + +\begin{verbatim} + void glp_error(const char *fmt, ...); +\end{verbatim} + +\description + +The routine \verb|glp_error| (implemented as a macro) formats its +parameters using the format control string \verb|fmt|, writes the +formatted message to the terminal, and then abnormally terminates the +program. + +\newpage + +\subsection{glp\_assert --- check logical condition} + +\synopsis + +\begin{verbatim} + void glp_assert(int expr); +\end{verbatim} + +\description + +The routine \verb|glp_assert| (implemented as a macro) checks +a logical condition specified by the expression \verb|expr|. If the +condition is true (non-zero), the routine does nothing; otherwise, if +the condition is false (zero), the routine prints an error message and +abnormally terminates the program. + +This routine is a replacement of the standard C function \verb|assert| +and used by all GLPK routines to check program logic. The application +program may use \verb|glp_assert| for the same purpose. + +\subsection{glp\_error\_hook --- install hook to intercept abnormal +termination} + +\synopsis + +\begin{verbatim} + void glp_error_hook(void (*func)(void *info), void *info); +\end{verbatim} + +\description + +The routine \verb|glp_error_hook| installs a user-defined hook routine +to intercept abnormal termination. + +The parameter \verb|func| specifies the user-defined hook routine. It +is called from the routine \verb|glp_error| before the latter calls the +abort function to abnormally terminate the application program because +of fatal error. The parameter \verb|info| is a transit pointer, +specified in the corresponding call to the routine +\verb|glp_error_hook|; it may be used to pass some information to the +hook routine. + +To uninstall the hook routine the parameters \verb|func| and \verb|info| +should be specified as \verb|NULL|. + +If the hook routine returns, the application program is abnormally +terminated. To prevent abnormal termnation the hook routine may perform +a global jump using the standard function \verb|longjmp|, in which case +the application program {\it must} call the routine \verb|glp_free_env|. + +\subsection{glp\_malloc --- allocate memory block} + +\synopsis + +\begin{verbatim} + void *glp_malloc(int size); +\end{verbatim} + +\description + +The routine \verb|glp_malloc| dynamically allocates a memory block of +\verb|size| bytes long. Note that: + +1) the parameter \verb|size| must be positive; + +2) being allocated the memory block contains arbitrary data, that is, +it is {\it not} initialized by binary zeros; + +3) if the block cannot be allocated due to insufficient memory, the +routine prints an error message and abnormally terminates the program. + +This routine is a replacement of the standard C function \verb|malloc| +and used by all GLPK routines for dynamic memory allocation. The +application program may use \verb|glp_malloc| for the same purpose. + +\returns + +The routine \verb|glp_malloc| returns a pointer to the memory block +allocated. To free this block the routine \verb|glp_free| (not the +standard C function \verb|free|!) must be used. + +\subsection{glp\_calloc --- allocate memory block} + +\synopsis + +\begin{verbatim} + void *glp_calloc(int n, int size); +\end{verbatim} + +\description + +The routine \verb|glp_calloc| dynamically allocates a memory block of +\verb|n|$\times$\verb|size| bytes long. Note that: + +1) both parameters \verb|n| and \verb|size| must be positive; + +2) being allocated the memory block contains arbitrary data, that is, +it is {\it not} initialized by binary zeros; + +3) if the block cannot be allocated due to insufficient memory, the +routine prints an error message and abnormally terminates the program. + +This routine is a replacement of the standard C function \verb|calloc| +(with exception that the block is not cleaned) and used by all GLPK +routines for dynamic memory allocation. The application program may use +\verb|glp_calloc| for the same purpose. + +\returns + +The routine \verb|glp_calloc| returns a pointer to the memory block +allocated. To free this block the routine \verb|glp_free| (not the +standard C function \verb|free|!) must be used. + +\subsection{glp\_free --- free memory block} + +\synopsis + +\begin{verbatim} + void glp_free(void *ptr); +\end{verbatim} + +\description + +The routine \verb|glp_free| deallocates a memory block pointed to by +\verb|ptr|, which was previously allocated by the routine +\verb|glp_malloc| or \verb|glp_calloc|. Note that the pointer +\verb|ptr| must be valid and must not be \verb|NULL|. + +This routine is a replacement of the standard C function \verb|free| +and used by all GLPK routines for dynamic memory allocation. The +application program may use \verb|glp_free| for the same purpose. + +\newpage + +\subsection{glp\_mem\_usage --- get memory usage information} + +\synopsis + +\begin{verbatim} + void glp_mem_usage(int *count, int *cpeak, size_t *total, size_t *tpeak); +\end{verbatim} + +\description + +The routine \verb|glp_mem_usage| reports some information about +utilization of the memory by the routines \verb|glp_malloc|, +\verb|glp_calloc|, and \verb|glp_free|. Information is stored to +locations specified by corresponding parameters (see below). Any +parameter can be specified as \verb|NULL|, in which case corresponding +information is not stored. + +\verb|*count| is the number of currently allocated memory blocks. + +\verb|*cpeak| is the peak value of \verb|*count| reached since the +initialization of the GLPK library environment. + +\verb|*total| is the total amount, in bytes, of currently allocated +memory blocks. + +\verb|*tpeak| is the peak value of \verb|*total| reached since the +initialization of the GLPK library envirionment. + +\para{Example} + +\begin{footnotesize} +\begin{verbatim} +glp_mem_usage(&count, NULL, NULL, NULL); +printf("%d memory block(s) are still allocated\n", count); +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_mem\_limit --- set memory usage limit} + +\synopsis + +\begin{verbatim} + void glp_mem_limit(int limit); +\end{verbatim} + +\description + +The routine \verb|glp_mem_limit| limits the amount of memory available +for dynamic allocation (with the routines \verb|glp_malloc| and +\verb|glp_calloc|) to \verb|limit| megabytes. + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk07.tex b/resources/3rdparty/glpk-4.53/doc/glpk07.tex new file mode 100644 index 000000000..004fe2ec8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk07.tex @@ -0,0 +1,258 @@ +%* glpk07.tex *% + +\chapter{Installing GLPK on Your Computer} +\label{install} + +\section{Downloading the distribution tarball} + +The distribution tarball of the most recent version of the GLPK +package can be found on \url{http://ftp.gnu.org/gnu/glpk/} [via http] +and \url{ftp://ftp.gnu.org/gnu/glpk/} [via FTP]. It can also be found +on one of the FTP mirrors; see \url{http://www.gnu.org/prep/ftp.html}. +Please use a mirror if possible. + +To make sure that the GLPK distribution tarball you have downloaded is +intact you need to download the corresponding `\verb|.sig|' file and +run a command like this: + +\begin{verbatim} + gpg --verify glpk-4.38.tar.gz.sig +\end{verbatim} + +\noindent +If that command fails because you do not have the required public key, +run the following command to import it: + +\begin{verbatim} + gpg --keyserver keys.gnupg.net --recv-keys 5981E818 +\end{verbatim} + +\noindent +and then re-run the previous command. + +\section{Unpacking the distribution tarball} + +The GLPK package (like all other GNU software) is distributed in the +form of packed archive. This is one file named \verb|glpk-X.Y.tar.gz|, +where {\it X} is the major version number and {\it Y} is the minor +version number. + +In order to prepare the distribution for installation you need to copy +the GLPK distribution file to a working subdirectory and then unpack +and unarchive the distribution file with the following command: + +\begin{verbatim} + tar zx < glpk-X.Y.tar +\end{verbatim} + +\newpage + +\section{Configuring the package} + +After unpacking and unarchiving the GLPK distribution you should +configure the package,\linebreak i.e. automatically tune it for your +platform. + +Normally, you should just \verb|cd| to the subdirectory \verb|glpk-X.Y| +and run the configure script, e.g. + +\begin{verbatim} + ./configure +\end{verbatim} + +The `\verb|configure|' shell script attempts to guess correct values +for various system-dependent variables used during compilation. It uses +those values to create a `\verb|Makefile|' in each directory of the +package. It also creates file `\verb|config.h|' containing +platform-dependent definitions. Finally, it creates a shell script +`\verb|config.status|' that you can run in the future to recreate the +current configuration, a file `\verb|config.cache|' that saves the +results of its tests to speed up reconfiguring, and a file +`\verb|config.log|' containing compiler output (useful mainly for +debugging `\verb|configure|'). + +Running `\verb|configure|' takes about a minute. While it is running, +it displays some informational messages that tell you what it +is doing. If you don't want to see these messages, run +`\verb|configure|' with its standard output redirected to +`\verb|dev/null|'; for example, `\verb|./configure > /dev/null|'. + +By default both static and shared versions of the GLPK library will be +compiled. Compilation of the shared librariy can be turned off by +specifying the `\verb|--disable-shared|' option to `\verb|configure|': + +\begin{verbatim} + ./configure --disable-shared +\end{verbatim} + +\noindent +If you encounter problems building the library try using the above +option, because some platforms do not support shared libraries. + +The GLPK package has some optional features listed below. By default +all these features are disabled. To enable a feature the corresponding +option should be passed to the configure script. + +\verb|--with-gmp | Enable using the GNU MP bignum library + +This feature allows the exact simplex solver to use the GNU MP bignum +library. If it is disabled, the exact simplex solver uses the GLPK +bignum module, which provides the same functionality as GNU MP, however, +it is much less efficient. + +For details about the GNU MP bignum library see its web page at +\url{http://gmplib.org/}. + +\verb|--enable-dl | The same as `\verb|--enable-dl=ltdl|' + +\verb|--enable-dl=ltdl | Enable shared library support (GNU) + +\verb|--enable-dl=dlfcn | Enable shared library support (POSIX) + +Currently this feature is only needed to provide dynamic linking to +ODBC and MySQL shared libraries (see below). + +For details about the GNU shared library support see the manual at +\url{http://www.gnu.org/software/libtool/manual/}. + +\verb|--enable-odbc | +Enable using ODBC table driver (\verb|libiodbc|) + +\verb|--enable-odbc=unix | +Enable using ODBC table driver (\verb|libodbc|) + +This feature allows transmitting data between MathProg model objects +and relational databases accessed through ODBC. + +For more details about this feature see the supplement ``Using Data +Tables in the GNU MathProg Modeling Language'' (\verb|doc/tables.pdf|). + +\verb|--enable-mysql | +Enable using MySQL table driver (\verb|libmysql|) + +This feature allows transmitting data between MathProg model objects +and MySQL relational databases. + +For more details about this feature see the supplement ``Using Data +Tables in the GNU MathProg Modeling Language'' (\verb|doc/tables.pdf|). + +\section{Compiling the package} + +Normally, you can compile (build) the package by typing the command: + +\begin{verbatim} + make +\end{verbatim} + +\noindent +It reads `\verb|Makefile|' generated by `\verb|configure|' and performs +all necessary jobs. + +If you want, you can override the `\verb|make|' variables \verb|CFLAGS| +and \verb|LDFLAGS| like this: + +\begin{verbatim} + make CFLAGS=-O2 LDFLAGS=-s +\end{verbatim} + +To compile the package in a different directory from the one containing +the source code, you must use a version of `\verb|make|' that supports +`\verb|VPATH|' variable, such as GNU `\verb|make|'. `\verb|cd|' to the +directory where you want the object files and executables to go and run +the `\verb|configure|' script. `\verb|configure|' automatically checks +for the source code in the directory that `\verb|configure|' is in and +in `\verb|..|'. If for some reason `\verb|configure|' is not in the +source code directory that you are configuring, then it will report +that it can't find the source code. In that case, run `\verb|configure|' +with the option `\verb|--srcdir=DIR|', where \verb|DIR| is the +directory that contains the source code. + +Some systems require unusual options for compilation or linking that +the `\verb|configure|' script does not know about. You can give +`\verb|configure|' initial values for variables by setting them in the +environment. Using a Bourne-compatible shell, you can do that on the +command line like this: + +\begin{verbatim} + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure +\end{verbatim} + +\noindent +Or on systems that have the `\verb|env|' program, you can do it like +this: + +\begin{verbatim} + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure +\end{verbatim} + +Here are the `\verb|make|' variables that you might want to override +with environment variables when running `\verb|configure|'. + +For these variables, any value given in the environment overrides the +value that `\verb|configure|' would choose: + +\verb|CC | C compiler program. The default is `\verb|cc|'. + +\verb|INSTALL | Program used to install files. The default value is +`\verb|install|' if you have it,\\ +\verb| | otherwise `\verb|cp|'. + +For these variables, any value given in the environment is added to the +value that `\verb|configure|' chooses: + +\verb|DEFS | Configuration options, in the form +`\verb|-Dfoo -Dbar| \dots'. + +\verb|LIBS | Libraries to link with, in the form +`\verb|-lfoo -lbar| \dots'. + +\section{Checking the package} + +To check the package, i.e. to run some tests included in the package, +you can use the following command: + +\begin{verbatim} + make check +\end{verbatim} + +\section{Installing the package} + +Normally, to install the GLPK package you should type the following +command: + +\begin{verbatim} + make install +\end{verbatim} + +\noindent +By default, `\verb|make install|' will install the package's files in +`\verb|usr/local/bin|', `\verb|usr/local/lib|', etc. You can specify an +installation prefix other than `\verb|/usr/local|' by giving +`\verb|configure|' the option `\verb|--prefix=PATH|'. Alternately, you +can do so by consistently giving a value for the `\verb|prefix|' +variable when you run `\verb|make|', e.g. + +\begin{verbatim} + make prefix=/usr/gnu + make prefix=/usr/gnu install +\end{verbatim} + +After installing you can remove the program binaries and object files +from the source directory by typing `\verb|make clean|'. To remove all +files that `\verb|configure|' created (`\verb|Makefile|', +`\verb|config.status|', etc.), just type `\verb|make distclean|'. + +The file `\verb|configure.ac|' is used to create `\verb|configure|' by +a program called `\verb|autoconf|'. You only need it if you want to +remake `\verb|configure|' using a newer version of `\verb|autoconf|'. + +\section{Uninstalling the package} + +To uninstall the GLPK package, i.e. to remove all the package's files +from the system places, you can use the following command: + +\begin{verbatim} + make uninstall +\end{verbatim} + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk08.tex b/resources/3rdparty/glpk-4.53/doc/glpk08.tex new file mode 100644 index 000000000..e56a8e892 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk08.tex @@ -0,0 +1,738 @@ +%* glpk08.tex *% + +\chapter{MPS Format} +\label{champs} + +\section{Fixed MPS Format} +\label{secmps} + +The MPS format\footnote{The MPS format was developed in 1960's by IBM +as input format for their mathematical programming system MPS/360. +Today the MPS format is a most widely used format understood by most +mathematical programming packages. This appendix describes only the +features of the MPS format, which are implemented in the GLPK package.} +is intended for coding LP/MIP problem data. This format assumes the +formulation of LP/MIP problem (1.1)---(1.3) (see Section \ref{seclp}, +page \pageref{seclp}). + +{\it MPS file} is a text file, which contains two types of +cards\footnote{In 1960's MPS file was a deck of 80-column punched +cards, so the author decided to keep the word ``card'', which may be +understood as ``line of text file''.}: indicator cards and data cards. + +Indicator cards determine a kind of succeeding data. Each indicator +card has one word in uppercase letters beginning in column 1. + +Data cards contain problem data. Each data card is divided into six +fixed fields: + +\begin{center} +\begin{tabular}{lcccccc} +& Field 1 & Field 2 & Field 3 & Field 4 & Field 5 & Feld 6 \\ +\hline +Columns & 2---3 & 5---12 & 15---22 & 25---36 & 40---47 & 50---61 \\ +Contents & Code & Name & Name & Number & Name & Number \\ +\end{tabular} +\end{center} + +On a particular data card some fields may be optional. + +Names are used to identify rows, columns, and some vectors (see below). + +Aligning the indicator code in the field 1 to the left margin is +optional. + +All names specified in the fields 2, 3, and 5 should contain from 1 up +to 8 arbitrary characters (except control characters). If a name is +placed in the field 3 or 5, its first character should not be the dollar +sign `\verb|$|'. If a name contains spaces, the spaces are ignored. + +All numerical values in the fields 4 and 6 should be coded in the form +$sxx$\verb|E|$syy$, where $s$ is the plus `\verb|+|' or the minus +`\verb|-|' sign, $xx$ is a real number with optional decimal point, +$yy$ is an integer decimal exponent. Any number should contain up to 12 +characters. If the sign $s$ is omitted, the plus sign is assumed. The +exponent part is optional. If a number contains spaces, the spaces are +ignored. + +\newpage + +If a card has the asterisk `\verb|*|' in the column 1, this card is +considered as a comment and ignored. Besides, if the first character in +the field 3 or 5 is the dollar sign `\verb|$|', all characters from the +dollar sign to the end of card are considered as a comment and ignored. + +MPS file should contain cards in the following order: + +\vspace*{-8pt} + +\begin{itemize} +\item NAME indicator card; + +\item ROWS indicator card; + +\item data cards specifying rows (constraints); + +\item COLUMNS indicator card; + +\item data cards specifying columns (structural variables) and +constraint coefficients; + +\item RHS indicator card; + +\item data cards specifying right-hand sides of constraints; + +\item RANGES indicator card; + +\item data cards specifying ranges for double-bounded constraints; + +\item BOUNDS indicator card; + +\item data cards specifying types and bounds of structural +variables; + +\item ENDATA indicator card. +\end{itemize} + +\vspace*{-8pt} + +{\it Section} is a group of cards consisting of an indicator card and +data cards succeeding this indicator card. For example, the ROWS section +consists of the ROWS indicator card and data cards specifying rows. + +The sections RHS, RANGES, and BOUNDS are optional and may be omitted. + +\section{Free MPS Format} + +{\it Free MPS format} is an improved version of the standard (fixed) +MPS format described above.\footnote{This format was developed in the +beginning of 1990's by IBM as an alternative to the standard fixed MPS +format for Optimization Subroutine Library (OSL).} Note that all +changes in free MPS format concern only the coding of data while the +structure of data is the same for both fixed and free versions of the +MPS format. + +In free MPS format indicator and data records\footnote{{\it Record} in +free MPS format has the same meaning as {\it card} in fixed MPS format.} +may have arbitrary length not limited to 80 characters. Fields of data +records have no predefined positions, i.e. the fields may begin in any +position, except position 1, which must be blank, and must be separated +from each other by one or more blanks. However, the fields must appear +in the same order as in fixed MPS format. + +\newpage + +Symbolic names in fields 2, 3, and 5 may be longer than 8 +characters\footnote{GLPK allows symbolic names having up to 255 +characters.} and must not contain embedded blanks. + +Numeric values in fields 4 and 6 are limited to 12 characters and must +not contain embedded blanks. + +Only six fields on each data record are used. Any other fields are +ignored. + +If the first character of any field (not necessarily fields 3 and 5) +is the dollar sign (\$), all characters from the dollar sign to the end +of record are considered as a comment and ignored. + +\section{NAME indicator card} + +The NAME indicator card should be the first card in the MPS file +(except optional comment cards, which may precede the NAME card). This +card should contain the word \verb|NAME| in the columns 1---4 and the +problem name in the field 3. The problem name is optional and may be +omitted. + +\section{ROWS section} +\label{secrows} + +The ROWS section should start with the indicator card, which contains +the word \verb|ROWS| in the columns 1---4. + +Each data card in the ROWS section specifies one row (constraint) of +the problem. All these data cards have the following format. + +`\verb|N|' in the field 1 means that the row is free (unbounded): +$$-\infty < x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} +< +\infty;$$ + +`\verb|L|' in the field 1 means that the row is of ``less than or equal +to'' type: +$$-\infty < x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} +\leq b_i;$$ + +`\verb|G|' in the field 1 means that the row is of ``greater than or +equal to'' type: +$$b_i \leq x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} +< +\infty;$$ + +`\verb|E|' in the field 1 means that the row is of ``equal to'' type: +$$x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} \leq +b_i,$$ +where $b_i$ is a right-hand side. Note that each constraint has a +corresponding implictly defined auxiliary variable ($x_i$ above), whose +value is a value of the corresponding linear form, therefore row bounds +can be considered as bounds of such auxiliary variable. + +The filed 2 specifies a row name (which is considered as the name of +the corresponding auxiliary variable). + +\newpage + +The fields 3, 4, 5, and 6 are not used and should be empty. + +Numerical values of all non-zero right-hand sides $b_i$ should be +specified in the RHS section (see below). All double-bounded (ranged) +constraints should be specified in the RANGES section (see below). + +\section{COLUMNS section} + +The COLUMNS section should start with the indicator card, which +contains the word \verb|COLUMNS| in the columns 1---7. + +Each data card in the COLUMNS section specifies one or two constraint +coefficients $a_{ij}$ and also introduces names of columns, i.e. names +of structural variables. All these data cards have the following +format. + +The field 1 is not used and should be empty. + +The field 2 specifies a column name. If this field is empty, the column +name from the immediately preceeding data card is assumed. + +The field 3 specifies a row name defined in the ROWS section. + +The field 4 specifies a numerical value of the constraint coefficient +$a_{ij}$, which is placed in the corresponding row and column. + +The fields 5 and 6 are optional. If they are used, they should contain +a second pair ``row name---constraint coefficient'' for the same column. + +Elements of the constraint matrix (i.e. constraint coefficients) should +be enumerated in the column wise manner: all elements for the current +column should be specified before elements for the next column. However, +the order of rows in the COLUMNS section may differ from the order of +rows in the ROWS section. + +Constraint coefficients not specified in the COLUMNS section are +considered as zeros. Therefore zero coefficients may be omitted, +although it is allowed to explicitly specify them. + +\section{RHS section} + +The RHS section should start with the indicator card, which contains the +word \verb|RHS| in the columns 1---3. + +Each data card in the RHS section specifies one or two right-hand sides +$b_i$ (see Section \ref{secrows}, page \pageref{secrows}). All these +data cards have the following format. + +The field 1 is not used and should be empty. + +The field 2 specifies a name of the right-hand side (RHS) +vector\footnote{This feature allows the user to specify several RHS +vectors in the same MPS file. However, before solving the problem a +particular RHS vector should be chosen.}. If this field is empty, the +RHS vector name from the immediately preceeding data card is assumed. + +\newpage + +The field 3 specifies a row name defined in the ROWS section. + +The field 4 specifies a right-hand side $b_i$ for the row, whose name is +specified in the field 3. Depending on the row type $b_i$ is a lower +bound (for the row of \verb|G| type), an upper bound (for the row of +\verb|L| type), or a fixed value (for the row of \verb|E| +type).\footnote{If the row is of {\tt N} type, $b_i$ is considered as +a constant term of the corresponding linear form. Should note, however, +this convention is non-standard.} + +The fields 5 and 6 are optional. If they are used, they should contain +a second pair ``row name---right-hand side'' for the same RHS vector. + +All right-hand sides for the current RHS vector should be specified +before right-hand sides for the next RHS vector. However, the order of +rows in the RHS section may differ from the order of rows in the ROWS +section. + +Right-hand sides not specified in the RHS section are considered as +zeros. Therefore zero right-hand sides may be omitted, although it is +allowed to explicitly specify them. + +\section{RANGES section} + +The RANGES section should start with the indicator card, which contains +the word \verb|RANGES| in the columns 1---6. + +Each data card in the RANGES section specifies one or two ranges for +double-side constraints, i.e. for constraints that are of the types +\verb|L| and \verb|G| at the same time: +$$l_i \leq x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} +\leq u_i,$$ +where $l_i$ is a lower bound, $u_i$ is an upper bound. All these data +cards have the following format. + +The field 1 is not used and should be empty. + +The field 2 specifies a name of the range vector\footnote{This feature +allows the user to specify several range vectors in the same MPS file. +However, before solving the problem a particular range vector should be +chosen.}. If this field is empty, the range vector name from the +immediately preceeding data card is assumed. + +The field 3 specifies a row name defined in the ROWS section. + +The field 4 specifies a range value $r_i$ (see the table below) for the +row, whose name is specified in the field 3. + +The fields 5 and 6 are optional. If they are used, they should contain +a second pair ``row name---range value'' for the same range vector. + +All range values for the current range vector should be specified before +range values for the next range vector. However, the order of rows in +the RANGES section may differ from the order of rows in the ROWS +section. + +For each double-side constraint specified in the RANGES section its +lower and upper bounds are determined as follows: + +\newpage + +\begin{center} +\begin{tabular}{cccc} +Row type & Sign of $r_i$ & Lower bound & Upper bound \\ +\hline +{\tt G} & $+$ or $-$ & $b_i$ & $b_i + |r_i|$ \\ +{\tt L} & $+$ or $-$ & $b_i - |r_i|$ & $b_i$ \\ +{\tt E} & $+$ & $b_i$ & $b_i + |r_i|$ \\ +{\tt E} & $-$ & $b_i - |r_i|$ & $b_i$ \\ +\end{tabular} +\end{center} + +\noindent +where $b_i$ is a right-hand side specified in the RHS section (if $b_i$ +is not specified, it is considered as zero), $r_i$ is a range value +specified in the RANGES section. + +\section{BOUNDS section} +\label{secbounds} + +The BOUNDS section should start with the indicator card, which contains +the word \verb|BOUNDS| in the columns 1---6. + +Each data card in the BOUNDS section specifies one (lower or upper) +bound for one structural variable (column). All these data cards have +the following format. + +The indicator in the field 1 specifies the bound type: + +\verb|LO| --- lower bound; + +\verb|UP| --- upper bound; + +\verb|FX| --- fixed variable (lower and upper bounds are equal); + +\verb|FR| --- free variable (no bounds); + +\verb|MI| --- no lower bound (lower bound is ``minus infinity''); + +\verb|PL| --- no upper bound (upper bound is ``plus infinity''). + +The field 2 specifies a name of the bound vector\footnote{This feature +allows the user to specify several bound vectors in the same MPS file. +However, before solving the problem a particular bound vector should be +chosen.}. If this field is empty, the bound vector name from the +immediately preceeding data card is assumed. + +The field 3 specifies a column name defined in the COLUMNS section. + +The field 4 specifies a bound value. If the bound type in the field 1 +differs from \verb|LO|, \verb|UP|, and \verb|FX|, the value in the field +4 is ignored and may be omitted. + +The fields 5 and 6 are not used and should be empty. + +All bound values for the current bound vector should be specified before +bound values for the next bound vector. However, the order of columns in +the BOUNDS section may differ from the order of columns in the COLUMNS +section. Specification of a lower bound should precede specification of +an upper bound for the same column (if both the lower and upper bounds +are explicitly specified). + +By default, all columns (structural variables) are non-negative, i.e. +have zero lower bound and no upper bound. Lower ($l_j$) and upper +($u_j$) bounds of some column (structural variable $x_j$) are set in the +following way, where $s_j$ is a corresponding bound value explicitly +specified in the BOUNDS section: + +\newpage + +\verb|LO| sets $l_j$ to $s_j$; + +\verb|UP| sets $u_j$ to $s_j$; + +\verb|FX| sets both $l_j$ and $u_j$ to $s_j$; + +\verb|FR| sets $l_j$ to $-\infty$ and $u_j$ to $+\infty$; + +\verb|MI| sets $l_j$ to $-\infty$; + +\verb|PL| sets $u_j$ to $+\infty$. + +\section{ENDATA indicator card} + +The ENDATA indicator card should be the last card of MPS file (except +optional comment cards, which may follow the ENDATA card). This card +should contain the word \verb|ENDATA| in the columns 1---6. + +\section{Specifying objective function} + +It is impossible to explicitly specify the objective function and +optimization direction in the MPS file. However, the following implicit +rule is used by default: the first row of \verb|N| type is considered +as a row of the objective function (i.e. the objective function is the +corresponding auxiliary variable), which should be {\it minimized}. + +GLPK also allows specifying a constant term of the objective function +as a right-hand side of the corresponding row in the RHS section. + +\section{Example of MPS file} +\label{secmpsex} + +To illustrate what the MPS format is, consider the following example of +LP problem: + +\def\arraystretch{1.2} + +\noindent\hspace{.5in}minimize +$$ +value = .03\ bin_1 + .08\ bin_2 + .17\ bin_3 + .12\ bin_4 + .15\ bin_5 ++ .21\ al + .38\ si +$$ +\noindent\hspace{.5in}subject to linear constraints +$$ +\begin{array}{@{}l@{\:}l@{}} +yield &= \ \ \ \ \;bin_1 + \ \ \ \ \;bin_2 + \ \ \ \ \;bin_3 + + \ \ \ \ \;bin_4 + \ \ \ \ \;bin_5 + \ \ \ \ \;al + + \ \ \ \ \;si \\ +FE &= .15\ bin_1 + .04\ bin_2 + .02\ bin_3 + .04\ bin_4 + .02\ bin_5 + + .01\ al + .03\ si \\ +CU &= .03\ bin_1 + .05\ bin_2 + .08\ bin_3 + .02\ bin_4 + .06\ bin_5 + + .01\ al \\ +MN &= .02\ bin_1 + .04\ bin_2 + .01\ bin_3 + .02\ bin_4 + .02\ bin_5 + \\ +MG &= .02\ bin_1 + .03\ bin_2 +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ + .01\ bin_5 \\ +AL &= .70\ bin_1 + .75\ bin_2 + .80\ bin_3 + .75\ bin_4 + .80\ bin_5 + + .97\ al \\ +SI &= .02\ bin_1 + .06\ bin_2 + .08\ bin_3 + .12\ bin_4 + .02\ bin_5 + + .01\ al + .97\ si \\ +\end{array} +$$ + +\newpage + +\noindent\hspace{.5in}and bounds of (auxiliary and structural) +variables +$$ +\begin{array}{r@{\ }l@{\ }l@{\ }l@{\ }rcr@{\ }l@{\ }l@{\ }l@{\ }r} +&&yield&=&2000&&0&\leq&bin_1&\leq&200\\ +-\infty&<&FE&\leq&60&&0&\leq&bin_2&\leq&2500\\ +-\infty&<&CU&\leq&100&&400&\leq&bin_3&\leq&800\\ +-\infty&<&MN&\leq&40&&100&\leq&bin_4&\leq&700\\ +-\infty&<&MG&\leq&30&&0&\leq&bin_5&\leq&1500\\ +1500&\leq&AL&<&+\infty&&0&\leq&al&<&+\infty\\ +250&\leq&SI&\leq&300&&0&\leq&si&<&+\infty\\ +\end{array} +$$ + +\def\arraystretch{1} + +A complete MPS file which specifies data for this example is shown +below (the first two comment lines show card positions). + +\bigskip + +\begin{footnotesize} +\begin{verbatim} +*000000001111111111222222222233333333334444444444555555555566 +*234567890123456789012345678901234567890123456789012345678901 +NAME PLAN +ROWS + N VALUE + E YIELD + L FE + L CU + L MN + L MG + G AL + L SI +COLUMNS + BIN1 VALUE .03000 YIELD 1.00000 + FE .15000 CU .03000 + MN .02000 MG .02000 + AL .70000 SI .02000 + BIN2 VALUE .08000 YIELD 1.00000 + FE .04000 CU .05000 + MN .04000 MG .03000 + AL .75000 SI .06000 + BIN3 VALUE .17000 YIELD 1.00000 + FE .02000 CU .08000 + MN .01000 AL .80000 + SI .08000 + BIN4 VALUE .12000 YIELD 1.00000 + FE .04000 CU .02000 + MN .02000 AL .75000 + SI .12000 + BIN5 VALUE .15000 YIELD 1.00000 + FE .02000 CU .06000 + MN .02000 MG .01000 + AL .80000 SI .02000 + ALUM VALUE .21000 YIELD 1.00000 + FE .01000 CU .01000 + AL .97000 SI .01000 + SILICON VALUE .38000 YIELD 1.00000 + FE .03000 SI .97000 +RHS + RHS1 YIELD 2000.00000 FE 60.00000 + CU 100.00000 MN 40.00000 + SI 300.00000 + MG 30.00000 AL 1500.00000 +RANGES + RNG1 SI 50.00000 +BOUNDS + UP BND1 BIN1 200.00000 + UP BIN2 2500.00000 + LO BIN3 400.00000 + UP BIN3 800.00000 + LO BIN4 100.00000 + UP BIN4 700.00000 + UP BIN5 1500.00000 +ENDATA +\end{verbatim} +\end{footnotesize} + +\vspace*{-6pt} + +\section{MIP features} + +\vspace*{-4pt} + +The MPS format provides two ways for introducing integer variables into +the problem. + +The first way is most general and based on using special marker cards +INTORG and INTEND. These marker cards are placed in the COLUMNS section. +The INTORG card indicates the start of a group of integer variables +(columns), and the card INTEND indicates the end of the group. The MPS +file may contain arbitrary number of the marker cards. + +The marker cards have the same format as the data cards (see Section +\ref{secmps}, page \pageref{secmps}). + +The fields 1, 2, and 6 are not used and should be empty. + +The field 2 should contain a marker name. This name may be arbitrary. + +The field 3 should contain the word \verb|'MARKER'| (including +apostrophes). + +The field 5 should contain either the word \verb|'INTORG'| (including +apostrophes) for the marker card, which begins a group of integer +columns, or the word \verb|'INTEND'| (including apostrophes) for the +marker card, which ends the group. + +The second way is less general but more convenient in some cases. It +allows the user declaring integer columns using three additional types +of bounds, which are specified in the field 1 of data cards in the +BOUNDS section (see Section \ref{secbounds}, page \pageref{secbounds}): + +\verb|LI| --- lower integer. This bound type specifies that the +corresponding column (structural variable), whose name is specified in +field 3, is of integer kind. In this case an lower bound of the +column should be specified in field 4 (like in the case of \verb|LO| +bound type). + +\verb|UI| --- upper integer. This bound type specifies that the +corresponding column (structural variable), whose name is specified in +field 3, is of integer kind. In this case an upper bound of the +column should be specified in field 4 (like in the case of \verb|UP| +bound type). + +\verb|BV| --- binary variable. This bound type specifies that the +corresponding column (structural variable), whose name is specified in +the field 3, is of integer kind, its lower bound is zero, and its upper +bound is one (thus, such variable being of integer kind can have only +two values zero and one). In this case a numeric value specified in the +field 4 is ignored and may be omitted. + +Consider the following example of MIP problem: + +\noindent +\hspace{1in} minimize +$$Z = 3 x_1 + 7 x_2 - x_3 + x4$$ +\hspace{1in} subject to linear constraints +$$ +\begin{array}{c} +\nonumber r_1 = 2 x_1 - \ \ x_2 + \ \ x_3 - \ \;x_4 \\ +\nonumber r_2 = \ \;x_1 - \ \;x_2 - 6 x_3 + 4 x_4 \\ +\nonumber r_3 = 5 x_1 + 3 x_2 \ \ \ \ \ \ \ \ \ + \ \ x_4 \\ +\end{array} +$$ +\hspace{1in} and bound of variables +$$ +\begin{array}{cccl} +\nonumber 1 \leq r_1 < +\infty && 0 \leq x_1 \leq 4 &{\rm(continuous)}\\ +\nonumber 8 \leq r_2 < +\infty && 2 \leq x_2 \leq 5 &{\rm(integer)} \\ +\nonumber 5 \leq r_3 < +\infty && 0 \leq x_3 \leq 1 &{\rm(integer)} \\ +\nonumber && 3 \leq x_4 \leq 8 &{\rm(continuous)}\\ +\end{array} +$$ + +The corresponding MPS file may look like the following: + +\medskip + +\begin{footnotesize} +\begin{verbatim} +NAME SAMP1 +ROWS + N Z + G R1 + G R2 + G R3 +COLUMNS + X1 R1 2.0 R2 1.0 + X1 R3 5.0 Z 3.0 + MARK0001 'MARKER' 'INTORG' + X2 R1 -1.0 R2 -1.0 + X2 R3 3.0 Z 7.0 + X3 R1 1.0 R2 -6.0 + X3 Z -1.0 + MARK0002 'MARKER' 'INTEND' + X4 R1 -1.0 R2 4.0 + X4 R3 1.0 Z 1.0 +RHS + RHS1 R1 1.0 + RHS1 R2 8.0 + RHS1 R3 5.0 +BOUNDS + UP BND1 X1 4.0 + LO BND1 X2 2.0 + UP BND1 X2 5.0 + UP BND1 X3 1.0 + LO BND1 X4 3.0 + UP BND1 X4 8.0 +ENDATA +\end{verbatim} +\end{footnotesize} + +\newpage + +The same example may be coded without INTORG/INTEND markers using the +bound type UI for the variable $x_2$ and the bound type BV for the +variable $x_3$: + +\medskip + +\begin{footnotesize} +\begin{verbatim} +NAME SAMP2 +ROWS + N Z + G R1 + G R2 + G R3 +COLUMNS + X1 R1 2.0 R2 1.0 + X1 R3 5.0 Z 3.0 + X2 R1 -1.0 R2 -1.0 + X2 R3 3.0 Z 7.0 + X3 R1 1.0 R2 -6.0 + X3 Z -1.0 + X4 R1 -1.0 R2 4.0 + X4 R3 1.0 Z 1.0 +RHS + RHS1 R1 1.0 + RHS1 R2 8.0 + RHS1 R3 5.0 +BOUNDS + UP BND1 X1 4.0 + LO BND1 X2 2.0 + UI BND1 X2 5.0 + BV BND1 X3 + LO BND1 X4 3.0 + UP BND1 X4 8.0 +ENDATA +\end{verbatim} +\end{footnotesize} + +%\section{Specifying predefined basis} +%\label{secbas} +% +%The MPS format can also be used to specify some predefined basis for an +%LP problem, i.e. to specify which rows and columns are basic and which +%are non-basic. +% +%The order of a basis file in the MPS format is: +% +%$\bullet$ NAME indicator card; +% +%$\bullet$ data cards (can appear in arbitrary order); +% +%$\bullet$ ENDATA indicator card. +% +%Each data card specifies either a pair "basic column---non-basic row" +%or a non-basic column. All the data cards have the following format. +% +%`\verb|XL|' in the field 1 means that a column, whose name is given in +%the field 2, is basic, and a row, whose name is given in the field 3, +%is non-basic and placed on its lower bound. +% +%`\verb|XU|' in the field 1 means that a column, whose name is given in +%the field 2, is basic, and a row, whose name is given in the field 3, +%is non-basic and placed on its upper bound. +% +%`\verb|LL|' in the field 1 means that a column, whose name is given in +%the field 3, is non-basic and placed on its lower bound. +% +%`\verb|UL|' in the field 1 means that a column, whose name is given in +%the field 3, is non-basic and placed on its upper bound. +% +%The field 2 contains a column name. +% +%If the indicator given in the field 1 is `\verb|XL|' or `\verb|XU|', +%the field 3 contains a row name. Otherwise, if the indicator is +%`\verb|LL|' or `\verb|UL|', the field 3 is not used and should be +%empty. +% +%The field 4, 5, and 6 are not used and should be empty. +% +%A basis file in the MPS format acts like a patch: it doesn't specify +%a basis completely, instead that it is just shows in what a given basis +%differs from the "standard" basis, where all rows (auxiliary variables) +%are assumed to be basic and all columns (structural variables) are +%assumed to be non-basic. +% +%As an example here is a basis file that specifies an optimal basis +%for the example LP problem given in Section \ref{secmpsex}, +%Page \pageref{secmpsex}: +% +%\pagebreak +% +%\begin{verbatim} +%*000000001111111111222222222233333333334444444444555555555566 +%*234567890123456789012345678901234567890123456789012345678901 +%NAME PLAN +% XL BIN2 YIELD +% XL BIN3 FE +% XL BIN4 MN +% XL ALUM AL +% XL SILICON SI +% LL BIN1 +% LL BIN5 +%ENDATA +%\end{verbatim} + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk09.tex b/resources/3rdparty/glpk-4.53/doc/glpk09.tex new file mode 100644 index 000000000..d04865d9d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk09.tex @@ -0,0 +1,424 @@ +%* glpk09.tex *% + +\chapter{CPLEX LP Format} +\label{chacplex} + +\section{Prelude} + +The CPLEX LP format\footnote{The CPLEX LP format was developed in +the end of 1980's by CPLEX Optimization, Inc. as an input format for +the CPLEX linear programming system. Although the CPLEX LP format is +not as widely used as the MPS format, being row-oriented it is more +convenient for coding mathematical programming models by human. This +appendix describes only the features of the CPLEX LP format which are +implemented in the GLPK package.} is intended for coding LP/MIP problem +data. It is a row-oriented format that assumes the formulation of +LP/MIP problem (1.1)---(1.3) (see Section \ref{seclp}, page +\pageref{seclp}). + +CPLEX LP file is a plain text file written in CPLEX LP format. Each +text line of this file may contain up to 255 characters\footnote{GLPK +allows text lines of arbitrary length.}. Blank lines are ignored. +If a line contains the backslash character ($\backslash$), this +character and everything that follows it until the end of line are +considered as a comment and also ignored. + +An LP file is coded by the user using the following elements: keywords, +symbolic names, numeric constants, delimiters, and blanks. + +{\it Keywords} which may be used in the LP file are the following: + +\begin{verbatim} + minimize minimum min + maximize maximum max + subject to such that s.t. st. st + bounds bound + general generals gen + integer integers int + binary binaries bin + infinity inf + free + end +\end{verbatim} + +\noindent +All the keywords are case insensitive. Keywords given above on the same +line are equivalent. Any keyword (except \verb|infinity|, \verb|inf|, +and \verb|free|) being used in the LP file must start at the beginning +of a text line. + +\newpage + +{\it Symbolic names} are used to identify the objective function, +constraints (rows), and variables (columns). All symbolic names are case +sensitive and may contain up to 16 alphanumeric characters\footnote{GLPK +allows symbolic names having up to 255 characters.} (\verb|a|, \dots, +\verb|z|, \verb|A|, \dots, \verb|Z|, \verb|0|, \dots, \verb|9|) as well +as the following characters: + +\begin{verbatim} + ! " # $ % & ( ) / , . ; ? @ _ ` ' { } | ~ +\end{verbatim} + +\noindent +with exception that no symbolic name can begin with a digit or +a period. + +{\it Numeric constants} are used to denote constraint and objective +coefficients, right-hand sides of constraints, and bounds of variables. +They are coded in the standard form $xx$\verb|E|$syy$, where $xx$ is +a real number with optional decimal point, $s$ is a sign (\verb|+| or +\verb|-|), $yy$ is an integer decimal exponent. Numeric constants may +contain arbitrary number of characters. The exponent part is optional. +The letter `\verb|E|' can be coded as `\verb|e|'. If the sign $s$ is +omitted, plus is assumed. + +{\it Delimiters} that may be used in the LP file are the following: + +\begin{verbatim} + : + + + - + < <= =< + > >= => + = +\end{verbatim} + +\noindent +Delimiters given above on the same line are equivalent. The meaning of +the delimiters will be explained below. + +{\it Blanks} are non-significant characters. They may be used freely to +improve readability of the LP file. Besides, blanks should be used to +separate elements from each other if there is no other way to do that +(for example, to separate a keyword from a following symbolic name). + +The order of an LP file is: + +\vspace*{-8pt} + +\begin{itemize} +\item objective function definition; + +\item constraints section; + +\item bounds section; + +\item general, integer, and binary sections (can appear in arbitrary +order); + +\item end keyword. +\end{itemize} + +\vspace*{-8pt} + +These components are discussed in following sections. + +\section{Objective function definition} + +The objective function definition must appear first in the LP file. +It defines the objective function and specifies the optimization +direction. + +The objective function definition has the following form: +$$ +\left\{ +\begin{array}{@{}c@{}} +{\tt minimize} \\ {\tt maximize} +\end{array} +\right\}\ f\ {\tt :}\ s\ c\ x\ s\ c\ x\ \dots\ s\ c\ x +$$ +where $f$ is a symbolic name of the objective function, $s$ is a sign +\verb|+| or \verb|-|, $c$ is a numeric constant that denotes an +objective coefficient, $x$ is a symbolic name of a variable. + +If necessary, the objective function definition can be continued on as +many text lines as desired. + +The name of the objective function is optional and may be omitted +(together with the semicolon that follows it). In this case the default +name `\verb|obj|' is assigned to the objective function. + +If the very first sign $s$ is omitted, the sign plus is assumed. Other +signs cannot be omitted. + +If some objective coefficient $c$ is omitted, 1 is assumed. + +Symbolic names $x$ used to denote variables are recognized by context +and therefore needn't to be declared somewhere else. + +Here is an example of the objective function definition: + +\begin{verbatim} + Minimize Z : - x1 + 2 x2 - 3.5 x3 + 4.997e3x(4) + x5 + x6 + + x7 - .01x8 +\end{verbatim} + +\section{Constraints section} + +The constraints section must follow the objective function definition. +It defines a system of equality and/or inequality constraints. + +The constraint section has the following form: + +\begin{center} +\begin{tabular}{l} +\verb|subject to| \\ +{\it constraint}$_1$ \\ +{\it constraint}$_2$ \\ +\hspace{20pt}\dots \\ +{\it constraint}$_m$ \\ +\end{tabular} +\end{center} + +\noindent where {\it constraint}$_i, i=1,\dots,m,$ is a particular +constraint definition. + +Each constraint definition can be continued on as many text lines as +desired. However, each constraint definition must begin on a new line +except the very first constraint definition which can begin on the same +line as the keyword `\verb|subject to|'. + +Constraint definitions have the following form: +$$ +r\ {\tt:}\ s\ c\ x\ s\ c\ x\ \dots\ s\ c\ x +\ \left\{ +\begin{array}{@{}c@{}} +\mbox{\tt<=} \\ \mbox{\tt>=} \\ \mbox{\tt=} +\end{array} +\right\}\ b +$$ +where $r$ is a symbolic name of a constraint, $s$ is a sign \verb|+| or +\verb|-|, $c$ is a numeric constant that denotes a constraint +coefficient, $x$ is a symbolic name of a variable, $b$ is a right-hand +side. + +The name $r$ of a constraint (which is the name of the corresponding +auxiliary variable) is optional and may be omitted (together with the +semicolon that follows it). In this case the default names like +`\verb|r.nnn|' are assigned to unnamed constraints. + +The linear form $s\ c\ x\ s\ c\ x\ \dots\ s\ c\ x$ in the left-hand +side of a constraint definition has exactly the same meaning as in the +case of the objective function definition (see above). + +After the linear form one of the following delimiters that indicates +the constraint sense must be specified: + +\verb|<=| \ means `less than or equal to' + +\verb|>=| \ means `greater than or equal to' + +\verb|= | \ means `equal to' + +The right hand side $b$ is a numeric constant with an optional sign. + +Here is an example of the constraints section: + +\begin{verbatim} + Subject To + one: y1 + 3 a1 - a2 - b >= 1.5 + y2 + 2 a3 + 2 + a4 - b >= -1.5 + two : y4 + 3 a1 + 4 a5 - b <= +1 + .20y5 + 5 a2 - b = 0 + 1.7 y6 - a6 + 5 a777 - b >= 1 +\end{verbatim} + +Should note that it is impossible to express ranged constraints in the +CPLEX LP format. Each a ranged constraint can be coded as two +constraints with identical linear forms in the left-hand side, one of +which specifies a lower bound and other does an upper one of the +original ranged constraint. Another way is to introduce a slack +double-bounded variable; for example, the +constraint +$$10\leq x+2y+3z\leq 50$$ +can be written as follows: +$$x+2y+3z+t=50,$$ +where $0\leq t\leq 40$ is a slack variable. + +\section{Bounds section} + +The bounds section is intended to define bounds of variables. This +section is optional; if it is specified, it must follow the constraints +section. If the bound section is omitted, all variables are assumed to +be non-negative (i.e. that they have zero lower bound and no upper +bound). + +The bounds section has the following form: + +\begin{center} +\begin{tabular}{l} +\verb|bounds| \\ +{\it definition}$_1$ \\ +{\it definition}$_2$ \\ +\hspace{20pt}\dots \\ +{\it definition}$_p$ \\ +\end{tabular} +\end{center} + +\noindent +where {\it definition}$_k, k=1,\dots,p,$ is a particular bound +definition. + +Each bound definition must begin on a new line\footnote{The GLPK +implementation allows several bound definitions to be placed on the +same line.} except the very first bound definition which can begin on +the same line as the keyword `\verb|bounds|'. + +\newpage + +Syntactically constraint definitions can have one of the following six +forms: + +\begin{center} +\begin{tabular}{ll} +$x$ \verb|>=| $l$ & specifies a lower bound \\ +$l$ \verb|<=| $x$ & specifies a lower bound \\ +$x$ \verb|<=| $u$ & specifies an upper bound \\ +$l$ \verb|<=| $x$ \verb|<=| $u$ &specifies both lower and upper bounds\\ +$x$ \verb|=| $t$ &specifies a fixed value \\ +$x$ \verb|free| &specifies free variable +\end{tabular} +\end{center} + +\noindent +where $x$ is a symbolic name of a variable, $l$ is a numeric constant +with an optional sign that defines a lower bound of the variable or +\verb|-inf| that means that the variable has no lower bound, $u$ is a +numeric constant with an optional sign that defines an upper bound of +the variable or \verb|+inf| that means that the variable has no upper +bound, $t$ is a numeric constant with an optional sign that defines a +fixed value of the variable. + +By default all variables are non-negative, i.e. have zero lower bound +and no upper bound. Therefore definitions of these default bounds can +be omitted in the bounds section. + +Here is an example of the bounds section: + +\begin{verbatim} + Bounds + -inf <= a1 <= 100 + -100 <= a2 + b <= 100 + x2 = +123.456 + x3 free +\end{verbatim} + +\section{General, integer, and binary sections} + +The general, integer, and binary sections are intended to define +some variables as integer or binary. All these sections are optional +and needed only in case of MIP problems. If they are specified, they +must follow the bounds section or, if the latter is omitted, the +constraints section. + +All the general, integer, and binary sections have the same form as +follows: + +\begin{center} +\begin{tabular}{l} +$ +\left\{ +\begin{array}{@{}l@{}} +\verb|general| \\ +\verb|integer| \\ +\verb|binary | \\ +\end{array} +\right\} +$ \\ +\hspace{10pt}$x_1$ \\ +\hspace{10pt}$x_2$ \\ +\hspace{10pt}\dots \\ +\hspace{10pt}$x_q$ \\ +\end{tabular} +\end{center} + +\noindent +where $x_k$ is a symbolic name of variable, $k=1,\dots,q$. + +Each symbolic name must begin on a new line\footnote{The GLPK +implementation allows several symbolic names to be placed on the same +line.} except the very first symbolic name which can begin on the same +line as the keyword `\verb|general|', `\verb|integer|', or +`\verb|binary|'. + +\newpage + +If a variable appears in the general or the integer section, it is +assumed to be general integer variable. If a variable appears in the +binary section, it is assumed to be binary variable, i.e. an integer +variable whose lower bound is zero and upper bound is one. (Note that +if bounds of a variable are specified in the bounds section and then +the variable appears in the binary section, its previously specified +bounds are ignored.) + +Here is an example of the integer section: + +\begin{verbatim} + Integer + z12 + z22 + z35 +\end{verbatim} + +\section{End keyword} + +The keyword `\verb|end|' is intended to end the LP file. It must begin +on a separate line and no other elements (except comments and blank +lines) must follow it. Although this keyword is optional, it is strongly +recommended to include it in the LP file. + +\section{Example of CPLEX LP file} + +Here is a complete example of CPLEX LP file that corresponds to the +example given in Section \ref{secmpsex}, page \pageref{secmpsex}. + +\medskip + +\begin{footnotesize} +\begin{verbatim} +\* plan.lp *\ + +Minimize + value: .03 bin1 + .08 bin2 + .17 bin3 + .12 bin4 + .15 bin5 + + .21 alum + .38 silicon + +Subject To + yield: bin1 + bin2 + bin3 + bin4 + bin5 + + alum + silicon = 2000 + + fe: .15 bin1 + .04 bin2 + .02 bin3 + .04 bin4 + .02 bin5 + + .01 alum + .03 silicon <= 60 + + cu: .03 bin1 + .05 bin2 + .08 bin3 + .02 bin4 + .06 bin5 + + .01 alum <= 100 + + mn: .02 bin1 + .04 bin2 + .01 bin3 + .02 bin4 + .02 bin5 <= 40 + + mg: .02 bin1 + .03 bin2 + .01 bin5 <= 30 + + al: .70 bin1 + .75 bin2 + .80 bin3 + .75 bin4 + .80 bin5 + + .97 alum >= 1500 + + si1: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + + .01 alum + .97 silicon >= 250 + + si2: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + + .01 alum + .97 silicon <= 300 + +Bounds + bin1 <= 200 + bin2 <= 2500 + 400 <= bin3 <= 800 + 100 <= bin4 <= 700 + bin5 <= 1500 + +End + +\* eof *\ +\end{verbatim} +\end{footnotesize} + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk10.tex b/resources/3rdparty/glpk-4.53/doc/glpk10.tex new file mode 100644 index 000000000..3499d04bf --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk10.tex @@ -0,0 +1,166 @@ +%* glpk10.tex *% + +\chapter{Stand-alone LP/MIP Solver} +\label{chaglpsol} + +The GLPK package includes the program \verb|glpsol|, which is a +stand-alone LP/MIP solver. This program can be invoked from the command +line to read LP/MIP problem data in any format supported by GLPK, solve +the problem, and write its solution to an output text file. + +\para{Usage} + +\verb|glpsol| [{\it options\dots}] [{\it filename}] + +\para{General options} + +\begin{verbatim} + --mps read LP/MIP problem in fixed MPS format + --freemps read LP/MIP problem in free MPS format (default) + --lp read LP/MIP problem in CPLEX LP format + --glp read LP/MIP problem in GLPK format + --math read LP/MIP model written in GNU MathProg modeling + language + -m filename, --model filename + read model section and optional data section from + filename (same as --math) + -d filename, --data filename + read data section from filename (for --math only); + if model file also has data section, it is ignored + -y filename, --display filename + send display output to filename (for --math only); + by default the output is sent to terminal + --seed value initialize pseudo-random number generator used in + MathProg model with specified seed (any integer); + if seed value is ?, some random seed will be used + --mincost read min-cost flow problem in DIMACS format + --maxflow read maximum flow problem in DIMACS format + --cnf read CNF-SAT problem in DIMACS format + --simplex use simplex method (default) + --interior use interior point method (LP only) + -r filename, --read filename + read solution from filename rather to find it with + the solver + --min minimization + --max maximization + --scale scale problem (default) + --noscale do not scale problem + -o filename, --output filename + write solution to filename in printable format + -w filename, --write filename + write solution to filename in plain text format + --ranges filename + write sensitivity analysis report to filename in + printable format (simplex only) + --tmlim nnn limit solution time to nnn seconds + --memlim nnn limit available memory to nnn megabytes + --check do not solve problem, check input data only + --name probname change problem name to probname + --wmps filename write problem to filename in fixed MPS format + --wfreemps filename + write problem to filename in free MPS format + --wlp filename write problem to filename in CPLEX LP format + --wglp filename write problem to filename in GLPK format + --wcnf filename write problem to filename in DIMACS CNF-SAT format + --log filename write copy of terminal output to filename + -h, --help display this help information and exit + -v, --version display program version and exit +\end{verbatim} + +\para{LP basis factorization options} + +\begin{verbatim} + --luf LU + Forrest-Tomlin update + (faster, less stable; default) + --cbg LU + Schur complement + Bartels-Golub update + (slower, more stable) + --cgr LU + Schur complement + Givens rotation update + (slower, more stable) +\end{verbatim} + +\para{Options specific to the simplex solver} + +\begin{verbatim} + --primal use primal simplex (default) + --dual use dual simplex + --std use standard initial basis of all slacks + --adv use advanced initial basis (default) + --bib use Bixby's initial basis + --ini filename use as initial basis previously saved with -w + (disables LP presolver) + --steep use steepest edge technique (default) + --nosteep use standard "textbook" pricing + --relax use Harris' two-pass ratio test (default) + --norelax use standard "textbook" ratio test + --presol use presolver (default; assumes --scale and --adv) + --nopresol do not use presolver + --exact use simplex method based on exact arithmetic + --xcheck check final basis using exact arithmetic +\end{verbatim} + +\para{Options specific to the interior-point solver} + +\begin{verbatim} + --nord use natural (original) ordering + --qmd use quotient minimum degree ordering + --amd use approximate minimum degree ordering (default) + --symamd use approximate minimum degree ordering +\end{verbatim} + +\para{Options specific to the MIP solver} + +\begin{verbatim} + --nomip consider all integer variables as continuous + (allows solving MIP as pure LP) + --first branch on first integer variable + --last branch on last integer variable + --mostf branch on most fractional variable + --drtom branch using heuristic by Driebeck and Tomlin + (default) + --pcost branch using hybrid pseudocost heuristic (may be + useful for hard instances) + --dfs backtrack using depth first search + --bfs backtrack using breadth first search + --bestp backtrack using the best projection heuristic + --bestb backtrack using node with best local bound + (default) + --intopt use MIP presolver (default) + --nointopt do not use MIP presolver + --binarize replace general integer variables by binary ones + (assumes --intopt) + --fpump apply feasibility pump heuristic + --proxy [nnn] apply proximity search heuristic (nnn is time limit + in seconds; default is 60) + --gomory generate Gomory's mixed integer cuts + --mir generate MIR (mixed integer rounding) cuts + --cover generate mixed cover cuts + --clique generate clique cuts + --cuts generate all cuts above + --mipgap tol set relative mip gap tolerance to tol + --minisat translate integer feasibility problem to CNF-SAT + and solve it with MiniSat solver +\end{verbatim} + +\newpage + +\begin{verbatim} + --objbnd bound add inequality obj <= bound (minimization) or + obj >= bound (maximization) to integer feasibility + problem (assumes --minisat) +\end{verbatim} + +For description of the MPS format see Appendix \ref{champs}, page +\pageref{champs}. + +For description of the CPLEX LP format see Appendix \ref{chacplex}, +page \pageref{chacplex}. + +For description of the modeling language see the document ``Modeling +Language GNU MathProg: Language Reference'' included in the GLPK +distribution. + +For description of the DIMACS min-cost flow problem format and DIMACS +maximum flow problem format see the document ``GLPK: Graph and Network +Routines'' included in the GLPK distribution. + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk11.tex b/resources/3rdparty/glpk-4.53/doc/glpk11.tex new file mode 100644 index 000000000..d45ab3d29 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk11.tex @@ -0,0 +1,203 @@ +%* glpk11.tex *% + +\chapter{External Software Modules Used In GLPK} + +In the GLPK package there are used some external software modules +listed in this Appendix. Note that these modules are {\it not} part of +GLPK, but are used with GLPK and included in the distribution. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{AMD} + +\noindent +AMD Version 2.2, Copyright {\copyright} 2007 by Timothy A. Davis, +Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. + +\para{Description} + +AMD is a set of routines for pre-ordering sparse matrices prior to +Cholesky or LU factorization, using the approximate minimum degree +ordering algorithm. + +\para{License} + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License +as published by the Free Software Foundation; either version 2.1 of +the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA. + +Permission is hereby granted to use or copy this program under the +terms of the GNU LGPL, provided that the Copyright, this License, +and the Availability of the original version is retained on all +copies. User documentation of any code that uses this code or any +modified version of this code must cite the Copyright, this License, +the Availability note, and ``Used by permission.'' Permission to +modify the code and to distribute modified code is granted, provided +the Copyright, this License, and the Availability note are retained, +and a notice that the code was modified is included. + +AMD is available under alternate licences; contact T. Davis for +details. + +\para{Availability} + +\noindent +\url{http://www.cise.ufl.edu/research/sparse/amd} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{COLAMD/SYMAMD} + +\noindent +COLAMD/SYMAMD Version 2.7, Copyright {\copyright} 1998-2007, Timothy A. +Davis, All Rights Reserved. + +\para{Description} + +colamd: an approximate minimum degree column ordering algorithm, for +LU factorization of symmetric or unsymmetric matrices, QR factorization, +least squares, interior point methods for linear programming problems, +and other related problems. + +symamd: an approximate minimum degree ordering algorithm for Cholesky +factorization of symmetric matrices. + +\para{Authors} + +The authors of the code itself are Stefan I. Larimore and Timothy A. +Davis (davis at cise.ufl.edu), University of Florida. The algorithm +was developed in collaboration with John Gilbert, Xerox PARC, and +Esmond Ng, Oak Ridge National Laboratory. + +\para{License} + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License +as published by the Free Software Foundation; either version 2.1 of +the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA. + +Permission is hereby granted to use or copy this program under the +terms of the GNU LGPL, provided that the Copyright, this License, +and the Availability of the original version is retained on all +copies. User documentation of any code that uses this code or any +modified version of this code must cite the Copyright, this License, +the Availability note, and ``Used by permission.'' Permission to +modify the code and to distribute modified code is granted, provided +the Copyright, this License, and the Availability note are retained, +and a notice that the code was modified is included. + +COLAMD is also available under alternate licenses, contact T. Davis for +details. + +\para{Availability} + +\noindent +\url{http://www.cise.ufl.edu/research/sparse/colamd} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{MiniSat} + +\noindent +MiniSat-C v1.14.1, Copyright {\copyright} 2005, Niklas Sorensson. + +\para{Description} + +MiniSat is a minimalistic implementation of a Chaff-like SAT solver +based on the two-literal watch scheme for fast BCP and clause learning +by conflict analysis. + +\para{License} + +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 AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +\para{Availability} + +\noindent +\url{http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{zlib} + +\noindent +zlib version 1.2.5, Copyright {\copyright} 1995--2010 Jean-loup Gailly +and Mark Adler. + +\para{Description} + +zlib is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by +RFCs (Request for Comments) 1950 to 1952 in the files +\verb|rfc1950.txt| (zlib format), \verb|rfc1951.txt| (deflate format) +and \verb|rfc1952.txt| (gzip format). + +\para{License} + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would + be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + +\hfill Jean-loup Gailly + +\hfill Mark Adler + +\para{Availability} + +\noindent +\url{http://www.zlib.net/} + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/glpk12.tex b/resources/3rdparty/glpk-4.53/doc/glpk12.tex new file mode 100644 index 000000000..2c2b1b7a6 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/glpk12.tex @@ -0,0 +1,707 @@ +%* glpk12.tex *% + +\begin{footnotesize} + +\chapter*{\sf\bfseries GNU General Public License} +\addcontentsline{toc}{chapter}{GNU General Public License} + +\begin{center} +{\bf Version 3, 29 June 2007} +\end{center} + +\begin{quotation} +\noindent +Copyright {\copyright} 2007 Free Software Foundation, Inc. +\verb|<http://fsf.org/>| +\end{quotation} + +\begin{quotation} +\noindent +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +\end{quotation} + +\section*{Preamble} + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + +\section*{TERMS AND CONDITIONS} + +\subsubsection*{0. Definitions.} + + ``This License'' refers to version 3 of the GNU General Public +License. + + ``Copyright'' also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + + ``The Program'' refers to any copyrightable work licensed under this +License. Each licensee is addressed as ``you''. ``Licensees'' and +``recipients'' may be individuals or organizations. + + To ``modify'' a work means to copy from or adapt all or part of the +work in a fashion requiring copyright permission, other than the making +of an exact copy. The resulting work is called a ``modified version'' +of the earlier work or a work ``based on'' the earlier work. + + A ``covered work'' means either the unmodified Program or a work based +on the Program. + + To ``propagate'' a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To ``convey'' a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays ``Appropriate Legal Notices'' +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +\subsubsection*{1. Source Code.} + + The ``source code'' for a work means the preferred form of the work +for making modifications to it. ``Object code'' means any non-source +form of a work. + + A ``Standard Interface'' means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The ``System Libraries'' of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +``Major Component'', in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The ``Corresponding Source'' for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + +\subsubsection*{2. Basic Permissions.} + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +\subsubsection*{3. Protecting Users' Legal Rights From +Anti-Circumvention Law.} + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +\subsubsection*{4. Conveying Verbatim Copies.} + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +\subsubsection*{5. Conveying Modified Source Versions.} + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + ``keep intact all notices''. + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +``aggregate'' if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +\subsubsection*{6. Conveying Non-Source Forms.} + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A ``User Product'' is either (1) a ``consumer product'', which means +any tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of coverage. +For a particular product received by a particular user, ``normally +used'' refers to a typical or common use of that class of product, +regardless of the status of the particular user or of the way in which +the particular user actually uses, or expects or is expected to use, the +product. A product is a consumer product regardless of whether the +product has substantial commercial, industrial or non-consumer uses, +unless such uses represent the only significant mode of use of the +product. + + ``Installation Information'' for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product +from a modified version of its Corresponding Source. The information +must suffice to ensure that the continued functioning of the modified +object code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to +a network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +\subsubsection*{7. Additional Terms.} + + ``Additional permissions'' are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered ``further +restrictions'' within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +\subsubsection*{8. Termination.} + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +\subsubsection*{9. Acceptance Not Required for Having Copies.} + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +\subsubsection*{10. Automatic Licensing of Downstream Recipients.} + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An ``entity transaction'' is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +\subsubsection*{11. Patents.} + + A ``contributor'' is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's ``contributor version''. + + A contributor's ``essential patent claims'' are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, ``control'' includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a ``patent license'' is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To ``grant'' such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. ``Knowingly relying'' means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is ``discriminatory'' if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +\subsubsection*{12. No Surrender of Others' Freedom.} + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not convey it at all. For example, if you agree to terms that +obligate you to collect a royalty for further conveying from those to +whom you convey the Program, the only way you could satisfy both those +terms and this License would be to refrain entirely from conveying the +Program. + +\subsubsection*{13. Use with the GNU Affero General Public License.} + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +\subsubsection*{14. Revised Versions of this License.} + + The Free Software Foundation may publish revised and/or new versions +of the GNU General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in +detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License ``or any later version'' applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +\subsubsection*{15. Disclaimer of Warranty.} + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE +OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU +ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +\subsubsection*{16. Limitation of Liability.} + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES +SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE +WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN +ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +\subsubsection*{17. Interpretation of Sections 15 and 16.} + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +\section*{END OF TERMS AND CONDITIONS} + +\newpage + +\section*{How to Apply These Terms to Your New Programs} + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the ``copyright'' line and a pointer to where the full notice is found. + +\begin{verbatim} + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 3 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, see <http://www.gnu.org/licenses/>. +\end{verbatim} + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +\begin{verbatim} + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. +\end{verbatim} + +\noindent +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, your +program's commands might be different; for a GUI interface, you would +use an ``about box''. + + You should also get your employer (if you work as a programmer) or +school, if any, to sign a ``copyright disclaimer'' for the program, if +necessary. For more information on this, and how to apply and follow the +GNU GPL, see \verb|<http://www.gnu.org/licenses/>|. + + The GNU General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use the +GNU Lesser General Public License instead of this License. But first, +please read \verb|<http://www.gnu.org/philosophy/why-not-lgpl.html>|. + +\end{footnotesize} + +%* eof *% diff --git a/resources/3rdparty/glpk-4.53/doc/gmpl.pdf b/resources/3rdparty/glpk-4.53/doc/gmpl.pdf new file mode 100644 index 0000000000000000000000000000000000000000..dfd72fc3c2b688fb7c73aeb09974a7cf5aecb99d GIT binary patch literal 216026 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	Wdan(S&2LrI;@d0;bqLTJ{*70Dt2pStS)1>A~ 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�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 literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/doc/gmpl.tex b/resources/3rdparty/glpk-4.53/doc/gmpl.tex new file mode 100644 index 000000000..4c84fbd20 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/gmpl.tex @@ -0,0 +1,4295 @@ +%* gmpl.tex *% + +%*********************************************************************** +% This code is part of GLPK (GNU Linear Programming Kit). +% +% Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +% 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +% Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +% reserved. E-mail: <mao@gnu.org>. +% +% GLPK 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 3 of the License, or +% (at your option) any later version. +% +% GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +%*********************************************************************** + +\documentclass[11pt]{report} +\usepackage{amssymb} +\usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, +urlcolor=blue]{hyperref} +\usepackage{indentfirst} + +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{8.5in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +\setlength{\itemsep}{\parskip} +\setlength{\parsep}{0pt} +\setlength{\leftmargini}{\parindent} +\renewcommand{\labelitemi}{---} + +\def\para#1{\noindent{\bf#1}} + +\renewcommand\contentsname{\sf\bfseries Contents} +\renewcommand\chaptername{\sf\bfseries Chapter} +\renewcommand\appendixname{\sf\bfseries Appendix} + +\begin{document} + +\thispagestyle{empty} + +\begin{center} + +\vspace*{1.5in} + +\begin{huge} +\sf\bfseries Modeling Language GNU MathProg +\end{huge} + +\vspace{0.5in} + +\begin{LARGE} +\sf Language Reference +\end{LARGE} + +\vspace{0.5in} + +\begin{LARGE} +\sf for GLPK Version 4.50 +\end{LARGE} + +\vspace{0.5in} +\begin{Large} +\sf (DRAFT, May 2013) +\end{Large} + +\end{center} + +\newpage + +\vspace*{1in} + +\vfill + +\noindent +The GLPK package is part of the GNU Project released under the aegis of +GNU. + +\noindent +Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +reserved. + +\noindent +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301, USA. + +\noindent +Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + +\noindent +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that +the entire resulting derived work is distributed under the terms of +a permission notice identical to this one. + +\noindent +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +{\setlength{\parskip}{0pt} +\tableofcontents +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Introduction} + +{\it GNU MathProg} is a modeling language intended for describing +linear mathematical programming models.\footnote{The GNU MathProg +language is a subset of the AMPL language. Its GLPK implementation is +mainly based on the paper: {\it Robert Fourer}, {\it David M. Gay}, and +{\it Brian W. Kernighan}, ``A Modeling Language for Mathematical +Programming.'' {\it Management Science} 36 (1990), pp.~519-54.} + +Model descriptions written in the GNU MathProg language consist of +a set of statements and data blocks constructed by the user from the +language elements described in this document. + +In a process called {\it translation}, a program called the {\it model +translator} analyzes the model description and translates it into +internal data structures, which may be then used either for generating +mathematical programming problem instance or directly by a program +called the {\it solver} to obtain numeric solution of the problem. + +\section{Linear programming problem} +\label{problem} + +In MathProg the linear programming (LP) problem is stated as follows: + +\medskip + +\noindent\hspace{1in}minimize (or maximize) +$$z=c_1x_1+c_2x_2+\dots+c_nx_n+c_0\eqno(1.1)$$ +\noindent\hspace{1in}subject to linear constraints +$$ +\begin{array}{l@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }l} +L_1&\leq&a_{11}x_1&+&a_{12}x_2&+\dots+&a_{1n}x_n&\leq&U_1\\ +L_2&\leq&a_{21}x_1&+&a_{22}x_2&+\dots+&a_{2n}x_n&\leq&U_2\\ +\multicolumn{9}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +L_m&\leq&a_{m1}x_1&+&a_{m2}x_2&+\dots+&a_{mn}x_n&\leq&U_m\\ +\end{array}\eqno(1.2) +$$ +\noindent\hspace{1in}and bounds of variables +$$ +\begin{array}{l@{\ }c@{\ }c@{\ }c@{\ }l} +l_1&\leq&x_1&\leq&u_1\\ +l_2&\leq&x_2&\leq&u_2\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .}\\ +l_n&\leq&x_n&\leq&u_n\\ +\end{array}\eqno(1.3) +$$ + +\newpage + +\noindent +where $x_1$, $x_2$, \dots, $x_n$ are variables; $z$ is the objective +function; $c_1$, $c_2$, \dots, $c_n$ are objective coefficients; $c_0$ +is the constant term (``shift'') of the objective function; $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ are constraint coefficients; $L_1$, $L_2$, +\dots, $L_m$ are lower constraint bounds; $U_1$, $U_2$, \dots, $U_m$ +are upper constraint bounds; $l_1$, $l_2$, \dots, $l_n$ are lower +bounds of variables; $u_1$, $u_2$, \dots, $u_n$ are upper bounds of +variables. + +Bounds of variables and constraint bounds can be finite as well as +infinite. Besides, lower bounds can be equal to corresponding upper +bounds. Thus, the following types of variables and constraints are +allowed: + +\medskip + +{\def\arraystretch{1.4} +\noindent\hspace{54pt} +\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }l@{\hspace*{39.5pt}}l} +$-\infty$&$<$&$x$&$<$&$+\infty$&Free (unbounded) variable\\ +$l$&$\leq$&$x$&$<$&$+\infty$&Variable with lower bound\\ +$-\infty$&$<$&$x$&$\leq$&$u$&Variable with upper bound\\ +$l$&$\leq$&$x$&$\leq$&$u$&Double-bounded variable\\ +$l$&$=$&$x$&=&$u$&Fixed variable\\ +\end{tabular} + +\noindent\hfil +\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }ll} +$-\infty$&$<$&$\sum a_jx_j$&$<$&$+\infty$&Free (unbounded) linear +form\\ +$L$&$\leq$&$\sum a_jx_j$&$<$&$+\infty$&Inequality constraint ``greater +than or equal to''\\ +$-\infty$&$<$&$\sum a_jx_j$&$\leq$&$U$&Inequality constraint ``less +than or equal to''\\ +$L$&$\leq$&$\sum a_jx_j$&$\leq$&$U$&Double-bounded inequality +constraint\\ +$L$&$=$&$\sum a_jx_j$&=&$U$&Equality constraint\\ +\end{tabular} +} + +\medskip + +In addition to pure LP problems MathProg also allows mixed integer +linear programming (MIP) problems, where some or all variables are +restricted to be integer or binary. + +\section{Model objects} + +In MathProg the model is described in terms of sets, parameters, +variables, constraints, and objectives, which are called {\it model +objects}. + +The user introduces particular model objects using the language +statements. Each model object is provided with a symbolic name which +uniquely identifies the object and is intended for referencing +purposes. + +Model objects, including sets, can be multidimensional arrays built +over indexing sets. Formally, $n$-dimensional array $A$ is the mapping: +$$A:\Delta\rightarrow\Xi,\eqno(1.4)$$ +where $\Delta\subseteq S_1\times\dots\times S_n$ is a subset of the +Cartesian product of indexing sets, $\Xi$ is a set of array members. +In MathProg the set $\Delta$ is called the {\it subscript domain}. Its +members are $n$-tuples $(i_1,\dots,i_n)$, where $i_1\in S_1$, \dots, +$i_n\in S_n$. + +If $n=0$, the Cartesian product above has exactly one member (namely, +0-tuple), so it is convenient to think scalar objects as 0-dimensional +arrays having one member. + +\newpage + +The type of array members is determined by the type of corresponding +model object as follows: + +\medskip + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Model object&Array member\\ +\hline +Set&Elemental plain set\\ +Parameter&Number or symbol\\ +Variable&Elemental variable\\ +Constraint&Elemental constraint\\ +Objective&Elemental objective\\ +\end{tabular} + +\medskip + +In order to refer to a particular object member the object should be +provided with {\it subscripts}. For example, if $a$ is a 2-dimensional +parameter defined over $I\times J$, a reference to its particular +member can be written as $a[i,j]$, where $i\in I$ and $j\in J$. It is +understood that scalar objects being 0-dimensional need no subscripts. + +\section{Structure of model description} + +It is sometimes desirable to write a model which, at various points, +may require different data for each problem instance to be solved using +that model. For this reason in MathProg the model description consists +of two parts: the {\it model section} and the {\it data section}. + +The model section is a main part of the model description that contains +declarations of model objects and is common for all problems based on +the corresponding model. + +The data section is an optional part of the model description that +contains data specific for a particular problem instance. + +Depending on what is more convenient the model and data sections can be +placed either in one file or in two separate files. The latter feature +allows having arbitrary number of different data sections to be used +with the same model section. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Coding model description} +\label{coding} + +The model description is coded in a plain text format using ASCII +character set. Characters valid in the model description are the +following: + +\begin{itemize} +\item alphabetic characters:\\ +\verb|A B C D E F G H I J K L M N O P Q R S T U V W X Y Z|\\ +\verb|a b c d e f g h i j k l m n o p q r s t u v w x y z _| +\item numeric characters:\\ +\verb|0 1 2 3 4 5 6 7 8 9| +\item special characters:\\ +\verb?! " # & ' ( ) * + , - . / : ; < = > [ ] ^ { | } ~? +\item white-space characters:\\ +\verb|SP HT CR NL VT FF| +\end{itemize} + +Within string literals and comments any ASCII characters (except +control characters) are valid. + +White-space characters are non-significant. They can be used freely +between lexical units to improve readability of the model description. +They are also used to separate lexical units from each other if there +is no other way to do that. + +Syntactically model description is a sequence of lexical units in the +following categories: + +\begin{itemize} +\item symbolic names; +\item numeric literals; +\item string literals; +\item keywords; +\item delimiters; +\item comments. +\end{itemize} + +The lexical units of the language are discussed below. + +\newpage + +\section{Symbolic names} + +A {\it symbolic name} consists of alphabetic and numeric characters, +the first of which should be alphabetic. All symbolic names are +distinct (case sensitive). + +\para{Examples} + +\begin{verbatim} +alpha123 +This_is_a_name +_P123_abc_321 +\end{verbatim} + +Symbolic names are used to identify model objects (sets, parameters, +variables, constraints, objectives) and dummy indices. + +All symbolic names (except names of dummy indices) should be unique, +i.e. the model description should have no objects with identical names. +Symbolic names of dummy indices should be unique within the scope, +where they are valid. + +\section{Numeric literals} + +A {\it numeric literal} has the form {\it xx}{\tt E}{\it syy}, where +{\it xx} is a number with optional decimal point, {\it s} is the sign +{\tt+} or {\tt-}, {\it yy} is a decimal exponent. The letter {\tt E} is +case insensitive and can be coded as {\tt e}. + +\para{Examples} + +\begin{verbatim} +123 +3.14159 +56.E+5 +.78 +123.456e-7 +\end{verbatim} + +Numeric literals are used to represent numeric quantities. They have +obvious fixed meaning. + +\section{String literals} + +A {\it string literal} is a sequence of arbitrary characters enclosed +either in single quotes or in double quotes. Both these forms are +equivalent. + +If a single quote is part of a string literal enclosed in single +quotes, it should be coded twice. Analogously, if a double quote is +part of a string literal enclosed in double quotes, it should be coded +twice. + +\para{Examples} + +\begin{verbatim} +'This is a string' +"This is another string" +'That''s all' +"""Hello there,"" said the captain." +\end{verbatim} + +String literals are used to represent symbolic quantities. + +\section{Keywords} + +A {\it keyword} is a sequence of alphabetic characters and possibly +some special characters. + +All keywords fall into two categories: {\it reserved keywords}, which +cannot be used as symbolic names, and {\it non-reserved keywords}, +which are recognized by context and therefore can be used as symbolic +names. + +The reserved keywords are the following: + +\noindent\hfil +\begin{tabular}{@{}p{.7in}p{.7in}p{.7in}p{.7in}@{}} +{\tt and}&{\tt else}&{\tt mod}&{\tt union}\\ +{\tt by}&{\tt if}&{\tt not}&{\tt within}\\ +{\tt cross}&{\tt in}&{\tt or}\\ +{\tt diff}&{\tt inter}&{\tt symdiff}\\ +{\tt div}&{\tt less}&{\tt then}\\ +\end{tabular} + +Non-reserved keywords are described in following sections. + +All the keywords have fixed meaning, which will be explained on +discussion of corresponding syntactic constructions, where the keywords +are used. + +\section{Delimiters} + +A {\it delimiter} is either a single special character or a sequence of +two special characters as follows: + +\noindent\hfil +\begin{tabular}{@{}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in} +p{.3in}p{.3in}@{}} +{\tt+}&{\tt**}&{\tt<=}&{\tt>}&{\tt\&\&}&{\tt:}&{\tt|}&{\tt[}& +{\tt>>}\\ +{\tt-}&{\tt\textasciicircum}&{\tt=}&{\tt<>}&{\tt||}&{\tt;}& +{\tt\char126}&{\tt]}&{\tt<-}\\ +{\tt*}&{\tt\&}&{\tt==}&{\tt!=}&{\tt.}&{\tt:=}&{\tt(}&{\tt\{}\\ +{\tt/}&{\tt<}&{\tt>=}&{\tt!}&{\tt,}&{\tt..}&{\tt)}&{\tt\}}\\ +\end{tabular} + +If the delimiter consists of two characters, there should be no spaces +between the characters. + +All the delimiters have fixed meaning, which will be explained on +discussion corresponding syntactic constructions, where the delimiters +are used. + +\section{Comments} + +For documenting purposes the model description can be provided with +{\it comments}, which may have two different forms. The first form is +a {\it single-line comment}, which begins with the character {\tt\#} +and extends until end of line. The second form is a {\it comment +sequence}, which is a sequence of any characters enclosed within +{\tt/*} and {\tt*/}. + +\para{Examples} + +\begin{verbatim} +param n := 10; # This is a comment +/* This is another comment */ +\end{verbatim} + +Comments are ignored by the model translator and can appear anywhere in +the model description, where white-space characters are allowed. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\chapter{Expressions} + +An {\it expression} is a rule for computing a value. In model +description expressions are used as constituents of certain statements. + +In general case expressions consist of operands and operators. + +Depending on the type of the resultant value all expressions fall into +the following categories: + +\vspace*{-8pt} + +\begin{itemize} +\item numeric expressions; +\item symbolic expressions; +\item indexing expressions; +\item set expressions; +\item logical expressions; +\item linear expressions. +\end{itemize} + +\vspace*{-8pt} + +\section{Numeric expressions} + +A {\it numeric expression} is a rule for computing a single numeric +value represented as a floating-point number. + +The primary numeric expression may be a numeric literal, dummy index, +unsubscripted parameter, subscripted parameter, built-in function +reference, iterated numeric expression, conditional numeric expression, +or another numeric expression enclosed in parentheses. + +\para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|1.23 |&(numeric literal)\\ +\verb|j|&(dummy index)\\ +\verb|time|&(unsubscripted parameter)\\ +\verb|a['May 2003',j+1]|&(subscripted parameter)\\ +\verb|abs(b[i,j])|&(function reference)\\ +\end{tabular} + +\newpage + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|sum{i in S diff T} alpha[i] * b[i,j]|&(iterated expression)\\ +\verb|if i in I then 2 * p else q[i+1]|&(conditional expression)\\ +\verb|(b[i,j] + .5 * c)|&(parenthesized expression)\\ +\end{tabular} + +More general numeric expressions containing two or more primary numeric +expressions may be constructed by using certain arithmetic operators. + +\para{Examples} + +\begin{verbatim} +j+1 +2 * a[i-1,j+1] - b[i,j] +sum{j in J} a[i,j] * x[j] + sum{k in K} b[i,k] * x[k] +(if i in I and p >= 1 then 2 * p else q[i+1]) / (a[i,j] + 1.5) +\end{verbatim} + +\subsection{Numeric literals} + +If the primary numeric expression is a numeric literal, the resultant +value is obvious. + +\subsection{Dummy indices} + +If the primary numeric expression is a dummy index, the resultant value +is current value assigned to that dummy index. + +\subsection{Unsubscripted parameters} + +If the primary numeric expression is an unsubscripted parameter (which +should be 0-dimen\-sional), the resultant value is the value of that +parameter. + +\subsection{Subscripted parameters} + +The primary numeric expression, which refers to a subscripted +parameter, has the following syntactic form: +$$ +\mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}} +$$ +where {\it name} is the symbolic name of the parameter, $i_1$, $i_2$, +\dots, $i_n$ are subscripts. + +Each subscript should be a numeric or symbolic expression. The number +of subscripts in the subscript list should be the same as the dimension +of the parameter with which the subscript list is associated. + +Actual values of subscript expressions are used to identify +a particular member of the parameter that determines the resultant +value of the primary expression. + +\newpage + +\subsection{Function references} + +In MathProg there exist the following built-in functions which may be +used in numeric expressions: + +\begin{tabular}{@{}p{112pt}p{328pt}@{}} +{\tt abs(}$x${\tt)}&$|x|$, absolute value of $x$\\ +{\tt atan(}$x${\tt)}&$\arctan x$, principal value of the arc tangent of +$x$ (in radians)\\ +{\tt atan(}$y${\tt,} $x${\tt)}&$\arctan y/x$, principal value of the +arc tangent of $y/x$ (in radians). In this case the signs of both +arguments $y$ and $x$ are used to determine the quadrant of the +resultant value\\ +{\tt card(}$X${\tt)}&$|X|$, cardinality (the number of elements) of +set $X$\\ +{\tt ceil(}$x${\tt)}&$\lceil x\rceil$, smallest integer not less than +$x$ (``ceiling of $x$'')\\ +{\tt cos(}$x${\tt)}&$\cos x$, cosine of $x$ (in radians)\\ +{\tt exp(}$x${\tt)}&$e^x$, base-$e$ exponential of $x$\\ +{\tt floor(}$x${\tt)}&$\lfloor x\rfloor$, largest integer not greater +than $x$ (``floor of $x$'')\\ +{\tt gmtime()}&the number of seconds elapsed since 00:00:00~Jan~1, 1970, +Coordinated Universal Time (for details see Section \ref{gmtime}, +page \pageref{gmtime})\\ +{\tt length(}$s${\tt)}&$|s|$, length of character string $s$\\ +{\tt log(}$x${\tt)}&$\log x$, natural logarithm of $x$\\ +{\tt log10(}$x${\tt)}&$\log_{10}x$, common (decimal) logarithm of $x$\\ +{\tt max(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&the largest +of values $x_1$, $x_2$, \dots, $x_n$\\ +{\tt min(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&the smallest +of values $x_1$, $x_2$, \dots, $x_n$\\ +{\tt round(}$x${\tt)}&rounding $x$ to nearest integer\\ +{\tt round(}$x${\tt,} $n${\tt)}&rounding $x$ to $n$ fractional decimal +digits\\ +{\tt sin(}$x${\tt)}&$\sin x$, sine of $x$ (in radians)\\ +{\tt sqrt(}$x${\tt)}&$\sqrt{x}$, non-negative square root of $x$\\ +{\tt str2time(}$s${\tt,} $f${\tt)}&converting character string $s$ to +calendar time (for details see Section \ref{str2time}, page +\pageref{str2time})\\ +{\tt trunc(}$x${\tt)}&truncating $x$ to nearest integer\\ +{\tt trunc(}$x${\tt,} $n${\tt)}&truncating $x$ to $n$ fractional +decimal digits\\ +{\tt Irand224()}&generating pseudo-random integer uniformly distributed +in $[0,2^{24})$\\ +{\tt Uniform01()}&generating pseudo-random number uniformly distributed +in $[0,1)$\\ +{\tt Uniform(}$a${\tt,} $b${\tt)}&generating pseudo-random number +uniformly distributed in $[a,b)$\\ +{\tt Normal01()}&generating Gaussian pseudo-random variate with +$\mu=0$ and $\sigma=1$\\ +{\tt Normal(}$\mu${\tt,} $\sigma${\tt)}&generating Gaussian +pseudo-random variate with given $\mu$ and $\sigma$\\ +\end{tabular} + +Arguments of all built-in functions, except {\tt card}, {\tt length}, +and {\tt str2time}, should be numeric expressions. The argument of +{\tt card} should be a set expression. The argument of {\tt length} and +both arguments of {\tt str2time} should be symbolic expressions. + +The resultant value of the numeric expression, which is a function +reference, is the result of applying the function to its argument(s). + +Note that each pseudo-random generator function has a latent argument +(i.e. some internal state), which is changed whenever the function has +been applied. Thus, if the function is applied repeatedly even to +identical arguments, due to the side effect different resultant values +are always produced. + +\newpage + +\subsection{Iterated expressions} +\label{itexpr} + +An {\it iterated numeric expression} is a primary numeric expression, +which has the following syntactic form: +$$\mbox{\it iterated-operator indexing-expression integrand}$$ +where {\it iterated-operator} is the symbolic name of the iterated +operator to be performed (see below), {\it indexing-expression} is an +indexing expression which introduces dummy indices and controls +iterating, {\it integrand} is a numeric expression that participates in +the operation. + +In MathProg there exist four iterated operators, which may be used in +numeric expressions: + +{\def\arraystretch{2} +\noindent\hfil +\begin{tabular}{@{}lll@{}} +{\tt sum}&summation&$\displaystyle\sum_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt prod}&production&$\displaystyle\prod_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt min}&minimum&$\displaystyle\min_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt max}&maximum&$\displaystyle\max_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +\end{tabular} +} + +\noindent where $i_1$, \dots, $i_n$ are dummy indices introduced in +the indexing expression, $\Delta$ is the domain, a set of $n$-tuples +specified by the indexing expression which defines particular values +assigned to the dummy indices on performing the iterated operation, +$f(i_1,\dots,i_n)$ is the integrand, a numeric expression whose +resultant value depends on the dummy indices. + +The resultant value of an iterated numeric expression is the result of +applying of the iterated operator to its integrand over all $n$-tuples +contained in the domain. + +\subsection{Conditional expressions} +\label{ifthen} + +A {\it conditional numeric expression} is a primary numeric expression, +which has one of the following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt if} $b$ {\tt then} $x$ {\tt else} $y$}\\ +\mbox{{\tt if} $b$ {\tt then} $x$}\\ +\end{array} +} +$$ +where $b$ is an logical expression, $x$ and $y$ are numeric +expressions. + +The resultant value of the conditional expression depends on the value +of the logical expression that follows the keyword {\tt if}. If it +takes on the value {\it true}, the value of the conditional expression +is the value of the expression that follows the keyword {\tt then}. +Otherwise, if the logical expression takes on the value {\it false}, +the value of the conditional expression is the value of the expression +that follows the keyword {\it else}. If the second, reduced form of the +conditional expression is used and the logical expression takes on the +value {\it false}, the resultant value of the conditional expression is +zero. + +\newpage + +\subsection{Parenthesized expressions} + +Any numeric expression may be enclosed in parentheses that +syntactically makes it a primary numeric expression. + +Parentheses may be used in numeric expressions, as in algebra, to +specify the desired order in which operations are to be performed. +Where parentheses are used, the expression within the parentheses is +evaluated before the resultant value is used. + +The resultant value of the parenthesized expression is the same as the +value of the expression enclosed within parentheses. + +\subsection{Arithmetic operators} + +In MathProg there exist the following arithmetic operators, which may +be used in numeric expressions: + +\begin{tabular}{@{}ll@{}} +{\tt +} $x$&unary plus\\ +{\tt -} $x$&unary minus\\ +$x$ {\tt +} $y$&addition\\ +$x$ {\tt -} $y$&subtraction\\ +$x$ {\tt less} $y$&positive difference (if $x<y$ then 0 else $x-y$)\\ +$x$ {\tt *} $y$&multiplication\\ +$x$ {\tt /} $y$&division\\ +$x$ {\tt div} $y$"ient of exact division\\ +$x$ {\tt mod} $y$&remainder of exact division\\ +$x$ {\tt **} $y$, $x$ {\tt\textasciicircum} $y$&exponentiation (raising +to power)\\ +\end{tabular} + +\noindent where $x$ and $y$ are numeric expressions. + +If the expression includes more than one arithmetic operator, all +operators are performed from left to right according to the hierarchy +of operations (see below) with the only exception that the +exponentiaion operators are performed from right to left. + +The resultant value of the expression, which contains arithmetic +operators, is the result of applying the operators to their operands. + +\subsection{Hierarchy of operations} +\label{hierarchy} + +The following list shows the hierarchy of operations in numeric +expressions: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operation&Hierarchy\\ +\hline +Evaluation of functions ({\tt abs}, {\tt ceil}, etc.)&1st\\ +Exponentiation ({\tt**}, {\tt\textasciicircum})&2nd\\ +Unary plus and minus ({\tt+}, {\tt-})&3rd\\ +Multiplication and division ({\tt*}, {\tt/}, {\tt div}, {\tt mod})&4th\\ +Iterated operations ({\tt sum}, {\tt prod}, {\tt min}, {\tt max})&5th\\ +Addition and subtraction ({\tt+}, {\tt-}, {\tt less})&6th\\ +Conditional evaluation ({\tt if} \dots {\tt then} \dots {\tt else})& +7th\\ +\end{tabular} + +\newpage + +This hierarchy is used to determine which of two consecutive operations +is performed first. If the first operator is higher than or equal to +the second, the first operation is performed. If it is not, the second +operator is compared to the third, etc. When the end of the expression +is reached, all of the remaining operations are performed in the +reverse order. + +\section{Symbolic expressions} + +A {\it symbolic expression} is a rule for computing a single symbolic +value represented as a character string. + +The primary symbolic expression may be a string literal, dummy index, +unsubscripted parameter, subscripted parameter, built-in function +reference, conditional symbolic expression, or another symbolic +expression enclosed in parentheses. + +It is also allowed to use a numeric expression as the primary symbolic +expression, in which case the resultant value of the numeric expression +is automatically converted to the symbolic type. + +\para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|'May 2003'|&(string literal)\\ +\verb|j|&(dummy index)\\ +\verb|p|&(unsubscripted parameter)\\ +\verb|s['abc',j+1]|&(subscripted parameter)\\ +\verb|substr(name[i],k+1,3)|&(function reference)\\ +\verb|if i in I then s[i,j] & "..." else t[i+1]| +& (conditional expression) \\ +\verb|((10 * b[i,j]) & '.bis')|&(parenthesized expression)\\ +\end{tabular} + +More general symbolic expressions containing two or more primary +symbolic expressions may be constructed by using the concatenation +operator. + +\para{Examples} + +\begin{verbatim} +'abc[' & i & ',' & j & ']' +"from " & city[i] " to " & city[j] +\end{verbatim} + +The principles of evaluation of symbolic expressions are completely +analogous to the ones given for numeric expressions (see above). + +\subsection{Function references} + +In MathProg there exist the following built-in functions which may be +used in symbolic expressions: + +\begin{tabular}{@{}p{112pt}p{328pt}@{}} +{\tt substr(}$s${\tt,} $x${\tt)}&substring of $s$ starting from +position $x$\\ +{\tt substr(}$s${\tt,} $x${\tt,} $y${\tt)}&substring of $s$ starting +from position $x$ and having length $y$\\ +{\tt time2str(}$t${\tt,} $f${\tt)}&converting calendar time to +character string (for details see Section \ref{time2str}, page +\pageref{time2str})\\ +\end{tabular} + +The first argument of {\tt substr} should be a symbolic expression +while its second and optional third arguments should be numeric +expressions. + +The first argument of {\tt time2str} should be a numeric expression, +and its second argument should be a symbolic expression. + +The resultant value of the symbolic expression, which is a function +reference, is the result of applying the function to its arguments. + +\subsection{Symbolic operators} + +Currently in MathProg there exists the only symbolic operator: +$$\mbox{\tt s \& t}$$ +where $s$ and $t$ are symbolic expressions. This operator means +concatenation of its two symbolic operands, which are character +strings. + +\subsection{Hierarchy of operations} + +The following list shows the hierarchy of operations in symbolic +expressions: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operation&Hierarchy\\ +\hline +Evaluation of numeric operations&1st-7th\\ +Concatenation ({\tt\&})&8th\\ +Conditional evaluation ({\tt if} \dots {\tt then} \dots {\tt else})& +9th\\ +\end{tabular} + +This hierarchy has the same meaning as was explained above for numeric +expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). + +\section{Indexing expressions and dummy indices} +\label{indexing} + +An {\it indexing expression} is an auxiliary construction, which +specifies a plain set of $n$-tuples and introduces dummy indices. It +has two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt\{} {\it entry}$_1${\tt,} {\it entry}$_2${\tt,} \dots{\tt,} +{\it entry}$_m$ {\tt\}}}\\ +\mbox{{\tt\{} {\it entry}$_1${\tt,} {\it entry}$_2${\tt,} \dots{\tt,} +{\it entry}$_m$ {\tt:} {\it predicate} {\tt\}}}\\ +\end{array} +} +$$ +where {\it entry}{$_1$}, {\it entry}{$_2$}, \dots, {\it entry}{$_m$} +are indexing entries, {\it predicate} is a logical expression that +specifies an optional predicate (logical condition). + +Each {\it indexing entry} in the indexing expression has one of the +following three forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{$i$ {\tt in} $S$}\\ +\mbox{{\tt(}$i_1${\tt,} $i_2${\tt,} \dots{\tt,}$i_n${\tt)} {\tt in} +$S$}\\ +\mbox{$S$}\\ +\end{array} +} +$$ +where $i_1$, $i_2$, \dots, $i_n$ are indices, $S$ is a set expression +(discussed in the next section) that specifies the basic set. + +\newpage + +The number of indices in the indexing entry should be the same as the +dimension of the basic set $S$, i.e. if $S$ consists of 1-tuples, the +first form should be used, and if $S$ consists of $n$-tuples, where +$n>1$, the second form should be used. + +If the first form of the indexing entry is used, the index $i$ can be +a dummy index only (see below). If the second form is used, the indices +$i_1$, $i_2$, \dots, $i_n$ can be either dummy indices or some numeric +or symbolic expressions, where at least one index should be a dummy +index. The third, reduced form of the indexing entry has the same +effect as if there were $i$ (if $S$ is 1-dimensional) or +$i_1$, $i_2$, \dots, $i_n$ (if $S$ is $n$-dimensional) all specified as +dummy indices. + +A {\it dummy index} is an auxiliary model object, which acts like an +individual variable. Values assigned to dummy indices are components of +$n$-tuples from basic sets, i.e. some numeric and symbolic quantities. + +For referencing purposes dummy indices can be provided with symbolic +names. However, unlike other model objects (sets, parameters, etc.) +dummy indices need not be explicitly declared. Each {\it undeclared} +symbolic name being used in the indexing position of an indexing entry +is recognized as the symbolic name of corresponding dummy index. + +Symbolic names of dummy indices are valid only within the scope of the +indexing expression, where the dummy indices were introduced. Beyond +the scope the dummy indices are completely inaccessible, so the same +symbolic names may be used for other purposes, in particular, to +represent dummy indices in other indexing expressions. + +The scope of indexing expression, where implicit declarations of dummy +indices are valid, depends on the context, in which the indexing +expression is used: + +\vspace*{-8pt} + +\begin{itemize} +\item If the indexing expression is used in iterated operator, its +scope extends until the end of the integrand. +\item If the indexing expression is used as a primary set expression, +its scope extends until the end of that indexing expression. +\item If the indexing expression is used to define the subscript domain +in declarations of some model objects, its scope extends until the end +of the corresponding statement. +\end{itemize} + +\vspace*{-8pt} + +The indexing mechanism implemented by means of indexing expressions is +best explained by some examples discussed below. + +Let there be given three sets: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +A=\{4,7,9\},\\ +B=\{(1,Jan),(1,Feb),(2,Mar),(2,Apr),(3,May),(3,Jun)\},\\ +C=\{a,b,c\},\\ +\end{array} +} +$$ +where $A$ and $C$ consist of 1-tuples (singlets), $B$ consists of +2-tuples (doublets). Consider the following indexing expression: +$$\mbox{{\tt\{i in A, (j,k) in B, l in C\}}}$$ +where {\tt i}, {\tt j}, {\tt k}, and {\tt l} are dummy indices. + +\newpage + +Although MathProg is not a procedural language, for any indexing +expression an equivalent algorithmic description can be given. In +particular, the algorithmic description of the indexing expression +above could look like follows: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf for all} $i\in A$ {\bf do}\\ +\hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf do}\\ +\hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ +\hspace{48pt}{\it action};\\ +\end{tabular} + +\noindent where the dummy indices $i$, $j$, $k$, $l$ are consecutively +assigned corresponding components of $n$-tuples from the basic sets $A$, +$B$, $C$, and {\it action} is some action that depends on the context, +where the indexing expression is used. For example, if the action were +printing current values of dummy indices, the printout would look like +follows: + +\noindent\hfil +\begin{tabular}{@{}llll@{}} +$i=4$&$j=1$&$k=Jan$&$l=a$\\ +$i=4$&$j=1$&$k=Jan$&$l=b$\\ +$i=4$&$j=1$&$k=Jan$&$l=c$\\ +$i=4$&$j=1$&$k=Feb$&$l=a$\\ +$i=4$&$j=1$&$k=Feb$&$l=b$\\ +\multicolumn{4}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +$i=9$&$j=3$&$k=Jun$&$l=b$\\ +$i=9$&$j=3$&$k=Jun$&$l=c$\\ +\end{tabular} + +Let the example indexing expression be used in the following iterated +operation: +$$\mbox{{\tt sum\{i in A, (j,k) in B, l in C\} p[i,j,k,l]}}$$ +where {\tt p} is a 4-dimensional numeric parameter or some numeric +expression whose resultant value depends on {\tt i}, {\tt j}, {\tt k}, +and {\tt l}. In this case the action is summation, so the resultant +value of the primary numeric expression is: +$$\sum_{i\in A,(j,k)\in B,l\in C}(p_{ijkl}).$$ + +Now let the example indexing expression be used as a primary set +expression. In this case the action is gathering all 4-tuples +(quadruplets) of the form $(i,j,k,l)$ in one set, so the resultant +value of such operation is simply the Cartesian product of the basic +sets: +$$A\times B\times C=\{(i,j,k,l):i\in A,(j,k)\in B,l\in C\}.$$ +Note that in this case the same indexing expression might be written in +the reduced form: +$$\mbox{{\tt\{A, B, C\}}}$$ +because the dummy indices $i$, $j$, $k$, and $l$ are not referenced and +therefore their symbolic names need not be specified. + +\newpage + +Finally, let the example indexing expression be used as the subscript +domain in the declaration of a 4-dimensional model object, say, +a numeric parameter: +$$\mbox{{\tt param p\{i in A, (j,k) in B, l in C\}} \dots {\tt;}}$$ + +\noindent In this case the action is generating the parameter members, +where each member has the form $p[i,j,k,l]$. + +As was said above, some indices in the second form of indexing entries +may be numeric or symbolic expressions, not only dummy indices. In this +case resultant values of such expressions play role of some logical +conditions to select only that $n$-tuples from the Cartesian product of +basic sets that satisfy these conditions. + +Consider, for example, the following indexing expression: +$$\mbox{{\tt\{i in A, (i-1,k) in B, l in C\}}}$$ +where {\tt i}, {\tt k}, {\tt l} are dummy indices, and {\tt i-1} is +a numeric expression. The algorithmic decsription of this indexing +expression is the following: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf for all} $i\in A$ {\bf do}\\ +\hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf and} $j=i-1$ {\bf do}\\ +\hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ +\hspace{48pt}{\it action};\\ +\end{tabular} + +\noindent Thus, if this indexing expression were used as a primary set +expression, the resultant set would be the following: +$$\{(4,May,a),(4,May,b),(4,May,c),(4,Jun,a),(4,Jun,b),(4,Jun,c)\}.$$ +Should note that in this case the resultant set consists of 3-tuples, +not of 4-tuples, because in the indexing expression there is no dummy +index that corresponds to the first component of 2-tuples from the set +$B$. + +The general rule is: the number of components of $n$-tuples defined by +an indexing expression is the same as the number of dummy indices in +that expression, where the correspondence between dummy indices and +components on $n$-tuples in the resultant set is positional, i.e. the +first dummy index corresponds to the first component, the second dummy +index corresponds to the second component, etc. + +In some cases it is needed to select a subset from the Cartesian +product of some sets. This may be attained by using an optional logical +predicate, which is specified in the indexing expression. + +Consider, for example, the following indexing expression: +$$\mbox{{\tt\{i in A, (j,k) in B, l in C: i <= 5 and k <> 'Mar'\}}}$$ +where the logical expression following the colon is a predicate. The +algorithmic description of this indexing expression is the following: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf for all} $i\in A$ {\bf do}\\ +\hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf do}\\ +\hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ +\hspace{48pt}{\bf if} $i\leq 5$ {\bf and} $k\neq`Mar'$ {\bf then}\\ +\hspace{64pt}{\it action};\\ +\end{tabular} + +\noindent Thus, if this indexing expression were used as a primary set +expression, the resultant set would be the following: +$$\{(4,1,Jan,a),(4,1,Feb,a),(4,2,Apr,a),\dots,(4,3,Jun,c)\}.$$ + +If no predicate is specified in the indexing expression, one, which +takes on the value {\it true}, is assumed. + +\section{Set expressions} + +A {\it set expression} is a rule for computing an elemental set, i.e. +a collection of $n$-tuples, where components of $n$-tuples are numeric +and symbolic quantities. + +The primary set expression may be a literal set, unsubscripted set, +subscripted set, ``arithmetic'' set, indexing expression, iterated set +expression, conditional set expression, or another set expression +enclosed in parentheses. + +\para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|{(123,'aaa'), (i+1,'bbb'), (j-1,'ccc')}| &(literal set)\\ +\verb|I| &(unsubscripted set)\\ +\verb|S[i-1,j+1]| &(subscripted set)\\ +\verb|1..t-1 by 2| &(``arithmetic'' set)\\ +\verb|{t in 1..T, (t+1,j) in S: (t,j) in F}| &(indexing expression)\\ +\verb|setof{i in I, j in J}(i+1,j-1)| &(iterated set expression)\\ +\verb|if i < j then S[i,j] else F diff S[i,j]| &(conditional set +expression)\\ +\verb|(1..10 union 21..30)| &(parenthesized set expression)\\ +\end{tabular} + +More general set expressions containing two or more primary set +expressions may be constructed by using certain set operators. + +\para{Examples} + +\begin{verbatim} +(A union B) inter (I cross J) +1..10 cross (if i < j then {'a', 'b', 'c'} else {'d', 'e', 'f'}) +\end{verbatim} + +\subsection{Literal sets} + +A {\it literal set} is a primary set expression, which has the +following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt\{}$e_1${\tt,} $e_2${\tt,} \dots{\tt,} $e_m${\tt\}}}\\ +\mbox{{\tt\{(}$e_{11}${\tt,} \dots{\tt,} $e_{1n}${\tt),} +{\tt(}$e_{21}${\tt,} \dots{\tt,} $e_{2n}${\tt),} \dots{\tt,} +{\tt(}$e_{m1}${\tt,} \dots{\tt,} $e_{mn}${\tt)\}}}\\ +\end{array} +} +$$ +where $e_1$, \dots, $e_m$, $e_{11}$, \dots, $e_{mn}$ are numeric or +symbolic expressions. + +If the first form is used, the resultant set consists of 1-tuples +(singlets) enumerated within the curly braces. It is allowed to specify +an empty set as {\tt\{\ \}}, which has no 1-tuples. If the second form +is used, the resultant set consists of $n$-tuples enumerated within the +curly braces, where a particular $n$-tuple consists of corresponding +components enumerated within the parentheses. All $n$-tuples should +have the same number of components. + +\subsection{Unsubscripted sets} + +If the primary set expression is an unsubscripted set (which should be +0-dimen\-sional), the resultant set is an elemental set associated with +the corresponding set object. + +\subsection{Subscripted sets} + +The primary set expression, which refers to a subscripted set, has the +following syntactic form: +$$\mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +$i_n${\tt]}}$$ +where {\it name} is the symbolic name of the set object, $i_1$, $i_2$, +\dots, $i_n$ are subscripts. + +Each subscript should be a numeric or symbolic expression. The number +of subscripts in the subscript list should be the same as the dimension +of the set object with which the subscript list is associated. + +Actual values of subscript expressions are used to identify a +particular member of the set object that determines the resultant set. + +\subsection{``Arithmetic'' sets} + +The primary set expression, which is an ``arithmetic'' set, has the +following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{$t_0$ {\tt..} $t_1$ {\tt by} $\delta t$}\\ +\mbox{$t_0$ {\tt..} $t_1$}\\ +\end{array} +} +$$ +where $t_0$, $t_1$, and $\delta t$ are numeric expressions (the value +of $\delta t$ should not be zero). The second form is equivalent to the +first form, where $\delta t=1$. + +If $\delta t>0$, the resultant set is determined as follows: +$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_0\leq t\leq t_1)\}.$$ +Otherwise, if $\delta t<0$, the resultant set is determined as follows: +$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_1\leq t\leq t_0)\}.$$ + +\subsection{Indexing expressions} + +If the primary set expression is an indexing expression, the resultant +set is determined as described above in Section \ref{indexing}, page +\pageref{indexing}. + +\newpage + +\subsection{Iterated expressions} + +An {\it iterated set expression} is a primary set expression, which has +the following syntactic form: +$$\mbox{{\tt setof} {\it indexing-expression} {\it integrand}}$$ +where {\it indexing-expression} is an indexing expression, which +introduces dummy indices and controls iterating, {\it integrand} is +either a single numeric or symbolic expression or a list of numeric and +symbolic expressions separated by commae and enclosed in parentheses. + +If the integrand is a single numeric or symbolic expression, the +resultant set consists of 1-tuples and is determined as follows: +$$\{x:(i_1,\dots,i_n)\in\Delta\},$$ +\noindent where $x$ is a value of the integrand, $i_1$, \dots, $i_n$ +are dummy indices introduced in the indexing expression, $\Delta$ is +the domain, a set of $n$-tuples specified by the indexing expression, +which defines particular values assigned to the dummy indices on +performing the iterated operation. + +If the integrand is a list containing $m$ numeric and symbolic +expressions, the resultant set consists of $m$-tuples and is determined +as follows: +$$\{(x_1,\dots,x_m):(i_1,\dots,i_n)\in\Delta\},$$ +where $x_1$, \dots, $x_m$ are values of the expressions in the +integrand list, $i_1$, \dots, $i_n$ and $\Delta$ have the same meaning +as above. + +\subsection{Conditional expressions} + +A {\it conditional set expression} is a primary set expression that has +the following syntactic form: +$$\mbox{{\tt if} $b$ {\tt then} $X$ {\tt else} $Y$}$$ +where $b$ is an logical expression, $X$ and $Y$ are set expressions, +which should define sets of the same dimension. + +The resultant value of the conditional expression depends on the value +of the logical expression that follows the keyword {\tt if}. If it +takes on the value {\it true}, the resultant set is the value of the +expression that follows the keyword {\tt then}. Otherwise, if the +logical expression takes on the value {\it false}, the resultant set is +the value of the expression that follows the keyword {\tt else}. + +\subsection{Parenthesized expressions} + +Any set expression may be enclosed in parentheses that syntactically +makes it a primary set expression. + +Parentheses may be used in set expressions, as in algebra, to specify +the desired order in which operations are to be performed. Where +parentheses are used, the expression within the parentheses is +evaluated before the resultant value is used. + +The resultant value of the parenthesized expression is the same as the +value of the expression enclosed within parentheses. + +\newpage + +\subsection{Set operators} + +In MathProg there exist the following set operators, which may be used +in set expressions: + +\begin{tabular}{@{}ll@{}} +$X$ {\tt union} $Y$&union $X\cup Y$\\ +$X$ {\tt diff} $Y$&difference $X\backslash Y$\\ +$X$ {\tt symdiff} $Y$&symmetric difference +$X\oplus Y=(X\backslash Y)\cup(Y\backslash X)$\\ +$X$ {\tt inter} $Y$&intersection $X\cap Y$\\ +$X$ {\tt cross} $Y$&cross (Cartesian) product $X\times Y$\\ +\end{tabular} + +\noindent where $X$ and Y are set expressions, which should define sets +of identical dimension (except the Cartesian product). + +If the expression includes more than one set operator, all operators +are performed from left to right according to the hierarchy of +operations (see below). + +The resultant value of the expression, which contains set operators, is +the result of applying the operators to their operands. + +The dimension of the resultant set, i.e. the dimension of $n$-tuples, +of which the resultant set consists of, is the same as the dimension of +the operands, except the Cartesian product, where the dimension of the +resultant set is the sum of the dimensions of its operands. + +\subsection{Hierarchy of operations} + +The following list shows the hierarchy of operations in set +expressions: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operation&Hierarchy\\ +\hline +Evaluation of numeric operations&1st-7th\\ +Evaluation of symbolic operations&8th-9th\\ +Evaluation of iterated or ``arithmetic'' set ({\tt setof}, {\tt..})& +10th\\ +Cartesian product ({\tt cross})&11th\\ +Intersection ({\tt inter})&12th\\ +Union and difference ({\tt union}, {\tt diff}, {\tt symdiff})&13th\\ +Conditional evaluation ({\tt if} \dots {\tt then} \dots {\tt else})& +14th\\ +\end{tabular} + +This hierarchy has the same meaning as was explained above for numeric +expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). + +\newpage + +\section{Logical expressions} + +A {\it logical expression} is a rule for computing a single logical +value, which can be either {\it true} or {\it false}. + +The primary logical expression may be a numeric expression, relational +expression, iterated logical expression, or another logical expression +enclosed in parentheses. + +\para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|i+1| &(numeric expression)\\ +\verb|a[i,j] < 1.5| &(relational expression)\\ +\verb|s[i+1,j-1] <> 'Mar' & year | &(relational expression)\\ +\verb|(i+1,'Jan') not in I cross J| &(relational expression)\\ +\verb|S union T within A[i] inter B[j]| &(relational expression)\\ +\verb|forall{i in I, j in J} a[i,j] < .5 * b[i]| &(iterated logical +expression)\\ +\verb|(a[i,j] < 1.5 or b[i] >= a[i,j])| &(parenthesized logical +expression)\\ +\end{tabular} + +More general logical expressions containing two or more primary logical +expressions may be constructed by using certain logical operators. + +\para{Examples} + +\begin{verbatim} +not (a[i,j] < 1.5 or b[i] >= a[i,j]) and (i,j) in S +(i,j) in S or (i,j) not in T diff U +\end{verbatim} + +\vspace*{-8pt} + +\subsection{Numeric expressions} + +The resultant value of the primary logical expression, which is a +numeric expression, is {\it true}, if the resultant value of the +numeric expression is non-zero. Otherwise the resultant value of the +logical expression is {\it false}. + +\vspace*{-8pt} + +\subsection{Relational operators} + +In MathProg there exist the following relational operators, which may +be used in logical expressions: + +\begin{tabular}{@{}ll@{}} +$x$ {\tt<} $y$&test on $x<y$\\ +$x$ {\tt<=} $y$&test on $x\leq y$\\ +$x$ {\tt=} $y$, $x$ {\tt==} $y$&test on $x=y$\\ +$x$ {\tt>=} $y$&test on $x\geq y$\\ +$x$ {\tt>} $y$&test on $x>y$\\ +$x$ {\tt<>} $y$, $x$ {\tt!=} $y$&test on $x\neq y$\\ +$x$ {\tt in} $Y$&test on $x\in Y$\\ +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt in} $Y$&test on +$(x_1,\dots,x_n)\in Y$\\ +$x$ {\tt not} {\tt in} $Y$, $x$ {\tt!in} $Y$&test on $x\not\in Y$\\ +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt not} {\tt in} $Y$, +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt !in} $Y$&test on +$(x_1,\dots,x_n)\not\in Y$\\ +$X$ {\tt within} $Y$&test on $X\subseteq Y$\\ +$X$ {\tt not} {\tt within} $Y$, $X$ {\tt !within} $Y$&test on +$X\not\subseteq Y$\\ +\end{tabular} + +\noindent where $x$, $x_1$, \dots, $x_n$, $y$ are numeric or symbolic +expressions, $X$ and $Y$ are set expression. + +\newpage + +1. In the operations {\tt in}, {\tt not in}, and {\tt !in} the +number of components in the first operands should be the same as the +dimension of the second operand. + +2. In the operations {\tt within}, {\tt not within}, and {\tt !within} +both operands should have identical dimension. + +All the relational operators listed above have their conventional +mathematical meaning. The resultant value is {\it true}, if +corresponding relation is satisfied for its operands, otherwise +{\it false}. (Note that symbolic values are ordered lexicographically, +and any numeric value precedes any symbolic value.) + +\subsection{Iterated expressions} + +An {\it iterated logical expression} is a primary logical expression, +which has the following syntactic form: +$$\mbox{{\it iterated-operator} {\it indexing-expression} +{\it integrand}}$$ +where {\it iterated-operator} is the symbolic name of the iterated +operator to be performed (see below), {\it indexing-expression} is an +indexing expression which introduces dummy indices and controls +iterating, {\it integrand} is a numeric expression that participates in +the operation. + +In MathProg there exist two iterated operators, which may be used in +logical expressions: + +{\def\arraystretch{1.4} +\noindent\hfil +\begin{tabular}{@{}lll@{}} +{\tt forall}&$\forall$-quantification&$\displaystyle +\forall(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +{\tt exists}&$\exists$-quantification&$\displaystyle +\exists(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +\end{tabular} +} + +\noindent where $i_1$, \dots, $i_n$ are dummy indices introduced in +the indexing expression, $\Delta$ is the domain, a set of $n$-tuples +specified by the indexing expression which defines particular values +assigned to the dummy indices on performing the iterated operation, +$f(i_1,\dots,i_n)$ is the integrand, a logical expression whose +resultant value depends on the dummy indices. + +For $\forall$-quantification the resultant value of the iterated +logical expression is {\it true}, if the value of the integrand is +{\it true} for all $n$-tuples contained in the domain, otherwise +{\it false}. + +For $\exists$-quantification the resultant value of the iterated +logical expression is {\it false}, if the value of the integrand is +{\it false} for all $n$-tuples contained in the domain, otherwise +{\it true}. + +\subsection{Parenthesized expressions} + +Any logical expression may be enclosed in parentheses that +syntactically makes it a primary logical expression. + +Parentheses may be used in logical expressions, as in algebra, to +specify the desired order in which operations are to be performed. +Where parentheses are used, the expression within the parentheses is +evaluated before the resultant value is used. + +The resultant value of the parenthesized expression is the same as the +value of the expression enclosed within parentheses. + +\newpage + +\subsection{Logical operators} + +In MathProg there exist the following logical operators, which may be +used in logical expressions: + +\begin{tabular}{@{}ll@{}} +{\tt not} $x$, {\tt!}$x$&negation $\neg\ x$\\ +$x$ {\tt and} $y$, $x$ {\tt\&\&} $y$&conjunction (logical ``and'') +$x\;\&\;y$\\ +$x$ {\tt or} $y$, $x$ {\tt||} $y$&disjunction (logical ``or'') +$x\vee y$\\ +\end{tabular} + +\noindent where $x$ and $y$ are logical expressions. + +If the expression includes more than one logical operator, all +operators are performed from left to right according to the hierarchy +of the operations (see below). The resultant value of the expression, +which contains logical operators, is the result of applying the +operators to their operands. + +\subsection{Hierarchy of operations} + +The following list shows the hierarchy of operations in logical +expressions: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operation&Hierarchy\\ +\hline +Evaluation of numeric operations&1st-7th\\ +Evaluation of symbolic operations&8th-9th\\ +Evaluation of set operations&10th-14th\\ +Relational operations ({\tt<}, {\tt<=}, etc.)&15th\\ +Negation ({\tt not}, {\tt!})&16th\\ +Conjunction ({\tt and}, {\tt\&\&})&17th\\ +$\forall$- and $\exists$-quantification ({\tt forall}, {\tt exists})& +18th\\ +Disjunction ({\tt or}, {\tt||})&19th\\ +\end{tabular} + +This hierarchy has the same meaning as was explained above for numeric +expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). + +\section{Linear expressions} + +An {\it linear expression} is a rule for computing so called +a {\it linear form} or simply a {\it formula}, which is a linear (or +affine) function of elemental variables. + +The primary linear expression may be an unsubscripted variable, +subscripted variable, iterated linear expression, conditional linear +expression, or another linear expression enclosed in parentheses. + +It is also allowed to use a numeric expression as the primary linear +expression, in which case the resultant value of the numeric expression +is automatically converted to a formula that includes the constant term +only. + +\para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|z| &(unsubscripted variable)\\ +\verb|x[i,j]| &(subscripted variable)\\ +\verb|sum{j in J} (a[i,j] * x[i,j] + 3 * y[i-1])| & +(iterated linear expression)\\ +\verb|if i in I then x[i,j] else 1.5 * z + 3.25| & +(conditional linear expression)\\ +\verb|(a[i,j] * x[i,j] + y[i-1] + .1)| & +(parenthesized linear expression)\\ +\end{tabular} + +More general linear expressions containing two or more primary linear +expressions may be constructed by using certain arithmetic operators. + +\para{Examples} + +\begin{verbatim} +2 * x[i-1,j+1] + 3.5 * y[k] + .5 * z +(- x[i,j] + 3.5 * y[k]) / sum{t in T} abs(d[i,j,t]) +\end{verbatim} + +\vspace*{-5pt} + +\subsection{Unsubscripted variables} + +If the primary linear expression is an unsubscripted variable (which +should be 0-dimensional), the resultant formula is that unsubscripted +variable. + +\vspace*{-5pt} + +\subsection{Subscripted variables} + +The primary linear expression, which refers to a subscripted variable, +has the following syntactic form: +$$\mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +$i_n${\tt]}}$$ +where {\it name} is the symbolic name of the model variable, $i_1$, +$i_2$, \dots, $i_n$ are subscripts. + +Each subscript should be a numeric or symbolic expression. The number +of subscripts in the subscript list should be the same as the dimension +of the model variable with which the subscript list is associated. + +Actual values of the subscript expressions are used to identify a +particular member of the model variable that determines the resultant +formula, which is an elemental variable associated with corresponding +member. + +\vspace*{-5pt} + +\subsection{Iterated expressions} + +An {\it iterated linear expression} is a primary linear expression, +which has the following syntactic form: +$$\mbox{{\tt sum} {\it indexing-expression} {\it integrand}}$$ +where {\it indexing-expression} is an indexing expression, which +introduces dummy indices and controls iterating, {\it integrand} is +a linear expression that participates in the operation. + +The iterated linear expression is evaluated exactly in the same way as +the iterated numeric expression (see Subection \ref{itexpr}, page +\pageref{itexpr}) with exception that the integrand participated in the +summation is a formula, not a numeric value. + +\vspace*{-5pt} + +\subsection{Conditional expressions} + +A {\it conditional linear expression} is a primary linear expression, +which has one of the following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt if} $b$ {\tt then} $f$ {\tt else} $g$}\\ +\mbox{{\tt if} $b$ {\tt then} $f$}\\ +\end{array} +} +$$ +where $b$ is an logical expression, $f$ and $g$ are linear expressions. + +\newpage + +The conditional linear expression is evaluated exactly in the same way +as the conditional numeric expression (see Subsection \ref{ifthen}, +page \pageref{ifthen}) with exception that operands participated in the +operation are formulae, not numeric values. + +\subsection{Parenthesized expressions} + +Any linear expression may be enclosed in parentheses that syntactically +makes it a primary linear expression. + +Parentheses may be used in linear expressions, as in algebra, to +specify the desired order in which operations are to be performed. +Where parentheses are used, the expression within the parentheses is +evaluated before the resultant formula is used. + +The resultant value of the parenthesized expression is the same as the +value of the expression enclosed within parentheses. + +\subsection{Arithmetic operators} + +In MathProg there exists the following arithmetic operators, which may +be used in linear expressions: + +\begin{tabular}{@{}ll@{}} +{\tt+} $f$&unary plus\\ +{\tt-} $f$&unary minus\\ +$f$ {\tt+} $g$&addition\\ +$f$ {\tt-} $g$&subtraction\\ +$x$ {\tt*} $f$, $f$ {\tt*} $x$&multiplication\\ +$f$ {\tt/} $x$&division +\end{tabular} + +\noindent where $f$ and $g$ are linear expressions, $x$ is a numeric +expression (more precisely, a linear expression containing only the +constant term). + +If the expression includes more than one arithmetic operator, all +operators are performed from left to right according to the hierarchy +of operations (see below). The resultant value of the expression, which +contains arithmetic operators, is the result of applying the operators +to their operands. + +\subsection{Hierarchy of operations} + +The hierarchy of arithmetic operations used in linear expressions is +the same as for numeric expressions (see Subsection \ref{hierarchy}, +page \pageref{hierarchy}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Statements} + +{\it Statements} are basic units of the model description. In MathProg +all statements are divided into two categories: declaration statements +and functional statements. + +{\it Declaration statements} (set statement, parameter statement, +variable statement, constraint statement, objective statement) are used +to declare model objects of certain kinds and define certain properties +of such objects. + +{\it Functional statements} (solve statement, check statement, display +statement, printf statement, loop statement, table statement) are +intended for performing some specific actions. + +Note that declaration statements may follow in arbitrary order, which +does not affect the result of translation. However, any model object +should be declared before it is referenced in other statements. + +\section{Set statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt set} {\it name} {\it alias} {\it domain} {\tt,} +{\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the set; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the set; + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the set; + +\noindent +{\it attrib}, \dots, {\it attrib} are optional attributes of the set. +(Commae preceding attributes may be omitted.) + +\para{Optional attributes} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt dimen} $n$]\hspace*{0pt}\\ +specifies the dimension of $n$-tuples which the set consists of; +\item[{\tt within} {\it expression}]\hspace*{0pt}\\ +specifies a superset which restricts the set or all its members +(elemental sets) to be within that superset; +\item[{\tt:=} {\it expression}]\hspace*{0pt}\\ +specifies an elemental set assigned to the set or its members; +\item[{\tt default} {\it expression}]\hspace*{0pt}\\ +specifies an elemental set assigned to the set or its members whenever +no appropriate data are available in the data section. +\end{description} + +\vspace*{-8pt} + +\para{Examples} + +\begin{verbatim} +set nodes; +set arcs within nodes cross nodes; +set step{s in 1..maxiter} dimen 2 := if s = 1 then arcs else step[s-1] + union setof{k in nodes, (i,k) in step[s-1], (k,j) in step[s-1]}(i,j); +set A{i in I, j in J}, within B[i+1] cross C[j-1], within D diff E, + default {('abc',123), (321,'cba')}; +\end{verbatim} + +The set statement declares a set. If the subscript domain is not +specified, the set is a simple set, otherwise it is an array of +elemental sets. + +The {\tt dimen} attribute specifies the dimension of $n$-tuples, which +the set (if it is a simple set) or its members (if the set is an array +of elemental sets) consist of, where $n$ should be an unsigned integer +from 1 to 20. At most one {\tt dimen} attribute can be specified. If +the {\tt dimen} attribute is not specified, the dimension of $n$-tuples +is implicitly determined by other attributes (for example, if there is +a set expression that follows {\tt:=} or the keyword {\tt default}, the +dimension of $n$-tuples of corresponding elemental set is used). +If no dimension information is available, {\tt dimen 1} is assumed. + +The {\tt within} attribute specifies a set expression whose resultant +value is a superset used to restrict the set (if it is a simple set) or +its members (if the set is an array of elemental sets) to be within +that superset. Arbitrary number of {\tt within} attributes may be +specified in the same set statement. + +The assign ({\tt:=}) attribute specifies a set expression used to +evaluate elemental set(s) assigned to the set (if it is a simple set) +or its members (if the set is an array of elemental sets). If the +assign attribute is specified, the set is {\it computable} and +therefore needs no data to be provided in the data section. If the +assign attribute is not specified, the set should be provided with data +in the data section. At most one assign or default attribute can be +specified for the same set. + +The {\tt default} attribute specifies a set expression used to evaluate +elemental set(s) assigned to the set (if it is a simple set) or its +members (if the set is an array of elemental sets) whenever +no appropriate data are available in the data section. If neither +assign nor default attribute is specified, missing data will cause an +error. + +\newpage + +\section{Parameter statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt param} {\it name} {\it alias} {\it domain} {\tt,} +{\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the parameter; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the parameter; + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the parameter; + +\noindent +{\it attrib}, \dots, {\it attrib} are optional attributes of the +parameter. (Commae preceding attributes may be omitted.) + +\para{Optional attributes} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt integer}]\hspace*{0pt}\\ +specifies that the parameter is integer; +\item[{\tt binary}]\hspace*{0pt}\\ +specifies that the parameter is binary; +\item[{\tt symbolic}]\hspace*{0pt}\\ +specifies that the parameter is symbolic; +\item[{\it relation expression}]\hspace*{0pt}\\ +(where {\it relation} is one of: {\tt<}, {\tt<=}, {\tt=}, {\tt==}, +{\tt>=}, {\tt>}, {\tt<>}, {\tt!=})\\ +specifies a condition that restricts the parameter or its members to +satisfy that condition; +\item[{\tt in} {\it expression}]\hspace*{0pt}\\ +specifies a superset that restricts the parameter or its members to be +in that superset; +\item[{\tt:=} {\it expression}]\hspace*{0pt}\\ +specifies a value assigned to the parameter or its members; +\item[{\tt default} {\it expression}]\hspace*{0pt}\\ +specifies a value assigned to the parameter or its members whenever +no appropriate data are available in the data section. +\end{description} + +\vspace*{-8pt} + +\para{Examples} + +\begin{verbatim} +param units{raw, prd} >= 0; +param profit{prd, 1..T+1}; +param N := 20 integer >= 0 <= 100; +param comb 'n choose k' {n in 0..N, k in 0..n} := + if k = 0 or k = n then 1 else comb[n-1,k-1] + comb[n-1,k]; +param p{i in I, j in J}, integer, >= 0, <= i+j, in A[i] symdiff B[j], + in C[i,j], default 0.5 * (i + j); +param month symbolic default 'May' in {'Mar', 'Apr', 'May'}; +\end{verbatim} + +The parameter statement declares a parameter. If a subscript domain is +not specified, the parameter is a simple (scalar) parameter, otherwise +it is a $n$-dimensional array. + +The type attributes {\tt integer}, {\tt binary}, and {\tt symbolic} +qualify the type of values that can be assigned to the parameter as +shown below: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Type attribute&Assigned values\\ +\hline +(not specified)&Any numeric values\\ +{\tt integer}&Only integer numeric values\\ +{\tt binary}&Either 0 or 1\\ +{\tt symbolic}&Any numeric and symbolic values\\ +\end{tabular} + +The {\tt symbolic} attribute cannot be specified along with other type +attributes. Being specified it should precede all other attributes. + +The condition attribute specifies an optional condition that restricts +values assigned to the parameter to satisfy that condition. This +attribute has the following syntactic forms: + +\begin{tabular}{@{}ll@{}} +{\tt<} $v$&check for $x<v$\\ +{\tt<=} $v$&check for $x\leq v$\\ +{\tt=} $v$, {\tt==} $v$&check for $x=v$\\ +{\tt>=} $v$&check for $x\geq v$\\ +{\tt>} $v$&check for $x\geq v$\\ +{\tt<>} $v$, {\tt!=} $v$&check for $x\neq v$\\ +\end{tabular} + +\noindent where $x$ is a value assigned to the parameter, $v$ is the +resultant value of a numeric or symbolic expression specified in the +condition attribute. Arbitrary number of condition attributes can be +specified for the same parameter. If a value being assigned to the +parameter during model evaluation violates at least one of specified +conditions, an error is raised. (Note that symbolic values are ordered +lexicographically, and any numeric value precedes any symbolic value.) + +The {\tt in} attribute is similar to the condition attribute and +specifies a set expression whose resultant value is a superset used to +restrict numeric or symbolic values assigned to the parameter to be in +that superset. Arbitrary number of the {\tt in} attributes can be +specified for the same parameter. If a value being assigned to the +parameter during model evaluation is not in at least one of specified +supersets, an error is raised. + +The assign ({\tt:=}) attribute specifies a numeric or symbolic +expression used to compute a value assigned to the parameter (if it is +a simple parameter) or its member (if the parameter is an array). If +the assign attribute is specified, the parameter is {\it computable} +and therefore needs no data to be provided in the data section. If the +assign attribute is not specified, the parameter should be provided +with data in the data section. At most one assign or {\tt default} +attribute can be specified for the same parameter. + +The {\tt default} attribute specifies a numeric or symbolic expression +used to compute a value assigned to the parameter or its member +whenever no appropriate data are available in the data section. If +neither assign nor {\tt default} attribute is specified, missing data +will cause an error. + +\newpage + +\section{Variable statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt var} {\it name} {\it alias} {\it domain} {\tt,} +{\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the variable; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the variable; + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the variable; + +\noindent +{\it attrib}, \dots, {\it attrib} are optional attributes of the +variable. (Commae preceding attributes may be omitted.) + +\para{Optional attributes} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt integer}]\hspace*{0pt}\\ +restricts the variable to be integer; +\item[{\tt binary}]\hspace*{0pt}\\ +restricts the variable to be binary; +\item[{\tt>=} {\it expression}]\hspace*{0pt}\\ +specifies an lower bound of the variable; +\item[{\tt<=} {\it expression}]\hspace*{0pt}\\ +specifies an upper bound of the variable; +\item[{\tt=} {\it expression}]\hspace*{0pt}\\ +specifies a fixed value of the variable; +\end{description} + +\vspace*{-8pt} + +\para{Examples} + +\begin{verbatim} +var x >= 0; +var y{I,J}; +var make{p in prd}, integer, >= commit[p], <= market[p]; +var store{raw, 1..T+1} >= 0; +var z{i in I, j in J} >= i+j; +\end{verbatim} + +The variable statement declares a variable. If a subscript domain is +not specified, the variable is a simple (scalar) variable, otherwise it +is a $n$-dimensional array of elemental variables. + +Elemental variable(s) associated with the model variable (if it is a +simple variable) or its members (if it is an array) correspond to the +variables in the LP/MIP problem formulation (see Section \ref{problem}, +page \pageref{problem}). Note that only elemental variables actually +referenced in some constraints and/or objectives are included in the +LP/MIP problem instance to be generated. + +The type attributes {\tt integer} and {\tt binary} restrict the +variable to be integer or binary, respectively. If no type attribute is +specified, the variable is continuous. If all variables in the model +are continuous, the corresponding problem is of LP class. If there is +at least one integer or binary variable, the problem is of MIP class. + +The lower bound ({\tt>=}) attribute specifies a numeric expression for +computing an lower bound of the variable. At most one lower bound can +be specified. By default all variables (except binary ones) have no +lower bound, so if a variable is required to be non-negative, its zero +lower bound should be explicitly specified. + +The upper bound ({\tt<=}) attribute specifies a numeric expression for +computing an upper bound of the variable. At most one upper bound +attribute can be specified. + +The fixed value ({\tt=}) attribute specifies a numeric expression for +computing a value, at which the variable is fixed. This attribute +cannot be specified along with the bound attributes. + +\section{Constraint statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][106pt]{468pt}{ +\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt,} {\tt=} {\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt,} {\tt<=} {\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt,} {\tt>=} {\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt,} {\tt<=} {\it expression} {\tt,} {\tt<=} +{\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt,} {\tt>=} {\it expression} {\tt,} {\tt>=} +{\it expression} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the constraint; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the constraint; + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the constraint; + +\noindent +{\it expression} is a linear expression used to compute a component of +the constraint. (Commae following expressions may be omitted.) + +\noindent +(The keyword {\tt s.t.} may be written as {\tt subject to} or as +{\tt subj to}, or may be omitted at all.) + +\para{Examples} + +\begin{verbatim} +s.t. r: x + y + z, >= 0, <= 1; +limit{t in 1..T}: sum{j in prd} make[j,t] <= max_prd; +subject to balance{i in raw, t in 1..T}: + store[i,t+1] - store[i,t] - sum{j in prd} units[i,j] * make[j,t]; +subject to rlim 'regular-time limit' {t in time}: + sum{p in prd} pt[p] * rprd[p,t] <= 1.3 * dpp[t] * crews[t]; +\end{verbatim} + +The constraint statement declares a constraint. If a subscript domain +is not specified, the\linebreak constraint is a simple (scalar) +constraint, otherwise it is a $n$-dimensional array of elemental +constraints. + +Elemental constraint(s) associated with the model constraint (if it is +a simple constraint) or its members (if it is an array) correspond to +the linear constraints in the LP/MIP problem formulation (see +Section \ref{problem}, page \pageref{problem}). + +If the constraint has the form of equality or single inequality, i.e. +includes two expressions, one of which follows the colon and other +follows the relation sign {\tt=}, {\tt<=}, or {\tt>=}, both expressions +in the statement can be linear expressions. If the constraint has the +form of double inequality,\linebreak i.e. includes three expressions, +the middle expression can be a linear expression while the leftmost and +rightmost ones can be only numeric expressions. + +Generating the model is, roughly speaking, generating its constraints, +which are always evaluated for the entire subscript domain. Evaluation +of the constraints leads, in turn, to evaluation of other model objects +such as sets, parameters, and variables. + +Constructing an actual linear constraint included in the problem +instance, which (constraint) corresponds to a particular elemental +constraint, is performed as follows. + +If the constraint has the form of equality or single inequality, +evaluation of both linear expressions gives two resultant linear forms: +$$\begin{array}{r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r} +f&=&a_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&a_0,\\ +g&=&b_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&b_0,\\ +\end{array}$$ +where $x_1$, $x_2$, \dots, $x_n$ are elemental variables; $a_1$, $a_2$, +\dots, $a_n$, $b_1$, $b_2$, \dots, $b_n$ are numeric coefficients; +$a_0$ and $b_0$ are constant terms. Then all linear terms of $f$ and +$g$ are carried to the left-hand side, and the constant terms are +carried to the right-hand side, that gives the final elemental +constraint in the standard form: +$$(a_1-b_1)x_1+(a_2-b_2)x_2+\dots+(a_n-b_n)x_n\left\{ +\begin{array}{@{}c@{}}=\\\leq\\\geq\\\end{array}\right\}b_0-a_0.$$ + +If the constraint has the form of double inequality, evaluation of the +middle linear expression gives the resultant linear form: +$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +and evaluation of the leftmost and rightmost numeric expressions gives +two numeric values $l$ and $u$, respectively. Then the constant term of +the linear form is carried to both left-hand and right-handsides that +gives the final elemental constraint in the standard form: +$$l-a_0\leq a_1x_1+a_2x_2+\dots+a_nx_n\leq u-a_0.$$ + +\section{Objective statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt minimize} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt maximize} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the objective; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the objective; + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the objective; + +\noindent +{\it expression} is a linear expression used to compute the linear form +of the objective. + +\newpage + +\para{Examples} + +\begin{verbatim} +minimize obj: x + 1.5 * (y + z); +maximize total_profit: sum{p in prd} profit[p] * make[p]; +\end{verbatim} + +The objective statement declares an objective. If a subscript domain is +not specified, the objective is a simple (scalar) objective. Otherwise +it is a $n$-dimensional array of elemental objectives. + +Elemental objective(s) associated with the model objective (if it is a +simple objective) or its members (if it is an array) correspond to +general linear constraints in the LP/MIP problem formulation (see +Section \ref{problem}, page \pageref{problem}). However, unlike +constraints the corresponding linear forms are free (unbounded). + +Constructing an actual linear constraint included in the problem +instance, which (constraint) corresponds to a particular elemental +constraint, is performed as follows. The linear expression specified in +the objective statement is evaluated that, gives the resultant linear +form: +$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +where $x_1$, $x_2$, \dots, $x_n$ are elemental variables; $a_1$, $a_2$, +\dots, $a_n$ are numeric coefficients; $a_0$ is the constant term. Then +the linear form is used to construct the final elemental constraint in +the standard form: +$$-\infty<a_1x_1+a_2x_2+\dots+a_nx_n+a_0<+\infty.$$ + +As a rule the model description contains only one objective statement +that defines the objective function used in the problem instance. +However, it is allowed to declare arbitrary number of objectives, in +which case the actual objective function is the first objective +encountered in the model description. Other objectives are also +included in the problem instance, but they do not affect the objective +function. + +\section{Solve statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt solve} {\tt;} +}} + +\medskip + +The solve statement is optional and can be used only once. If no solve +statement is used, one is assumed at the end of the model section. + +The solve statement causes the model to be solved, that means computing +numeric values of all model variables. This allows using variables in +statements below the solve statement in the same way as if they were +numeric parameters. + +Note that the variable, constraint, and objective statements cannot be +used below the solve statement, i.e. all principal components of the +model should be declared above the solve statement. + +\newpage + +\section{Check statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt check} {\it domain} {\tt:} {\it expression} {\tt;} +}} + +\medskip + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the check statement; + +\noindent +{\it expression} is an logical expression which specifies the logical +condition to be checked. (The colon preceding {\it expression} may be +omitted.) + +\para{Examples} + +\begin{verbatim} +check: x + y <= 1 and x >= 0 and y >= 0; +check sum{i in ORIG} supply[i] = sum{j in DEST} demand[j]; +check{i in I, j in 1..10}: S[i,j] in U[i] union V[j]; +\end{verbatim} + +The check statement allows checking the resultant value of an logical +expression specified in the statement. If the value is {\it false}, an +error is reported. + +If the subscript domain is not specified, the check is performed only +once. Specifying the subscript domain allows performing multiple check +for every $n$-tuple in the domain set. In the latter case the logical +expression may include dummy indices introduced in corresponding +indexing expression. + +\section{Display statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt display} {\it domain} {\tt:} {\it item} {\tt,} +\dots {\tt,} {\it item} {\tt;} +}} + +\medskip + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the display statement; + +\noindent +{\it item}, \dots, {\it item} are items to be displayed. (The colon +preceding the first item may be omitted.) + +\para{Examples} + +\begin{verbatim} +display: 'x =', x, 'y =', y, 'z =', z; +display sqrt(x ** 2 + y ** 2 + z ** 2); +display{i in I, j in J}: i, j, a[i,j], b[i,j]; +\end{verbatim} + +The display statement evaluates all items specified in the statement +and writes their values on the standard output (terminal) in plain text +format. + +If a subscript domain is not specified, items are evaluated and then +displayed only once. Specifying the subscript domain causes items to be +evaluated and displayed for every $n$-tuple in the domain set. In the +latter case items may include dummy indices introduced in corresponding +indexing expression. + +An item to be displayed can be a model object (set, parameter, v +ariable, constraint, objective) or an expression. + +If the item is a computable object (i.e. a set or parameter provided +with the assign attribute), the object is evaluated over the entire +domain and then its content (i.e. the content of the object array) is +displayed. Otherwise, if the item is not a computable object, only its +current content (i.e. members actually generated during the model +evaluation) is displayed. + +If the item is an expression, the expression is evaluated and its +resultant value is displayed. + +\section{Printf statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][64pt]{468pt}{ +\hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} +{\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} +{\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt>} +{\it filename} {\tt;} + +\medskip + +\hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} +{\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt>>} +{\it filename} {\tt;} +}} + +\medskip + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the printf statement; + +\noindent +{\it format} is a symbolic expression whose value specifies a format +control string. (The colon preceding the format expression may be +omitted.) + +\noindent +{\it expression}, \dots, {\it expression} are zero or more expressions +whose values have to be formatted and printed. Each expression should +be of numeric, symbolic, or logical type. + +\noindent +{\it filename} is a symbolic expression whose value specifies a name +of a text file, to which the output is redirected. The flag {\tt>} +means creating a new empty file while the flag {\tt>>} means appending +the output to an existing file. If no file name is specified, the +output is written on the standard output (terminal). + +\para{Examples} + +\begin{verbatim} +printf 'Hello, world!\n'; +printf: "x = %.3f; y = %.3f; z = %.3f\n", x, y, z > "result.txt"; +printf{i in I, j in J}: "flow from %s to %s is %d\n", i, j, x[i,j] + >> result_file & ".txt"; +printf{i in I} 'total flow from %s is %g\n', i, sum{j in J} x[i,j]; +printf{k in K} "x[%s] = " & (if x[k] < 0 then "?" else "%g"), + k, x[k]; +\end{verbatim} + +The printf statement is similar to the display statement, however, it +allows formatting data to be written. + +If a subscript domain is not specified, the printf statement is +executed only once. Specifying a subscript domain causes executing the +printf statement for every $n$-tuple in the domain set. In the latter +case the format and expression may include dummy indices introduced in +corresponding indexing expression. + +The format control string is a value of the symbolic expression +{\it format} specified in the printf statement. It is composed of zero +or more directives as follows: ordinary characters (not {\tt\%}), which +are copied unchanged to the output stream, and conversion +specifications, each of which causes evaluating corresponding +expression specified in the printf statement, formatting it, and +writing its resultant value to the output stream. + +Conversion specifications that may be used in the format control string +are the following:\linebreak {\tt d}, {\tt i}, {\tt f}, {\tt F}, +{\tt e}, {\tt E}, {\tt g}, {\tt G}, and {\tt s}. These specifications +have the same syntax and semantics as in the C programming language. + +\section{For statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt for} {\it domain} {\tt:} {\it statement} {\tt;} + +\medskip + +\hspace{6pt} {\tt for} {\it domain} {\tt:} {\tt\{} {\it statement} +\dots {\it statement} {\tt\}} {\tt;} +}} + +\medskip + +\noindent +{\it domain} is an indexing expression which specifies a subscript +domain of the for statement. (The colon following the indexing +expression may be omitted.) + +\noindent +{\it statement} is a statement, which should be executed under control +of the for statement; + +\noindent +{\it statement}, \dots, {\it statement} is a sequence of statements +(enclosed in curly braces), which should be executed under control of +the for statement. + +Only the following statements can be used within the for statement: +check, display, printf, and another for. + +\para{Examples} + +\begin{verbatim} +for {(i,j) in E: i != j} +{ printf "flow from %s to %s is %g\n", i, j, x[i,j]; + check x[i,j] >= 0; +} +for {i in 1..n} +{ for {j in 1..n} printf " %s", if x[i,j] then "Q" else "."; + printf("\n"); +} +for {1..72} printf("*"); +\end{verbatim} + +The for statement causes a statement or a sequence of statements +specified as part of the for statement to be executed for every +$n$-tuple in the domain set. Thus, statements within the for statement +may include dummy indices introduced in corresponding indexing +expression. + +\newpage + +\section{Table statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][80pt]{468pt}{ +\hspace{6pt} {\tt table} {\it name} {\it alias} {\tt IN} {\it driver} +{\it arg} \dots {\it arg} {\tt:} + +\hspace{6pt} {\tt\ \ \ \ \ } {\it set} {\tt<-} {\tt[} {\it fld} {\tt,} +\dots {\tt,} {\it fld} {\tt]} {\tt,} {\it par} {\tt\textasciitilde} +{\it fld} {\tt,} \dots {\tt,} {\it par} {\tt\textasciitilde} {\it fld} +{\tt;} + +\medskip + +\hspace{6pt} {\tt table} {\it name} {\it alias} {\it domain} {\tt OUT} +{\it driver} {\it arg} \dots {\it arg} {\tt:} + +\hspace{6pt} {\tt\ \ \ \ \ } {\it expr} {\tt\textasciitilde} {\it fld} +{\tt,} \dots {\tt,} {\it expr} {\tt\textasciitilde} {\it fld} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the table; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the table; + +\noindent +{\it domain} is an indexing expression, which specifies a subscript +domain of the (output) table; + +\noindent +{\tt IN} means reading data from the input table; + +\noindent +{\tt OUT} means writing data to the output table; + +\noindent +{\it driver} is a symbolic expression, which specifies the driver used +to access the table (for details see Appendix \ref{drivers}, page +\pageref{drivers}); + +\noindent +{\it arg} is an optional symbolic expression, which is an argument +pass\-ed to the table driver. This symbolic expression should not +include dummy indices specified in the domain; + +\noindent +{\it set} is the name of an optional simple set called {\it control +set}. It can be omitted along with the delimiter {\tt<-}; + +\noindent +{\it fld} is a field name. Within square brackets at least one field +should be specified. The field name following a parameter name or +expression is optional and can be omitted along with the +delimiter~{\tt\textasciitilde}, in which case the name of corresponding +model object is used as the field name; + +\noindent +{\it par} is a symbolic name of a model parameter; + +\noindent +{\it expr} is a numeric or symbolic expression. + +\para{Examples} + +\begin{verbatim} +table data IN "CSV" "data.csv": S <- [FROM,TO], d~DISTANCE, + c~COST; +table result{(f,t) in S} OUT "CSV" "result.csv": f~FROM, t~TO, + x[f,t]~FLOW; +\end{verbatim} + +The table statement allows reading data from a table into model +objects such as sets and (non-scalar) parameters as well as writing +data from the model to a table. + +\newpage + +\subsection{Table structure} + +A {\it data table} is an (unordered) set of {\it records}, where each +record consists of the same number of {\it fields}, and each field is +provided with a unique symbolic name called the {\it field name}. For +example: + +\bigskip + +\begin{tabular}{@{\hspace*{42mm}}c@{\hspace*{11mm}}c@{\hspace*{10mm}}c +@{\hspace*{9mm}}c} +First&Second&&Last\\ +field&field&.\ \ .\ \ .&field\\ +$\downarrow$&$\downarrow$&&$\downarrow$\\ +\end{tabular} + +\begin{tabular}{ll@{}} +Table header&$\rightarrow$\\ +First record&$\rightarrow$\\ +Second record&$\rightarrow$\\ +\\ +\hfil .\ \ .\ \ .\\ +\\ +Last record&$\rightarrow$\\ +\end{tabular} +\begin{tabular}{|l|l|c|c|} +\hline +{\tt FROM}&{\tt TO}&{\tt DISTANCE}&{\tt COST}\\ +\hline +{\tt Seattle} &{\tt New-York}&{\tt 2.5}&{\tt 0.12}\\ +{\tt Seattle} &{\tt Chicago} &{\tt 1.7}&{\tt 0.08}\\ +{\tt Seattle} &{\tt Topeka} &{\tt 1.8}&{\tt 0.09}\\ +{\tt San-Diego}&{\tt New-York}&{\tt 2.5}&{\tt 0.15}\\ +{\tt San-Diego}&{\tt Chicago} &{\tt 1.8}&{\tt 0.10}\\ +{\tt San-Diego}&{\tt Topeka} &{\tt 1.4}&{\tt 0.07}\\ +\hline +\end{tabular} + +\subsection{Reading data from input table} + +The input table statement causes reading data from the specified table +record by record. + +Once a next record has been read, numeric or symbolic values of fields, +whose names are enclosed in square brackets in the table statement, are +gathered into $n$-tuple, and if the control set is specified in the +table statement, this $n$-tuple is added to it. Besides, a numeric or +symbolic value of each field associated with a model parameter is +assigned to the parameter member identified by subscripts, which are +components of the $n$-tuple just read. + +For example, the following input table statement: + +\noindent\hfil +\verb|table data IN "...": S <- [FROM,TO], d~DISTANCE, c~COST;| + +\noindent +causes reading values of four fields named {\tt FROM}, {\tt TO}, +{\tt DISTANCE}, and {\tt COST} from each record of the specified table. +Values of fields {\tt FROM} and {\tt TO} give a pair $(f,t)$, which is +added to the control set {\tt S}. The value of field {\tt DISTANCE} is +assigned to parameter member ${\tt d}[f,t]$, and the value of field +{\tt COST} is assigned to parameter member ${\tt c}[f,t]$. + +Note that the input table may contain extra fields whose names are not +specified in the table statement, in which case values of these fields +on reading the table are ignored. + +\subsection{Writing data to output table} + +The output table statement causes writing data to the specified table. +Note that some drivers (namely, CSV and xBASE) destroy the output table +before writing data, i.e. delete all its existing records. + +Each $n$-tuple in the specified domain set generates one record written +to the output table. Values of fields are numeric or symbolic values of +corresponding expressions specified in the table statement. These +expressions are evaluated for each $n$-tuple in the domain set and, +thus, may include dummy indices introduced in the corresponding indexing +expression. + +For example, the following output table statement: + +\noindent\hfil +\verb|table result{(f,t) in S} OUT "...": f~FROM, t~TO, x[f,t]~FLOW;| + +\noindent +causes writing records, by one record for each pair $(f,t)$ in set +{\tt S}, to the output table, where each record consists of three +fields named {\tt FROM}, {\tt TO}, and {\tt FLOW}. The values written +to fields {\tt FROM} and {\tt TO} are current values of dummy indices +{\tt f} and {\tt t}, and the value written to field {\tt FLOW} is +a value of member ${\tt x}[f,t]$ of corresponding subscripted parameter +or variable. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Model data} + +{\it Model data} include elemental sets, which are ``values'' of model +sets, and numeric and symbolic values of model parameters. + +In MathProg there are two different ways to saturate model sets and +parameters with data. One way is simply providing necessary data using +the assign attribute. However, in many cases it is more practical to +separate the model itself and particular data needed for the model. For +the latter reason in MathProg there is another way, when the model +description is divided into two parts: model section and data section. + +A {\it model section} is a main part of the model description that +contains declarations of all model objects and is common for all +problems based on that model. + +A {\it data section} is an optional part of the model description that +contains model data specific for a particular problem. + +In MathProg model and data sections can be placed either in one text +file or in two separate text files. + +1. If both model and data sections are placed in one file, the file is +composed as follows: + +\bigskip + +\noindent\hfil +\framebox{\begin{tabular}{l} +{\it statement}{\tt;}\\ +{\it statement}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it statement}{\tt;}\\ +{\tt data;}\\ +{\it data block}{\tt;}\\ +{\it data block}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it data block}{\tt;}\\ +{\tt end;} +\end{tabular}} + +\newpage + +2. If the model and data sections are placed in two separate files, the +files are composed as follows: + +\bigskip + +\noindent\hfil +\begin{tabular}{@{}c@{}} +\framebox{\begin{tabular}{l} +{\it statement}{\tt;}\\ +{\it statement}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it statement}{\tt;}\\ +{\tt end;}\\ +\end{tabular}}\\ +\\\\Model file\\ +\end{tabular} +\hspace{32pt} +\begin{tabular}{@{}c@{}} +\framebox{\begin{tabular}{l} +{\tt data;}\\ +{\it data block}{\tt;}\\ +{\it data block}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it data block}{\tt;}\\ +{\tt end;}\\ +\end{tabular}}\\ +\\Data file\\ +\end{tabular} + +\bigskip + +Note: If the data section is placed in a separate file, the keyword +{\tt data} is optional and may be omitted along with the semicolon that +follows it. + +\section{Coding data section} + +The {\it data section} is a sequence of data blocks in various formats, +which are discussed in following sections. The order, in which data +blocks follow in the data section, may be arbitrary, not necessarily +the same, in which corresponding model objects follow in the model +section. + +The rules of coding the data section are commonly the same as the rules +of coding the model description (see Section \ref{coding}, page +\pageref{coding}), i.e. data blocks are composed from basic lexical +units such as symbolic names, numeric and string literals, keywords, +delimiters, and comments. However, for the sake of convenience and for +improving readability there is one deviation from the common rule: if +a string literal consists of only alphanumeric characters (including +the underscore character), the signs {\tt+} and {\tt-}, and/or the +decimal point, it may be coded without bordering by (single or double) +quotes. + +All numeric and symbolic material provided in the data section is coded +in the form of numbers and symbols, i.e. unlike the model section +no expressions are allowed in the data section. Nevertheless, the signs +{\tt+} and {\tt-} can precede numeric literals to allow coding signed +numeric quantities, in which case there should be no white-space +characters between the sign and following numeric literal (if there is +at least one white-space, the sign and following numeric literal are +recognized as two different lexical units). + +\newpage + +\section{Set data block} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt set} {\it name} {\tt,} {\it record} {\tt,} \dots +{\tt,} {\it record} {\tt;} + +\medskip + +\hspace{6pt} {\tt set} {\it name} {\tt[} {\it symbol} {\tt,} \dots +{\tt,} {\it symbol} {\tt]} {\tt,} {\it record} {\tt,} \dots {\tt,} +{\it record} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the set; + +\noindent +{\it symbol}, \dots, {\it symbol} are subscripts, which specify +a particular member of the set (if the set is an array, i.e. a set of +sets); + +\noindent +{\it record}, \dots, {\it record} are data records. + +\noindent +Commae preceding data records may be omitted. + +\para{Data records} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt :=}]\hspace*{0pt}\\ +is a non-significant data record, which may be used freely to improve +readability; +\item[{\tt(} {\it slice} {\tt)}]\hspace*{0pt}\\ +specifies a slice; +\item[{\it simple-data}]\hspace*{0pt}\\ +specifies set data in the simple format; +\item[{\tt:} {\it matrix-data}]\hspace*{0pt}\\ +specifies set data in the matrix format; +\item[{\tt(tr)} {\tt:} {\it matrix-data}]\hspace*{0pt}\\ +specifies set data in the transposed matrix format. (In this case the +colon following the keyword {\tt(tr)} may be omitted.) +\end{description} + +\vspace*{-8pt} + +\para{Examples} + +\begin{verbatim} +set month := Jan Feb Mar Apr May Jun; +set month "Jan", "Feb", "Mar", "Apr", "May", "Jun"; +set A[3,Mar] := (1,2) (2,3) (4,2) (3,1) (2,2) (4,4) (3,4); +set A[3,'Mar'] := 1 2 2 3 4 2 3 1 2 2 4 4 2 4; +set A[3,'Mar'] : 1 2 3 4 := + 1 - + - - + 2 - + + - + 3 + - - + + 4 - + - + ; +set B := (1,2,3) (1,3,2) (2,3,1) (2,1,3) (1,2,2) (1,1,1) (2,1,1); +set B := (*,*,*) 1 2 3, 1 3 2, 2 3 1, 2 1 3, 1 2 2, 1 1 1, 2 1 1; +set B := (1,*,2) 3 2 (2,*,1) 3 1 (1,2,3) (2,1,3) (1,1,1); +set B := (1,*,*) : 1 2 3 := + 1 + - - + 2 - + + + 3 - + - + (2,*,*) : 1 2 3 := + 1 + - + + 2 - - - + 3 + - - ; +\end{verbatim} + +\noindent(In these examples {\tt month} is a simple set of singlets, +{\tt A} is a 2-dimensional array of doublets, and {\tt B} is a simple +set of triplets. Data blocks for the same set are equivalent in the +sense that they specify the same data in different formats.) + +The {\it set data block} is used to specify a complete elemental set, +which is assigned to a set (if it is a simple set) or one of its +members (if the set is an array of sets).\footnote{There is another way +to specify data for a simple set along with data for parameters. This +feature is discussed in the next section.} + +Data blocks can be specified only for non-computable sets, i.e. for +sets, which have no assign attribute ({\tt:=}) in the corresponding set +statements. + +If the set is a simple set, only its symbolic name should be specified +in the header of the data block. Otherwise, if the set is a +$n$-dimensional array, its symbolic name should be provided with a +complete list of subscripts separated by commae and enclosed in square +brackets to specify a particular member of the set array. The number of +subscripts should be the same as the dimension of the set array, where +each subscript should be a number or symbol. + +An elemental set defined in the set data block is coded as a sequence +of data records described below.\footnote{{\it Data record} is simply a +technical term. It does not mean that data records have any special +formatting.} + +\subsection{Assign data record} + +The {\it assign data record} ({\tt:=}) is a non-signficant element. +It may be used for improving readability of data blocks. + +\subsection{Slice data record} + +The {\it slice data record} is a control record, which specifies a +{\it slice} of the elemental set defined in the data block. It has the +following syntactic form: +$$\mbox{{\tt(} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt)}}$$ +where $s_1$, $s_2$, \dots, $s_n$ are components of the slice. + +Each component of the slice can be a number or symbol or the asterisk +({\tt*}). The number of components in the slice should be the same as +the dimension of $n$-tuples in the elemental set to be defined. For +instance, if the elemental set contains 4-tuples (quadruplets), the +slice should have four components. The number of asterisks in the slice +is called the {\it slice dimension}. + +The effect of using slices is the following. If a $m$-dimensional slice +(i.e. a slice having $m$ asterisks) is specified in the data block, all +subsequent data records should specify tuples of the dimension~$m$. +Whenever a $m$-tuple is encountered, each asterisk in the slice is +replaced by corresponding components of the $m$-tuple that gives the +resultant $n$-tuple, which is included in the elemental set to be +defined. For example, if the slice $(a,*,1,2,*)$ is in effect, and +2-tuple $(3,b)$ is encountered in a subsequent data record, the +resultant 5-tuple included in the elemental set is $(a,3,1,2,b)$. + +The slice having no asterisks itself defines a complete $n$-tuple, +which is included in the elemental set. + +Being once specified the slice effects until either a new slice or the +end of data block is encountered. Note that if no slice is specified in +the data block, one, components of which are all asterisks, is assumed. + +\subsection{Simple data record} + +The {\it simple data record} defines one $n$-tuple in a simple format +and has the following syntactic form: +$$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$}$$ +where $t_1$, $t_2$, \dots, $t_n$ are components of the $n$-tuple. Each +component can be a number or symbol. Commae between components are +optional and may be omitted. + +\subsection{Matrix data record} + +The {\it matrix data record} defines several 2-tuples (doublets) in +a matrix format and has the following syntactic form: +$$\begin{array}{cccccc} +\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +where $r_1$, $r_2$, \dots, $r_m$ are numbers and/or symbols +corresponding to rows of the matrix; $c_1$, $c_2$, \dots, $c_n$ are +numbers and/or symbols corresponding to columns of the matrix, $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ are matrix elements, which can be either +{\tt+} or {\tt-}. (In this data record the delimiter {\tt:} preceding +the column list and the delimiter {\tt:=} following the column list +cannot be omitted.) + +Each element $a_{ij}$ of the matrix data block (where $1\leq i\leq m$, +$1\leq j\leq n$) corresponds to 2-tuple $(r_i,c_j)$. If $a_{ij}$ is the +plus sign ({\tt+}), that 2-tuple (or a longer $n$-tuple, if a slice is +used) is included in the elemental set. Otherwise, if $a_{ij}$ is the +minus sign ({\tt-}), that 2-tuple is not included in the elemental set. + +Since the matrix data record defines 2-tuples, either the elemental set +should consist of 2-tuples or the slice currently used should be +2-dimensional. + +\newpage + +\subsection{Transposed matrix data record} + +The {\it transposed matrix data record} has the following syntactic +form: +$$\begin{array}{cccccc} +\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +(In this case the delimiter {\tt:} following the keyword {\tt(tr)} is +optional and may be omitted.) + +This data record is completely analogous to the matrix data record (see +above) with only exception that in this case each element $a_{ij}$ of +the matrix corresponds to 2-tuple $(c_j,r_i)$ rather than $(r_i,c_j)$. + +Being once specified the {\tt(tr)} indicator affects all subsequent +data records until either a slice or the end of data block is +encountered. + +\section{Parameter data block} + +\noindent +\framebox[468pt][l]{ +\parbox[c][88pt]{468pt}{ +\hspace{6pt} {\tt param} {\it name} {\tt,} {\it record} {\tt,} \dots +{\tt,} {\it record} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\it name} {\tt default} {\it value} {\tt,} +{\it record} {\tt,} \dots {\tt,} {\it record} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\tt:} {\it tabbing-data} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\tt default} {\it value} {\tt:} +{\it tabbing-data} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the parameter; + +\noindent +{\it value} is an optional default value of the parameter; + +\noindent +{\it record}, \dots, {\it record} are data records; + +\noindent +{\it tabbing-data} specifies parameter data in the tabbing format. + +\noindent +Commae preceding data records may be omitted. + +\para{Data records} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt :=}]\hspace*{0pt}\\ +is a non-significant data record, which may be used freely to improve +readability; +\item[{\tt[} {\it slice} {\tt]}]\hspace*{0pt}\\ +specifies a slice; +\item[{\it plain-data}]\hspace*{0pt}\\ +specifies parameter data in the plain format; +\item[{\tt:} {\it tabular-data}]\hspace*{0pt}\\ +specifies parameter data in the tabular format; +\item[{\tt(tr)} {\tt:} {\it tabular-data}]\hspace*{0pt}\\ +specifies set data in the transposed tabular format. (In this case the +colon following the keyword {\tt(tr)} may be omitted.) +\end{description} + +\vspace*{-8pt} + +\para{Examples} + +\begin{verbatim} +param T := 4; +param month := 1 Jan 2 Feb 3 Mar 4 Apr 5 May; +param month := [1] 'Jan', [2] 'Feb', [3] 'Mar', [4] 'Apr', [5] 'May'; +param init_stock := iron 7.32 nickel 35.8; +param init_stock [*] iron 7.32, nickel 35.8; +param cost [iron] .025 [nickel] .03; +param value := iron -.1, nickel .02; +param : init_stock cost value := + iron 7.32 .025 -.1 + nickel 35.8 .03 .02 ; +param : raw : init stock cost value := + iron 7.32 .025 -.1 + nickel 35.8 .03 .02 ; +param demand default 0 (tr) + : FRA DET LAN WIN STL FRE LAF := + bands 300 . 100 75 . 225 250 + coils 500 750 400 250 . 850 500 + plate 100 . . 50 200 . 250 ; +param trans_cost := + [*,*,bands]: FRA DET LAN WIN STL FRE LAF := + GARY 30 10 8 10 11 71 6 + CLEV 22 7 10 7 21 82 13 + PITT 19 11 12 10 25 83 15 + [*,*,coils]: FRA DET LAN WIN STL FRE LAF := + GARY 39 14 11 14 16 82 8 + CLEV 27 9 12 9 26 95 17 + PITT 24 14 17 13 28 99 20 + [*,*,plate]: FRA DET LAN WIN STL FRE LAF := + GARY 41 15 12 16 17 86 8 + CLEV 29 9 13 9 28 99 18 + PITT 26 14 17 13 31 104 20 ; +\end{verbatim} + +The {\it parameter data block} is used to specify complete data for a +parameter (or parameters, if data are specified in the tabbing format). + +Data blocks can be specified only for non-computable parameters, i.e. +for parameters, which have no assign attribute ({\tt:=}) in the +corresponding parameter statements. + +Data defined in the parameter data block are coded as a sequence of +data records described below. Additionally the data block can be +provided with the optional {\tt default} attribute, which specifies a +default numeric or symbolic value of the parameter (parameters). This +default value is assigned to the parameter or its members when +no appropriate value is defined in the parameter data block. The +{\tt default} attribute cannot be used, if it is already specified in +the corresponding parameter statement. + +\subsection{Assign data record} + +The {\it assign data record} ({\tt:=}) is a non-signficant element. +It may be used for improving readability of data blocks. + +\subsection{Slice data record} + +The {\it slice data record} is a control record, which specifies a +{\it slice} of the parameter array. It has the following syntactic +form: +$$\mbox{{\tt[} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt]}}$$ +where $s_1$, $s_2$, \dots, $s_n$ are components of the slice. + +Each component of the slice can be a number or symbol or the asterisk +({\tt*}). The number of components in the slice should be the same as +the dimension of the parameter. For instance, if the parameter is a +4-dimensional array, the slice should have four components. The number +of asterisks in the slice is called the {\it slice dimension}. + +The effect of using slices is the following. If a $m$-dimensional slice +(i.e. a slice having $m$ asterisks) is specified in the data block, all +subsequent data records should specify subscripts of the parameter +members as if the parameter were $m$-dimensional, not $n$-dimensional. + +Whenever $m$ subscripts are encountered, each asterisk in the slice is +replaced by corresponding subscript that gives $n$ subscripts, which +define the actual parameter member. For example, if the slice +$[a,*,1,2,*]$ is in effect, and subscripts 3 and $b$ are encountered in +a subsequent data record, the complete subscript list used to choose a +parameter member is $[a,3,1,2,b]$. + +It is allowed to specify a slice having no asterisks. Such slice itself +defines a complete subscript list, in which case the next data record +should define only a single value of corresponding parameter member. + +Being once specified the slice effects until either a new slice or the +end of data block is encountered. Note that if no slice is specified in +the data block, one, components of which are all asterisks, is assumed. + +\subsection{Plain data record} + +The {\it plain data record} defines a subscript list and a single value +in the plain format. This record has the following syntactic form: +$$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$ {\tt,} $v$}$$ +where $t_1$, $t_2$, \dots, $t_n$ are subscripts, and $v$ is a value. +Each subscript as well as the value can be a number or symbol. Commae +following subscripts are optional and may be omitted. + +In case of 0-dimensional parameter or slice the plain data record has +no subscripts and consists of a single value only. + +\subsection{Tabular data record} + +The {\it tabular data record} defines several values, where each value +is provided with two subscripts. This record has the following +syntactic form: +$$\begin{array}{cccccc} +\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +where $r_1$, $r_2$, \dots, $r_m$ are numbers and/or symbols +corresponding to rows of the table; $c_1$, $c_2$, \dots, $c_n$ are +numbers and/or symbols corresponding to columns of the table, $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ are table elements. Each element can be a +number or symbol or the single decimal point ({\tt.}). (In this data +record the delimiter {\tt:} preceding the column list and the delimiter +{\tt:=} following the column list cannot be omitted.) + +Each element $a_{ij}$ of the tabular data block ($1\leq i\leq m$, +$1\leq j\leq n$) defines two subscripts, where the first subscript is +$r_i$, and the second one is $c_j$. These subscripts are used in +conjunction with the current slice to form the complete subscript list +that identifies a particular member of the parameter array. If $a_{ij}$ +is a number or symbol, this value is assigned to the parameter member. +However, if $a_{ij}$ is the single decimal point, the member is +assigned a default value specified either in the parameter data block +or in the parameter statement, or, if no default value is specified, +the member remains undefined. + +Since the tabular data record provides two subscripts for each value, +either the parameter or the slice currently used should be +2-dimensional. + +\subsection{Transposed tabular data record} + +The {\it transposed tabular data record} has the following syntactic +form: +$$\begin{array}{cccccc} +\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +(In this case the delimiter {\tt:} following the keyword {\tt(tr)} is +optional and may be omitted.) + +This data record is completely analogous to the tabular data record +(see above) with only exception that the first subscript defined by +element $a_{ij}$ is $c_j$ while the second one is $r_i$. + +Being once specified the {\tt(tr)} indicator affects all subsequent +data records until either a slice or the end of data block is +encountered. + +\newpage + +\subsection{Tabbing data format} + +The parameter data block in the {\it tabbing format} has the following +syntactic form: +$$ +\begin{array}{*{8}{l}} +\multicolumn{4}{l} +{{\tt param}\ {\tt default}\ value\ {\tt :}\ s\ {\tt :}}& +p_1\ \ \verb|,|&p_2\ \ \verb|,|&\dots\ \verb|,|&p_r\ \ \verb|:=|\\ +r_{11}\ \verb|,|& r_{12}\ \verb|,|& \dots\ \verb|,|& r_{1n}\ \verb|,|& +a_{11}\ \verb|,|& a_{12}\ \verb|,|& \dots\ \verb|,|& a_{1r}\ \verb|,|\\ +r_{21}\ \verb|,|& r_{22}\ \verb|,|& \dots\ \verb|,|& r_{2n}\ \verb|,|& +a_{21}\ \verb|,|& a_{22}\ \verb|,|& \dots\ \verb|,|& a_{2r}\ \verb|,|\\ +\dots & \dots & \dots & \dots & \dots & \dots & \dots & \dots \\ +r_{m1}\ \verb|,|& r_{m2}\ \verb|,|& \dots\ \verb|,|& r_{mn}\ \verb|,|& +a_{m1}\ \verb|,|& a_{m2}\ \verb|,|& \dots\ \verb|,|& a_{mr}\ \verb|;|\\ +\end{array} +$$ + +1. The keyword {\tt default} may be omitted along with a value +following it. + +2. Symbolic name $s$ may be omitted along with the colon following it. + +3. All comae are optional and may be omitted. + +The data block in the tabbing format shown above is exactly equivalent +to the following data blocks: + +\verb|set| $s$\ \verb|:=|\ $ +\verb|(|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|) | +\verb|(|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|) | +\dots +\verb| (|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|);|$ + +\verb|param| $p_1$\ \verb|default|\ $value$\ \verb|:=| + +$\verb| | +\verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{11} +\verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{21} +\verb| |\dots +\verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{m1} +\verb|;| +$ + +\verb|param| $p_2$\ \verb|default|\ $value$\ \verb|:=| + +$\verb| | +\verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{12} +\verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{22} +\verb| |\dots +\verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{m2} +\verb|;| +$ + +\verb| |.\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ . + +\verb|param| $p_r$\ \verb|default|\ $value$\ \verb|:=| + +$\verb| | +\verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{1r} +\verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{2r} +\verb| |\dots +\verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{mr} +\verb|;| +$ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\appendix + +\chapter{Using suffixes} + +\vspace*{-12pt} + +Suffixes can be used to retrieve additional values associated with +model variables, constraints, and objectives. + +A {\it suffix} consists of a period ({\tt.}) followed by a non-reserved +keyword. For example, if {\tt x} is a two-dimensional variable, +{\tt x[i,j].lb} is a numeric value equal to the lower bound of +elemental variable {\tt x[i,j]}, which (value) can be used everywhere +in expressions like a numeric parameter. + +For model variables suffixes have the following meaning: + +\begin{tabular}{@{}ll@{}} +{\tt.lb}&lower bound\\ +{\tt.ub}&upper bound\\ +{\tt.status}&status in the solution:\\ +&0 --- undefined\\ +&1 --- basic\\ +&2 --- non-basic on lower bound\\ +&3 --- non-basic on upper bound\\ +&4 --- non-basic free (unbounded) variable\\ +&5 --- non-basic fixed variable\\ +{\tt.val}&primal value in the solution\\ +{\tt.dual}&dual value (reduced cost) in the solution\\ +\end{tabular} + +For model constraints and objectives suffixes have the following +meaning: + +\begin{tabular}{@{}ll@{}} +{\tt.lb}&lower bound of the linear form\\ +{\tt.ub}&upper bound of the linear form\\ +{\tt.status}&status in the solution:\\ +&0 --- undefined\\ +&1 --- non-active\\ +&2 --- active on lower bound\\ +&3 --- active on upper bound\\ +&4 --- active free (unbounded) row\\ +&5 --- active equality constraint\\ +{\tt.val}&primal value of the linear form in the solution\\ +{\tt.dual}&dual value (reduced cost) of the linear form in the +solution\\ +\end{tabular} + +Note that suffixes {\tt.status}, {\tt.val}, and {\tt.dual} can be used +only below the solve statement. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Date and time functions} + +\noindent\hfil +\begin{tabular}{c} +by Andrew Makhorin \verb|<mao@gnu.org>|\\ +and Heinrich Schuchardt \verb|<heinrich.schuchardt@gmx.de>|\\ +\end{tabular} + +\section{Obtaining current calendar time} +\label{gmtime} + +To obtain the current calendar time in MathProg there exists the +function {\tt gmtime}. It has no arguments and returns the number of +seconds elapsed since 00:00:00 on January 1, 1970, Coordinated +Universal Time (UTC). For example: + +\begin{verbatim} + param utc := gmtime(); +\end{verbatim} + +MathProg has no function to convert UTC time returned by the function +{\tt gmtime} to {\it local} calendar times. Thus, if you need to +determine the current local calendar time, you have to add to the UTC +time returned the time offset from UTC expressed in seconds. For +example, the time in Berlin during the winter is one hour ahead of UTC +that corresponds to the time offset +1~hour~= +3600~secs, so the +current winter calendar time in Berlin may be determined as follows: + +\begin{verbatim} + param now := gmtime() + 3600; +\end{verbatim} + +\noindent Similarly, the summer time in Chicago (Central Daylight Time) +is five hours behind UTC, so the corresponding current local calendar +time may be determined as follows: + +\begin{verbatim} + param now := gmtime() - 5 * 3600; +\end{verbatim} + +Note that the value returned by {\tt gmtime} is volatile, i.e. being +called several times this function may return different values. + +\section{Converting character string to calendar time} +\label{str2time} + +The function {\tt str2time(}{\it s}{\tt,} {\it f}{\tt)} converts a +character string (timestamp) specified by its first argument {\it s}, +which should be a symbolic expression, to the calendar time suitable +for arithmetic calculations. The conversion is controlled by the +specified format string {\it f} (the second argument), which also +should be a symbolic expression. + +\newpage + +The result of conversion returned by {\tt str2time} has the same +meaning as values returned by the function {\tt gmtime} (see Subsection +\ref{gmtime}, page \pageref{gmtime}). Note that {\tt str2time} does +{\tt not} correct the calendar time returned for the local timezone, +i.e. being applied to 00:00:00 on January 1, 1970 it always returns 0. + +For example, the model statements: + +\begin{verbatim} + param s, symbolic, := "07/14/98 13:47"; + param t := str2time(s, "%m/%d/%y %H:%M"); + display t; +\end{verbatim} + +\noindent produce the following printout: + +\begin{verbatim} + t = 900424020 +\end{verbatim} + +\noindent where the calendar time printed corresponds to 13:47:00 on +July 14, 1998. + +The format string passed to the function {\tt str2time} consists of +conversion specifiers and ordinary characters. Each conversion +specifier begins with a percent ({\tt\%}) character followed by a +letter. + +The following conversion specifiers may be used in the format string: + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%b}&The abbreviated month name (case insensitive). At least three +first letters of the month name should appear in the input string.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%d}&The day of the month as a decimal number (range 1 to 31). +Leading zero is permitted, but not required.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%h}&The same as {\tt\%b}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%H}&The hour as a decimal number, using a 24-hour clock (range 0 +to 23). Leading zero is permitted, but not required.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%m}&The month as a decimal number (range 1 to 12). Leading zero is +permitted, but not required.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%M}&The minute as a decimal number (range 0 to 59). Leading zero +is permitted, but not required.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%S}&The second as a decimal number (range 0 to 60). Leading zero +is permitted, but not required.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%y}&The year without a century as a decimal number (range 0 to 99). +Leading zero is permitted, but not required. Input values in the range +0 to 68 are considered as the years 2000 to 2068 while the values 69 to +99 as the years 1969 to 1999.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%z}&The offset from GMT in ISO 8601 format.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%\%}&A literal {\tt\%} character.\\ +\end{tabular} + +All other (ordinary) characters in the format string should have a +matching character in the input string to be converted. Exceptions are +spaces in the input string which can match zero or more space +characters in the format string. + +\newpage + +If some date and/or time component(s) are missing in the format and, +therefore, in the input string, the function {\tt str2time} uses their +default values corresponding to 00:00:00 on January 1, 1970, that is, +the default value of the year is 1970, the default value of the month +is January, etc. + +The function {\tt str2time} is applicable to all calendar times in the +range 00:00:00 on January 1, 0001 to 23:59:59 on December 31, 4000 of +the Gregorian calendar. + +\section{Converting calendar time to character string} +\label{time2str} + +The function {\tt time2str(}{\it t}{\tt,} {\it f}{\tt)} converts the +calendar time specified by its first argument {\it t}, which should be +a numeric expression, to a character string (symbolic value). The +conversion is controlled by the specified format string {\it f} (the +second argument), which should be a symbolic expression. + +The calendar time passed to {\tt time2str} has the same meaning as +values returned by the function {\tt gmtime} (see Subsection +\ref{gmtime}, page \pageref{gmtime}). Note that {\tt time2str} does +{\it not} correct the specified calendar time for the local timezone, +i.e. the calendar time 0 always corresponds to 00:00:00 on January 1, +1970. + +For example, the model statements: + +\begin{verbatim} + param s, symbolic, := time2str(gmtime(), "%FT%TZ"); + display s; +\end{verbatim} + +\noindent may produce the following printout: + +\begin{verbatim} + s = '2008-12-04T00:23:45Z' +\end{verbatim} + +\noindent which is a timestamp in the ISO format. + +The format string passed to the function {\tt time2str} consists of +conversion specifiers and ordinary characters. Each conversion +specifier begins with a percent ({\tt\%}) character followed by a +letter. + +The following conversion specifiers may be used in the format string: + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%a}&The abbreviated (2-character) weekday name.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%A}&The full weekday name.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%b}&The abbreviated (3-character) month name.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%B}&The full month name.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%C}&The century of the year, that is the greatest integer not +greater than the year divided by~100.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%d}&The day of the month as a decimal number (range 01 to 31).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%D}&The date using the format \verb|%m/%d/%y|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%e}&The day of the month like with \verb|%d|, but padded with +blank rather than zero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%F}&The date using the format \verb|%Y-%m-%d|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%g}&The year corresponding to the ISO week number, but without the +century (range 00 to~99). This has the same format and value as +\verb|%y|, except that if the ISO week number (see \verb|%V|) belongs +to the previous or next year, that year is used instead.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%G}&The year corresponding to the ISO week number. This has the +same format and value as \verb|%Y|, except that if the ISO week number +(see \verb|%V|) belongs to the previous or next year, that year is used +instead. +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%h}&The same as \verb|%b|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%H}&The hour as a decimal number, using a 24-hour clock (range 00 +to 23).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%I}&The hour as a decimal number, using a 12-hour clock (range 01 +to 12).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%j}&The day of the year as a decimal number (range 001 to 366).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%k}&The hour as a decimal number, using a 24-hour clock like +\verb|%H|, but padded with blank rather than zero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%l}&The hour as a decimal number, using a 12-hour clock like +\verb|%I|, but padded with blank rather than zero. +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%m}&The month as a decimal number (range 01 to 12).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%M}&The minute as a decimal number (range 00 to 59).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%p}&Either {\tt AM} or {\tt PM}, according to the given time value. +Midnight is treated as {\tt AM} and noon as {\tt PM}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%P}&Either {\tt am} or {\tt pm}, according to the given time value. +Midnight is treated as {\tt am} and noon as {\tt pm}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%R}&The hour and minute in decimal numbers using the format +\verb|%H:%M|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%S}&The second as a decimal number (range 00 to 59).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%T}&The time of day in decimal numbers using the format +\verb|%H:%M:%S|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%u}&The day of the week as a decimal number (range 1 to 7), Monday +being 1.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%U}&The week number of the current year as a decimal number (range +00 to 53), starting with the first Sunday as the first day of the first +week. Days preceding the first Sunday in the year are considered to be +in week 00. +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%V}&The ISO week number as a decimal number (range 01 to 53). ISO +weeks start with Monday and end with Sunday. Week 01 of a year is the +first week which has the majority of its days in that year; this is +equivalent to the week containing January 4. Week 01 of a year can +contain days from the previous year. The week before week 01 of a year +is the last week (52 or 53) of the previous year even if it contains +days from the new year. In other word, if 1 January is Monday, Tuesday, +Wednesday or Thursday, it is in week 01; if 1 January is Friday, +Saturday or Sunday, it is in week 52 or 53 of the previous year.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%w}&The day of the week as a decimal number (range 0 to 6), Sunday +being 0.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%W}&The week number of the current year as a decimal number (range +00 to 53), starting with the first Monday as the first day of the first +week. Days preceding the first Monday in the year are considered to be +in week 00.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%y}&The year without a century as a decimal number (range 00 to +99), that is the year modulo~100.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%Y}&The year as a decimal number, using the Gregorian calendar.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%\%}&A literal \verb|%| character.\\ +\end{tabular} + +All other (ordinary) characters in the format string are simply copied +to the resultant string. + +The first argument (calendar time) passed to the function {\tt time2str} +should be in the range from $-62135596800$ to $+64092211199$ that +corresponds to the period from 00:00:00 on January 1, 0001 to 23:59:59 +on December 31, 4000 of the Gregorian calendar. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Table drivers} +\label{drivers} + +\noindent\hfil +\begin{tabular}{c} +by Andrew Makhorin \verb|<mao@gnu.org>|\\ +and Heinrich Schuchardt \verb|<heinrich.schuchardt@gmx.de>|\\ +\end{tabular} + +\bigskip\bigskip + +The {\it table driver} is a program module which provides transmitting +data between MathProg model objects and data tables. + +Currently the GLPK package has four table drivers: + +\vspace*{-8pt} + +\begin{itemize} +\item built-in CSV table driver; +\item built-in xBASE table driver; +\item ODBC table driver; +\item MySQL table driver. +\end{itemize} + +\vspace*{-8pt} + +\section{CSV table driver} + +The CSV table driver assumes that the data table is represented in the +form of a plain text file in the CSV (comma-separated values) file +format as described below. + +To choose the CSV table driver its name in the table statement should +be specified as \verb|"CSV"|, and the only argument should specify the +name of a plain text file containing the table. For example: + +\begin{verbatim} + table data IN "CSV" "data.csv": ... ; +\end{verbatim} + +The filename suffix may be arbitrary, however, it is recommended to use +the suffix `\verb|.csv|'. + +On reading input tables the CSV table driver provides an implicit field +named \verb|RECNO|, which contains the current record number. This +field can be specified in the input table statement as if there were +the actual field named \verb|RECNO| in the CSV file. For example: + +\begin{verbatim} + table list IN "CSV" "list.csv": num <- [RECNO], ... ; +\end{verbatim} + +\newpage + +\subsection*{CSV format\footnote{This material is based on the RFC +document 4180.}} + +The CSV (comma-separated values) format is a plain text file format +defined as follows. + +1. Each record is located on a separate line, delimited by a line +break. For example: + +\begin{verbatim} + aaa,bbb,ccc\n + xxx,yyy,zzz\n +\end{verbatim} + +\noindent +where \verb|\n| means the control character \verb|LF| ({\tt 0x0A}). + +2. The last record in the file may or may not have an ending line +break. For example: + +\begin{verbatim} + aaa,bbb,ccc\n + xxx,yyy,zzz +\end{verbatim} + +3. There should be a header line appearing as the first line of the +file in the same format as normal record lines. This header should +contain names corresponding to the fields in the file. The number of +field names in the header line should be the same as the number of +fields in the records of the file. For example: + +\begin{verbatim} + name1,name2,name3\n + aaa,bbb,ccc\n + xxx,yyy,zzz\n +\end{verbatim} + +4. Within the header and each record there may be one or more fields +separated by commas. Each line should contain the same number of fields +throughout the file. Spaces are considered as part of a field and +therefore not ignored. The last field in the record should not be +followed by a comma. For example: + +\begin{verbatim} + aaa,bbb,ccc\n +\end{verbatim} + +5. Fields may or may not be enclosed in double quotes. For example: + +\begin{verbatim} + "aaa","bbb","ccc"\n + zzz,yyy,xxx\n +\end{verbatim} + +6. If a field is enclosed in double quotes, each double quote which is +part of the field should be coded twice. For example: + +\begin{verbatim} + "aaa","b""bb","ccc"\n +\end{verbatim} + +\para{Example} + +\begin{verbatim} +FROM,TO,DISTANCE,COST +Seattle,New-York,2.5,0.12 +Seattle,Chicago,1.7,0.08 +Seattle,Topeka,1.8,0.09 +San-Diego,New-York,2.5,0.15 +San-Diego,Chicago,1.8,0.10 +San-Diego,Topeka,1.4,0.07 +\end{verbatim} + +\newpage + +\section{xBASE table driver} + +The xBASE table driver assumes that the data table is stored in the +.dbf file format. + +To choose the xBASE table driver its name in the table statement should +be specified as \verb|"xBASE"|, and the first argument should specify +the name of a .dbf file containing the table. For the output table there +should be the second argument defining the table format in the form +\verb|"FF...F"|, where \verb|F| is either {\tt C({\it n})}, +which specifies a character field of length $n$, or +{\tt N({\it n}{\rm [},{\it p}{\rm ]})}, which specifies a numeric field +of length $n$ and precision $p$ (by default $p$ is 0). + +The following is a simple example which illustrates creating and +reading a .dbf file: + +\begin{verbatim} +table tab1{i in 1..10} OUT "xBASE" "foo.dbf" + "N(5)N(10,4)C(1)C(10)": 2*i+1 ~ B, Uniform(-20,+20) ~ A, + "?" ~ FOO, "[" & i & "]" ~ C; +set S, dimen 4; +table tab2 IN "xBASE" "foo.dbf": S <- [B, C, RECNO, A]; +display S; +end; +\end{verbatim} + +\section{ODBC table driver} + +The ODBC table driver allows connecting to SQL databases using an +implementation of the ODBC interface based on the Call Level Interface +(CLI).\footnote{The corresponding software standard is defined in +ISO/IEC 9075-3:2003.} + +\para{Debian GNU/Linux.} +Under Debian GNU/Linux the ODBC table driver uses the iODBC +package,\footnote{See {\tt<http://www.iodbc.org/>}.} which should be +installed before building the GLPK package. The installation can be +effected with the following command: + +\begin{verbatim} + sudo apt-get install libiodbc2-dev +\end{verbatim} + +Note that on configuring the GLPK package to enable using the iODBC +library the option `\verb|--enable-odbc|' should be passed to the +configure script. + +The individual databases should be entered for systemwide usage in +\verb|/etc/odbc.ini| and\linebreak \verb|/etc/odbcinst.ini|. Database +connections to be used by a single user are specified by files in the +home directory (\verb|.odbc.ini| and \verb|.odbcinst.ini|). + +\para{Microsoft Windows.} +Under Microsoft Windows the ODBC table driver uses the Microsoft ODBC +library. To enable this feature the symbol: + +\begin{verbatim} + #define ODBC_DLNAME "odbc32.dll" +\end{verbatim} + +\noindent +should be defined in the GLPK configuration file `\verb|config.h|'. + +Data sources can be created via the Administrative Tools from the +Control Panel. + +To choose the ODBC table driver its name in the table statement should +be specified as \verb|'ODBC'| or \verb|'iODBC'|. + +\newpage + +The argument list is specified as follows. + +The first argument is the connection string passed to the ODBC library, +for example: + +\verb|'DSN=glpk;UID=user;PWD=password'|, or + +\verb|'DRIVER=MySQL;DATABASE=glpkdb;UID=user;PWD=password'|. + +Different parts of the string are separated by semicolons. Each part +consists of a pair {\it fieldname} and {\it value} separated by the +equal sign. Allowable fieldnames depend on the ODBC library. Typically +the following fieldnames are allowed: + +\verb|DATABASE | database; + +\verb|DRIVER | ODBC driver; + +\verb|DSN | name of a data source; + +\verb|FILEDSN | name of a file data source; + +\verb|PWD | user password; + +\verb|SERVER | database; + +\verb|UID | user name. + +The second argument and all following are considered to be SQL +statements + +SQL statements may be spread over multiple arguments. If the last +character of an argument is a semicolon this indicates the end of +a SQL statement. + +The arguments of a SQL statement are concatenated separated by space. +The eventual trailing semicolon will be removed. + +All but the last SQL statement will be executed directly. + +For IN-table the last SQL statement can be a SELECT command starting +with the capitalized letters \verb|'SELECT '|. If the string does not +start with \verb|'SELECT '| it is considered to be a table name and a +SELECT statement is automatically generated. + +For OUT-table the last SQL statement can contain one or multiple +question marks. If it contains a question mark it is considered a +template for the write routine. Otherwise the string is considered a +table name and an INSERT template is automatically generated. + +The writing routine uses the template with the question marks and +replaces the first question mark by the first output parameter, the +second question mark by the second output parameter and so forth. Then +the SQL command is issued. + +The following is an example of the output table statement: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS result;' + 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'INSERT INTO result 'VALUES ( 4, ?, ? )' : + l ~ LOC, quantity[l] ~ QUAN; +\end{verbatim} + +\newpage + +\noindent +Alternatively it could be written as follows: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS result;' + 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'result' : + l ~ LOC, quantity[l] ~ QUAN, 4 ~ ID; +\end{verbatim} + +Using templates with `\verb|?|' supports not only INSERT, but also +UPDATE, DELETE, etc. For example: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'UPDATE result SET DATE = ' & date & ' WHERE ID = 4;' + 'UPDATE result SET QUAN = ? WHERE LOC = ? AND ID = 4' : + quantity[l], l; +\end{verbatim} + +\section{MySQL table driver} + +The MySQL table driver allows connecting to MySQL databases. + +\para{Debian GNU/Linux.} +Under Debian GNU/Linux the MySQL table driver uses the MySQL +package,\footnote{For download development files see +{\tt<http://dev.mysql.com/downloads/mysql/>}.} which should be +installed before building the GLPK package. The installation can be +effected with the following command: + +\begin{verbatim} + sudo apt-get install libmysqlclient15-dev +\end{verbatim} + +Note that on configuring the GLPK package to enable using the MySQL +library the option `\verb|--enable-mysql|' should be passed to the +configure script. + +\para{Microsoft Windows.} +Under Microsoft Windows the MySQL table driver also uses the MySQL +library. To enable this feature the symbol: + +\begin{verbatim} + #define MYSQL_DLNAME "libmysql.dll" +\end{verbatim} + +\noindent +should be defined in the GLPK configuration file `\verb|config.h|'. + +To choose the MySQL table driver its name in the table statement should +be specified as \verb|'MySQL'|. + +The argument list is specified as follows. + +The first argument specifies how to connect the data base in the DSN +style, for example: + +\verb|'Database=glpk;UID=glpk;PWD=gnu'|. + +Different parts of the string are separated by semicolons. Each part +consists of a pair {\it fieldname} and {\it value} separated by the +equal sign. The following fieldnames are allowed: + +\newpage + +\verb|Server | server running the database (defaulting to localhost); + +\verb|Database | name of the database; + +\verb|UID | user name; + +\verb|PWD | user password; + +\verb|Port | port used by the server (defaulting to 3306). + +The second argument and all following are considered to be SQL +statements. + +SQL statements may be spread over multiple arguments. If the last +character of an argument is a semicolon this indicates the end of +a SQL statement. + +The arguments of a SQL statement are concatenated separated by space. +The eventual trailing semicolon will be removed. + +All but the last SQL statement will be executed directly. + +For IN-table the last SQL statement can be a SELECT command starting +with the capitalized letters \verb|'SELECT '|. If the string does not +start with \verb|'SELECT '| it is considered to be a table name and a +SELECT statement is automatically generated. + +For OUT-table the last SQL statement can contain one or multiple +question marks. If it contains a question mark it is considered a +template for the write routine. Otherwise the string is considered a +table name and an INSERT template is automatically generated. + +The writing routine uses the template with the question marks and +replaces the first question mark by the first output parameter, the +second question mark by the second output parameter and so forth. Then +the SQL command is issued. + +The following is an example of the output table statement: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS result;' + 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'INSERT INTO result VALUES ( 4, ?, ? )' : + l ~ LOC, quantity[l] ~ QUAN; +\end{verbatim} + +\noindent +Alternatively it could be written as follows: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS result;' + 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'result' : + l ~ LOC, quantity[l] ~ QUAN, 4 ~ ID; +\end{verbatim} + +\newpage + +Using templates with `\verb|?|' supports not only INSERT, but also +UPDATE, DELETE, etc. For example: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'UPDATE result SET DATE = ' & date & ' WHERE ID = 4;' + 'UPDATE result SET QUAN = ? WHERE LOC = ? AND ID = 4' : + quantity[l], l; +\end{verbatim} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Solving models with glpsol} + +The GLPK package\footnote{{\tt http://www.gnu.org/software/glpk/}} +includes the program {\tt glpsol}, a stand-alone LP/MIP solver. This +program can be launched from the command line or from the shell to +solve models written in the GNU MathProg modeling language. + +To tell the solver that the input file contains a model description you +need to specify the option \verb|--model| in the command line. +For example: + +\begin{verbatim} + glpsol --model foo.mod +\end{verbatim} + +Sometimes it is necessary to use the data section placed in a separate +file, in which case you may use the following command: + +\begin{verbatim} + glpsol --model foo.mod --data foo.dat +\end{verbatim} + +\noindent Note that if the model file also contains the data section, +that section is ignored. + +It is also allowed to specify more than one file containing the data +section, for example: + +\begin{verbatim} + glpsol --model foo.mod --data foo1.dat --data foo2.dat +\end{verbatim} + +If the model description contains some display and/or printf +statements, by default the output is sent to the terminal. If you need +to redirect the output to a file, you may use the following command: + +\begin{verbatim} + glpsol --model foo.mod --display foo.out +\end{verbatim} + +If you need to look at the problem, which has been generated by the +model translator, you may use the option \verb|--wlp| as follows: + +\begin{verbatim} + glpsol --model foo.mod --wlp foo.lp +\end{verbatim} + +\noindent In this case the problem data is written to file +\verb|foo.lp| in CPLEX LP format suitable for visual analysis. + +Sometimes it is needed merely to check the model description not +solving the generated problem instance. In this case you may specify +the option \verb|--check|, for example: + +\begin{verbatim} + glpsol --check --model foo.mod --wlp foo.lp +\end{verbatim} + +\newpage + +If you need to write a numeric solution obtained by the solver to +a file, you may use the following command: + +\begin{verbatim} + glpsol --model foo.mod --output foo.sol +\end{verbatim} + +\noindent in which case the solution is written to file \verb|foo.sol| +in a plain text format suitable for visual analysis. + +The complete list of the \verb|glpsol| options can be found in the +GLPK reference manual included in the GLPK distribution. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Example model description} + +\section{Model description written in MathProg} + +Below here is a complete example of the model description written in +the GNU MathProg modeling language. + +\bigskip + +\begin{verbatim} +# A TRANSPORTATION PROBLEM +# +# This problem finds a least cost shipping schedule that meets +# requirements at markets and supplies at factories. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* canning plants */ + +set J; +/* markets */ + +param a{i in I}; +/* capacity of plant i in cases */ + +param b{j in J}; +/* demand at market j in cases */ + +param d{i in I, j in J}; +/* distance in thousands of miles */ + +param f; +/* freight in dollars per case per thousand miles */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* transport cost in thousands of dollars per case */ + +var x{i in I, j in J} >= 0; +/* shipment quantities in cases */ + +minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; +/* total transportation costs in thousands of dollars */ + +s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observe supply limit at plant i */ + +s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfy demand at market j */ + +data; + +set I := Seattle San-Diego; + +set J := New-York Chicago Topeka; + +param a := Seattle 350 + San-Diego 600; + +param b := New-York 325 + Chicago 300 + Topeka 275; + +param d : New-York Chicago Topeka := + Seattle 2.5 1.7 1.8 + San-Diego 2.5 1.8 1.4 ; + +param f := 90; + +end; +\end{verbatim} + +\newpage + +\section{Generated LP problem instance} + +Below here is the result of the translation of the example model +produced by the solver \verb|glpsol| and written in CPLEX LP format +with the option \verb|--wlp|. + +\medskip + +\begin{verbatim} +\* Problem: transp *\ + +Minimize + cost: + 0.225 x(Seattle,New~York) + 0.153 x(Seattle,Chicago) + + 0.162 x(Seattle,Topeka) + 0.225 x(San~Diego,New~York) + + 0.162 x(San~Diego,Chicago) + 0.126 x(San~Diego,Topeka) + +Subject To + supply(Seattle): + x(Seattle,New~York) + x(Seattle,Chicago) + + x(Seattle,Topeka) <= 350 + supply(San~Diego): + x(San~Diego,New~York) + x(San~Diego,Chicago) + + x(San~Diego,Topeka) <= 600 + demand(New~York): + x(Seattle,New~York) + x(San~Diego,New~York) >= 325 + demand(Chicago): + x(Seattle,Chicago) + x(San~Diego,Chicago) >= 300 + demand(Topeka): + x(Seattle,Topeka) + x(San~Diego,Topeka) >= 275 + +End +\end{verbatim} + +\section{Optimal LP solution} + +Below here is the optimal solution of the generated LP problem instance +found by the solver \verb|glpsol| and written in plain text format +with the option \verb|--output|. + +\medskip + +\begin{footnotesize} +\begin{verbatim} +Problem: transp +Rows: 6 +Columns: 6 +Non-zeros: 18 +Status: OPTIMAL +Objective: cost = 153.675 (MINimum) + + No. Row name St Activity Lower bound Upper bound Marginal +------ ------------ -- ------------- ------------- ------------- ------------- + 1 cost B 153.675 + 2 supply[Seattle] + NU 350 350 < eps + 3 supply[San-Diego] + B 550 600 + 4 demand[New-York] + NL 325 325 0.225 + 5 demand[Chicago] + NL 300 300 0.153 + 6 demand[Topeka] + NL 275 275 0.126 + + No. Column name St Activity Lower bound Upper bound Marginal +------ ------------ -- ------------- ------------- ------------- ------------- + 1 x[Seattle,New-York] + B 50 0 + 2 x[Seattle,Chicago] + B 300 0 + 3 x[Seattle,Topeka] + NL 0 0 0.036 + 4 x[San-Diego,New-York] + B 275 0 + 5 x[San-Diego,Chicago] + NL 0 0 0.009 + 6 x[San-Diego,Topeka] + B 275 0 + +End of output +\end{verbatim} +\end{footnotesize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section*{Acknowledgements} +\addcontentsline{toc}{chapter}{Acknowledgements} + +The authors would like to thank the following people, who kindly read, +commented, and corrected the draft of this document: + +\noindent Juan Carlos Borras \verb|<borras@cs.helsinki.fi>| + +\noindent Harley Mackenzie \verb|<hjm@bigpond.com>| + +\noindent Robbie Morrison \verb|<robbie@actrix.co.nz>| + +\end{document} diff --git a/resources/3rdparty/glpk-4.53/doc/graphs.pdf b/resources/3rdparty/glpk-4.53/doc/graphs.pdf new file mode 100644 index 0000000000000000000000000000000000000000..896dd7cd6c0ef05a34448aa05d00f9647a3ca929 GIT binary patch literal 214470 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 AzyJUM literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/doc/graphs.tex b/resources/3rdparty/glpk-4.53/doc/graphs.tex new file mode 100644 index 000000000..cddb7518e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/graphs.tex @@ -0,0 +1,4150 @@ +%* graphs.tex *% + +%*********************************************************************** +% This code is part of GLPK (GNU Linear Programming Kit). +% +% Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +% 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +% Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +% reserved. E-mail: <mao@gnu.org>. +% +% GLPK 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 3 of the License, or +% (at your option) any later version. +% +% GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +%*********************************************************************** + +\documentclass[11pt]{report} +\usepackage{amssymb} +\usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, +urlcolor=blue]{hyperref} +\usepackage{indentfirst} +\usepackage[all]{xy} + +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{8.5in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +\setlength{\itemsep}{\parskip} +\setlength{\parsep}{0pt} +\setlength{\leftmargini}{\parindent} +\renewcommand{\labelitemi}{---} + +\def\para#1{\noindent{\bf#1}} +\def\synopsis{\para{Synopsis}} +\def\description{\para{Description}} +\def\returns{\para{Returns}} + +\renewcommand\contentsname{\sf\bfseries Contents} +\renewcommand\chaptername{\sf\bfseries Chapter} +\renewcommand\appendixname{\sf\bfseries Appendix} + +\newenvironment{retlist} +{ \def\arraystretch{1.5} + \noindent + \begin{tabular}{@{}p{1in}@{}p{5.5in}@{}} +} +{\end{tabular}} + +\begin{document} + +\thispagestyle{empty} + +\begin{center} + +\vspace*{1.5in} + +\begin{huge} +\sf\bfseries GNU Linear Programming Kit +\end{huge} + +\vspace{0.5in} + +\begin{LARGE} +\sf Graph and Network Routines +\end{LARGE} + +\vspace{0.5in} + +\begin{LARGE} +\sf for GLPK Version 4.49 +\end{LARGE} + +\vspace{0.5in} +\begin{Large} +\sf (DRAFT, April 2013) +\end{Large} +\end{center} + +\newpage + +\vspace*{1in} + +\vfill + +\noindent +The GLPK package is part of the GNU Project released under the aegis of +GNU. + +\noindent +Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +reserved. + +\noindent +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +02110-1301, USA. + +\noindent +Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + +\noindent +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +entire resulting derived work is distributed under the terms of +a permission notice identical to this one. + +\noindent +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +{\setlength{\parskip}{0pt} +\tableofcontents +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Basic Graph API Routines} + +\section{Graph program object} + +In GLPK the base program object used to represent graphs and networks +is a directed graph (digraph). + +Formally, {\it digraph} (or simply, {\it graph}) is a pair $G=(V,A)$, +where $V$ is a set of {\it vertices}, and $A$ is a set +{\it arcs}.\footnote{$A$ may be a multiset.} Each arc $a\in A$ is an +ordered pair of vertices $a=(x,y)$, where $x\in V$ is called {\it tail +vertex} of arc $a$, and $y\in V$ is called its {\it head vertex}. + +Representation of a graph in the program includes three structs defined +by typedef in the header \verb|glpk.h|: + +\vspace*{-8pt} + +\begin{itemize} +\item \verb|glp_graph|, which represents the graph in a whole, + +\item \verb|glp_vertex|, which represents a vertex of the graph, and + +\item \verb|glp_arc|, which represents an arc of the graph. +\end{itemize} + +\vspace*{-8pt} + +All these three structs are ``semi-opaque'', i.e. the application +program can directly access their fields through pointers, however, +changing the fields directly is not allowed --- all changes should be +performed only with appropriate GLPK API routines. + +\newenvironment{comment} +{\addtolength{\leftskip}{16pt}\noindent} +{\par\addtolength{\leftskip}{-16pt}} + +\para{\bf glp\_graph.} The struct \verb|glp_graph| has the following +fields available to the application program: + +\noindent +\verb|char *name;| + +\begin{comment}Symbolic name assigned to the graph. It is a pointer to +a null terminated character string of length from 1 to 255 characters. +If no name is assigned to the graph, this field contains \verb|NULL|. +\end{comment} + +\noindent +\verb|int nv;| + +\begin{comment}The number of vertices in the graph, $nv\geq 0$. +\end{comment} + +\noindent +\verb|int na;| + +\begin{comment}The number of arcs in the graph, $na\geq 0$. +\end{comment} + +\newpage + +\noindent +\verb|glp_vertex **v;| + +\begin{comment}Pointer to an array containing the list of vertices. +Element $v[0]$ is not used. Element $v[i]$, $1\leq i\leq nv$, is a +pointer to $i$-th vertex of the graph. Note that on adding new vertices +to the graph the field $v$ may be altered due to reallocation. However, +pointers $v[i]$ are not changed while corresponding vertices exist in +the graph. +\end{comment} + +\noindent +\verb|int v_size;| + +\begin{comment}Size of vertex data blocks, in bytes, +$0\leq v\_size\leq 256$. (See also the field \verb|data| in the struct +\verb|glp_vertex|.) +\end{comment} + +\noindent +\verb|int a_size;| + +\begin{comment}Size of arc data blocks, in bytes, +$0\leq v\_size\leq 256$. (See also the field \verb|data| in the struct +\verb|glp_arc|.) +\end{comment} + +\para{\bf glp\_vertex.} The struct \verb|glp_vertex| has the following +fields available to the application program: + +\noindent +\verb|int i;| + +\begin{comment}Ordinal number of the vertex, $1\leq i\leq nv$. Note +that element $v[i]$ in the struct \verb|glp_graph| points to the vertex, +whose ordinal number is $i$. +\end{comment} + +\noindent +\verb|char *name;| + +\begin{comment}Symbolic name assigned to the vertex. It is a pointer to +a null terminated character string of length from 1 to 255 characters. +If no name is assigned to the vertex, this field contains \verb|NULL|. +\end{comment} + +\noindent +\verb|void *data;| + +\begin{comment}Pointer to a data block associated with the vertex. This +data block is automatically allocated on creating a new vertex and freed +on deleting the vertex. If $v\_size=0$, the block is not allocated, and +this field contains \verb|NULL|. +\end{comment} + +\noindent +\verb|void *temp;| + +\begin{comment}Working pointer, which may be used freely for any +purposes. The application program can change this field directly. +\end{comment} + +\noindent +\verb|glp_arc *in;| + +\begin{comment}Pointer to the (unordered) list of incoming arcs. If the +vertex has no incoming arcs, this field contains \verb|NULL|. +\end{comment} + +\noindent +\verb|glp_arc *out;| + +\begin{comment}Pointer to the (unordered) list of outgoing arcs. If the +vertex has no outgoing arcs, this field contains \verb|NULL|. +\end{comment} + +\para{\bf glp\_arc.} The struct \verb|glp_arc| has the following fields +available to the application program: + +\noindent +\verb|glp_vertex *tail;| + +\begin{comment}Pointer to a vertex, which is tail endpoint of the arc. +\end{comment} + +\noindent +\verb|glp_vertex *head;| + +\begin{comment}Pointer to a vertex, which is head endpoint of the arc. +\end{comment} + +\newpage + +\noindent +\verb|void *data;| + +\begin{comment}Pointer to a data block associated with the arc. This +data block is automatically allocated on creating a new arc and freed on +deleting the arc. If $v\_size=0$, the block is not allocated, and this +field contains \verb|NULL|. +\end{comment} + +\noindent +\verb|void *temp;| + +\begin{comment}Working pointer, which may be used freely for any +purposes. The application program can change this field directly. +\end{comment} + +\noindent +\verb|glp_arc *t_next;| + +\begin{comment}Pointer to another arc, which has the same tail endpoint +as this one. \verb|NULL| in this field indicates the end of the list of +outgoing arcs. +\end{comment} + +\noindent +\verb|glp_arc *h_next;| + +\begin{comment}Pointer to another arc, which has the same head endpoint +as this one. \verb|NULL| in this field indicates the end of the list of +incoming arcs. +\end{comment} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Graph creating and modifying routines} + +\subsection{glp\_create\_graph --- create graph} + +\synopsis + +\begin{verbatim} + glp_graph *glp_create_graph(int v_size, int a_size); +\end{verbatim} + +\description + +The routine \verb|glp_create_graph| creates a new graph, which +initially is empty, i.e. has no vertices and arcs. + +The parameter \verb|v_size| specifies the size of vertex data blocks, +in bytes, $0\leq v\_size\leq 256$. + +The parameter \verb|a_size| specifies the size of arc data blocks, in +bytes, $0\leq a\_size\leq 256$. + +\returns + +The routine returns a pointer to the graph object created. + +\subsection{glp\_set\_graph\_name --- assign (change) graph name} + +\synopsis + +\begin{verbatim} + void glp_set_graph_name(glp_graph *G, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_graph_name| assigns a symbolic name specified +by the character string \verb|name| (1 to 255 chars) to the graph. + +If the parameter \verb|name| is \verb|NULL| or an empty string, the +routine erases the existing symbolic name of the graph. + +\subsection{glp\_add\_vertices --- add new vertices to graph} + +\synopsis + +\begin{verbatim} + int glp_add_vertices(glp_graph *G, int nadd); +\end{verbatim} + +\description + +The routine \verb|glp_add_vertices| adds \verb|nadd| vertices to the +specified graph. New vertices are always added to the end of the vertex +list, so ordinal numbers of existing vertices remain unchanged. Note +that this operation may change the field \verb|v| in the struct +\verb|glp_graph| (pointer to the vertex array) due to reallocation. + +Being added each new vertex is isolated, i.e. has no incident arcs. + +If the size of vertex data blocks specified on creating the graph is +non-zero, the routine also allocates a memory block of that size for +each new vertex added, fills it by binary zeros, and stores a pointer +to it in the field \verb|data| of the struct \verb|glp_vertex|. +Otherwise, if the block size is zero, the field \verb|data| is set to +\verb|NULL|. + +\returns + +The routine \verb|glp_add_vertices| returns the ordinal number of the +first new vertex added to the graph. + +\subsection{glp\_set\_vertex\_name --- assign (change) vertex name} + +\synopsis + +\begin{verbatim} + void glp_set_vertex_name(glp_graph *G, int i, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_vertex_name| assigns a given symbolic name +(1 up to 255 characters) to \verb|i|-th vertex of the specified graph. + +If the parameter \verb|name| is \verb|NULL| or empty string, the +routine erases an existing name of \verb|i|-th vertex. + +\subsection{glp\_add\_arc --- add new arc to graph} + +\synopsis + +\begin{verbatim} + glp_arc *glp_add_arc(glp_graph *G, int i, int j); +\end{verbatim} + +\description + +The routine \verb|glp_add_arc| adds one new arc to the specified graph. + +The parameters \verb|i| and \verb|j| specify the ordinal numbers of, +resp., tail and head endpoints (vertices) of the arc. Note that +self-loops and multiple arcs are allowed. + +If the size of arc data blocks specified on creating the graph is +non-zero, the routine also allocates a memory block of that size, fills +it by binary zeros, and stores a pointer to it in the field \verb|data| +of the struct \verb|glp_arc|. Otherwise, if the block size is zero, the +field \verb|data| is set to \verb|NULL|. + +\subsection{glp\_del\_vertices --- delete vertices from graph} + +\synopsis + +\begin{verbatim} + void glp_del_vertices(glp_graph *G, int ndel, const int num[]); +\end{verbatim} + +\description + +The routine \verb|glp_del_vertices| deletes vertices along with all +incident arcs from the specified graph. Ordinal numbers of vertices to +be deleted should be placed in locations \verb|num[1]|, \dots, +\verb|num[ndel]|, \verb|ndel| $>0$. + +Note that deleting vertices involves changing ordinal numbers of other +vertices remaining in the graph. New ordinal numbers of the remaining +vertices are assigned under the assumption that the original order of +vertices is not changed. + +\newpage + +\subsection{glp\_del\_arc --- delete arc from graph} + +\synopsis + +\begin{verbatim} + void glp_del_arc(glp_graph *G, glp_arc *a); +\end{verbatim} + +\description + +The routine \verb|glp_del_arc| deletes an arc from the specified graph. +The arc to be deleted must exist. + +\subsection{glp\_erase\_graph --- erase graph content} + +\synopsis + +\begin{verbatim} + void glp_erase_graph(glp_graph *G, int v_size, int a_size); +\end{verbatim} + +\description + +The routine \verb|glp_erase_graph| erases the content of the specified +graph. The effect of this operation is the same as if the graph would +be deleted with the routine \verb|glp_delete_graph| and then created +anew with the routine \verb|glp_create_graph|, with exception that the +pointer to the graph remains valid. + +The parameters \verb|v_size| and \verb|a_size| have the same meaning as +for \verb|glp_create_graph|. + +\subsection{glp\_delete\_graph --- delete graph} + +\synopsis + +\begin{verbatim} + void glp_delete_graph(glp_graph *G); +\end{verbatim} + +\description + +The routine \verb|glp_delete_graph| deletes the specified graph and +frees all the memory allocated to this program object. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Graph searching routines} + +\subsection{glp\_create\_v\_index --- create vertex name index} + +\synopsis + +\begin{verbatim} + void glp_create_v_index(glp_graph *G); +\end{verbatim} + +\description + +The routine \verb|glp_create_v_index| creates the name index for the +specified graph. The name index is an auxiliary data structure, which +is intended to quickly (i.e. for logarithmic time) find vertices by +their names. + +This routine can be called at any time. If the name index already +exists, the routine does nothing. + +\subsection{glp\_find\_vertex --- find vertex by its name} + +\synopsis + +\begin{verbatim} + int glp_find_vertex(glp_graph *G, const char *name); +\end{verbatim} + +\returns + +The routine \verb|glp_find_vertex| returns the ordinal number of +a vertex, which is assigned (by the routine \verb|glp_set_vertex_name|) +the specified symbolic \verb|name|. If no such vertex exists, the +routine returns 0. + +\subsection{glp\_delete\_v\_index --- delete vertex name index} + +\synopsis + +\begin{verbatim} + void glp_delete_v_index(glp_graph *G); +\end{verbatim} + +\description + +The routine \verb|glp_delete_v_index| deletes the name index previously +created by the routine \verb|glp_create_v_index| and frees the memory +allocated to this auxiliary data structure. + +This routine can be called at any time. If the name index does not +exist, the routine does nothing. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Graph reading/writing routines} + +\subsection{glp\_read\_graph --- read graph from plain text file} + +\synopsis + +\begin{verbatim} + int glp_read_graph(glp_graph *G, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_graph| reads a graph from a plain text file, +whose name is specified by the parameter \verb|fname|. Note that before +reading data the current content of the graph object is completely +erased with the routine \verb|glp_erase_graph|. + +For the file format see description of the routine +\verb|glp_write_graph|. + +\returns + +If the operation was successful, the routine returns zero. Otherwise +it prints an error message and returns non-zero. + +\subsection{glp\_write\_graph --- write graph to plain text file} + +\synopsis + +\begin{verbatim} + int glp_write_graph(glp_graph *G, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_graph| writes the graph to a plain text +file, whose name is specified by the parameter \verb|fname|. + +\returns + +If the operation was successful, the routine returns zero. Otherwise +it prints an error message and returns non-zero. + +\para{File format} + +The file created by the routine \verb|glp_write_graph| is a plain text +file, which contains the following information: + +\begin{verbatim} + nv na + i[1] j[1] + i[2] j[2] + . . . + i[na] j[na] +\end{verbatim} + +\noindent +where: \verb|nv| is the number of vertices (nodes); \verb|na| is the +number of arcs; \verb|i[k]|, $k=1,\dots,na$, is the index of tail +vertex of arc $k$; \verb|j[k]|, $k=1,\dots,na$, is the index of head +vertex of arc $k$. + +\newpage + +\subsection{glp\_read\_ccdata --- read graph from text file in DIMACS +clique/coloring\\format} + +\synopsis + +\begin{verbatim} + int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname); +\end{verbatim} + +\description + +The routine {\tt glp\_read\_ccdata} reads a graph from a text file in +DIMACS clique/coloring format. (Though this format is originally +designed to represent data for the minimal vertex coloring and maximal +clique problems, it may be used to represent general undirected and +directed graphs, because the routine allows reading self-loops and +multiple edges/arcs keeping the order of vertices specified for each +edge/arc of the graph.) + +The parameter {\tt G} specifies the graph object to be read in. Note +that before reading data the current content of the graph object is +completely erased with the routine {\tt glp\_erase\_graph}. + +The parameter {\tt v\_wgt} specifies an offset of the field of type +{\tt double} in the vertex data block, to which the routine stores the +vertex weight. If {\tt v\_wgt} $<0$, the vertex weights are not stored. + +The character string {\tt fname} specifies the name of a text file to +be read in. (If the file name ends with the suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine +decompresses it ``on the fly''.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\para{DIMACS clique/coloring format\footnote{This material is +based on the paper ``Clique and Coloring Problems Graph Format'', which +is publically available at \url{http://dimacs.rutgers.edu/Challenges}.}} + +The DIMACS input file is a plain ASCII text file. It contains +{\it lines} of several types described below. A line is terminated with +an end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +Note that DIMACS requires all numerical quantities to be integers in +the range $[-2^{31},2^{31}-1]$ while GLPK allows the quantities to be +floating-point numbers. + +\para{Comment lines.} Comment lines give human-readable information +about the file and are ignored by programs. Comment lines can appear +anywhere in the file. Each comment line begins with a lower-case +character \verb|c|. + +\begin{verbatim} + c This is a comment line +\end{verbatim} + +\para{Problem line.} There is one problem line per data file. +The problem line must appear before any node or edge descriptor lines. +It has the following format: + +\begin{verbatim} + p edge NODES EDGES +\end{verbatim} + +\noindent +The lower-case letter \verb|p| signifies that this is a problem line. +The four-character problem designator \verb|edge| identifies the file +as containing data for the minimal vertex coloring or maximal clique +problem. The \verb|NODES| field contains an integer value specifying +the number of vertices in the graph. The \verb|EDGES| field contains an +integer value specifying the number of edges (arcs) in the graph. + +\para{Vertex descriptors.} These lines give the weight assigned to +a vertex of the graph. There is one vertex descriptor line for each +vertex, with the following format. Vertices without a descriptor take +on a default value of 1. + +\begin{verbatim} + n ID VALUE +\end{verbatim} + +\noindent +The lower-case character \verb|n| signifies that this is a vertex +descriptor line. The \verb|ID| field gives a vertex identification +number, an integer between 1 and $n$, where $n$ is the number of +vertices in the graph. The \verb|VALUE| field gives a vertex weight, +which can either positive or negative (or zero). + +\para{Edge descriptors.} There is one edge descriptor line for each +edge (arc) of the graph, each with the following format: + +\begin{verbatim} + e I J +\end{verbatim} + +\noindent +The lower-case character \verb|e| signifies that this is an edge +descriptor line. For an edge (arc) $(i,j)$ the fields \verb|I| and +\verb|J| specify its endpoints. + +\para{Example.} The following example of an undirected graph: + +\bigskip + +\noindent\hfil +\xymatrix %@C=32pt +{&{v_1}\ar@{-}[ldd]\ar@{-}[dd]\ar@{-}[rd]\ar@{-}[rr]&&{v_2}\ar@{-}[ld] +\ar@{-}[dd]\ar@{-}[rdd]&\\ +&&{v_7}\ar@{-}[ld]\ar@{-}[rd]&&\\ +{v_6}\ar@{-}[r]\ar@{-}[rdd]&{v_{10}}\ar@{-}[rr]\ar@{-}[rd]\ar@{-}[dd]&& +{v_8}\ar@{-}[ld]\ar@{-}[dd]\ar@{-}[r]&{v_3}\ar@{-}[ldd]\\ +&&{v_9}\ar@{-}[ld]\ar@{-}[rd]&&\\ +&{v_5}\ar@{-}[rr]&&{v_4}&\\ +} + +\bigskip + +\noindent +might be coded in DIMACS clique/coloring format as follows: + +\begin{footnotesize} +\begin{verbatim} +c sample.col +c +c This is an example of the vertex coloring problem data +c in DIMACS format. +c +p edge 10 21 +c +e 1 2 +e 1 6 +e 1 7 +e 1 10 +e 2 3 +e 2 7 +e 2 8 +e 3 4 +e 3 8 +e 4 5 +e 4 8 +e 4 9 +e 5 6 +e 5 9 +e 5 10 +e 6 10 +e 7 8 +e 7 10 +e 8 9 +e 8 10 +e 9 10 +c +c eof +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_write\_ccdata --- write graph to text file in DIMACS +clique/coloring\\format} + +\synopsis + +\begin{verbatim} + int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname); +\end{verbatim} + +\description + +The routine {\tt glp\_write\_ccdata} writes the graph object specified +by the parameter {\tt G} to a text file in DIMACS clique/coloring +format. (Though this format is originally designed to represent data +for the minimal vertex coloring and maximal clique problems, it may be +used to represent general undirected and directed graphs, because the +routine allows writing self-loops and multiple edges/arcs keeping the +order of vertices specified for each edge/arc of the graph.) + +The parameter {\tt v\_wgt} specifies an offset of the field of type +{\tt double} in the vertex data block, which contains the vertex +weight. If {\tt v\_wgt} $<0$, it is assumed that the weight of each +vertex is 1. + +The character string {\tt fname} specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine performs +automatic compression on writing it.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Graph analysis routines} + +\subsection{glp\_weak\_comp --- find all weakly connected components of +graph} + +\synopsis + +\begin{verbatim} + int glp_weak_comp(glp_graph *G, int v_num); +\end{verbatim} + +\description + +The routine \verb|glp_weak_comp| finds all weakly connected components +of the specified graph. + +The parameter \verb|v_num| specifies an offset of the field of type +\verb|int| in the vertex data block, to which the routine stores the +number of a weakly connected component containing that vertex. If +\verb|v_num| $<0$, no component numbers are stored. + +The components are numbered in arbitrary order from 1 to \verb|nc|, +where \verb|nc| is the total number of components found, +$0\leq$ \verb|nc| $\leq|V|$. + +\returns + +The routine returns \verb|nc|, the total number of components found. + +\subsection{glp\_strong\_comp --- find all strongly connected +components of graph} + +\synopsis + +\begin{verbatim} + int glp_strong_comp(glp_graph *G, int v_num); +\end{verbatim} + +\description + +The routine \verb|glp_strong_comp| finds all strongly connected +components of the specified graph. + +The parameter \verb|v_num| specifies an offset of the field of type +\verb|int| in the vertex data block, to which the routine stores the +number of a strongly connected component containing that vertex. If +\verb|v_num| $<0$, no component numbers are stored. + +The components are numbered in arbitrary order from 1 to \verb|nc|, +where \verb|nc| is the total number of components found, +$0\leq$ \verb|nc| $\leq|V|$. However, the component numbering has the +property that for every arc $(i\rightarrow j)$ in the graph the +condition $num(i)\geq num(j)$ holds. + +\returns + +The routine returns \verb|nc|, the total number of components found. + +\para{References} + +I.~S.~Duff, J.~K.~Reid, Algorithm 529: Permutations to block triangular +form, ACM Trans. on Math. Softw. 4 (1978), 189-92. + +\newpage + +\para{Example} + +The following program reads a graph from a plain text file +`\verb|graph.txt|' and finds all its strongly connected components. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +typedef struct { int num; } v_data; + +#define vertex(v) ((v_data *)((v)->data)) + +int main(void) +{ glp_graph *G; + int i, nc; + G = glp_create_graph(sizeof(v_data), 0); + glp_read_graph(G, "graph.txt"); + nc = glp_strong_comp(G, offsetof(v_data, num)); + printf("nc = %d\n", nc); + for (i = 1; i <= G->nv; i++) + printf("num[%d] = %d\n", i, vertex(G->v[i])->num); + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +\noindent +If the file `\verb|graph.txt|' contains the following graph: + +\medskip + +\noindent\hfil +\xymatrix +{1\ar[r]&2\ar[r]&3\ar[r]\ar[dd]&4\ar[dd]\\ +5\ar[u]&6\ar[l]\\ +7\ar[u]&&8\ar[lu]\ar[ll]\ar[r]&9\ar[r]&10\ar[r]\ar[d]&11\ar[d]\\ +12\ar[u]\ar[rru]\ar@/_/[rr]&&13\ar[ll]\ar[u]\ar[rr]&&14\ar[lu]&15\ar[l] +\\ +} + +\medskip\medskip + +\noindent +the program output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading graph from `graph.txt'... +Graph has 15 vertices and 30 arcs +31 lines were read +nc = 4 +num[1] = 3 +num[2] = 3 +num[3] = 3 +num[4] = 2 +num[5] = 3 +num[6] = 3 +num[7] = 3 +num[8] = 3 +num[9] = 1 +num[10] = 1 +num[11] = 1 +num[12] = 4 +num[13] = 4 +num[14] = 1 +num[15] = 1 +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_top\_sort --- topological sorting of acyclic digraph} + +\synopsis + +\begin{verbatim} + int glp_top_sort(glp_graph *G, int v_num); +\end{verbatim} + +\description + +The routine \verb|glp_top_sort| performs topological sorting of +vertices of the specified acyclic digraph. + +The parameter \verb|v_num| specifies an offset of the field of type +\verb|int| in the vertex data block, to which the routine stores the +vertex number assigned. If \verb|v_num| $<0$, vertex numbers are not +stored. + +The vertices are numbered from 1 to $n$, where $n$ is the total number +of vertices in the graph. The vertex numbering has the property that +for every arc $(i\rightarrow j)$ in the graph the condition +$num(i)<num(j)$ holds. Special case $num(i)=0$ means that vertex $i$ is +not assigned a number, because the graph is {\it not} acyclic. + +\returns + +If the graph is acyclic and therefore all the vertices have been +assigned numbers, the routine \verb|glp_top_sort| returns zero. +Otherwise, if the graph is not acyclic, the routine returns the number +of vertices which have not been numbered, i.e. for which $num(i)=0$. + +\para{Example} + +The following program reads a digraph from a plain text file +`\verb|graph.txt|' and performs topological sorting of its vertices. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +typedef struct { int num; } v_data; + +#define vertex(v) ((v_data *)((v)->data)) + +int main(void) +{ glp_graph *G; + int i, cnt; + G = glp_create_graph(sizeof(v_data), 0); + glp_read_graph(G, "graph.txt"); + cnt = glp_top_sort(G, offsetof(v_data, num)); + printf("cnt = %d\n", cnt); + for (i = 1; i <= G->nv; i++) + printf("num[%d] = %d\n", i, vertex(G->v[i])->num); + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +\noindent +If the file `\verb|graph.txt|' contains the following graph: + +\medskip + +\noindent\hfil +\xymatrix @=20pt +{ +1\ar[rrr]&&&2\ar[r]\ar[rddd]&3\ar[rd]&&&&\\ +&&&4\ar[ru]&&5\ar[r]&6\ar[rd]\ar[dd]&&\\ +7\ar[r]&8\ar[r]&9\ar[ruu]\ar[ru]\ar[r]\ar[rd]&10\ar[rr]\ar[rru]&& +11\ar[ru]&&12\ar[r]&13\\ +&&&14\ar[r]&15\ar[rrru]\ar[rr]&&16\ar[rru]\ar[rr]&&17\\ +} + +\medskip\medskip + +\noindent +the program output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading graph from `graph.txt'... +Graph has 17 vertices and 23 arcs +24 lines were read +cnt = 0 +num[1] = 8 +num[2] = 9 +num[3] = 10 +num[4] = 4 +num[5] = 11 +num[6] = 12 +num[7] = 1 +num[8] = 2 +num[9] = 3 +num[10] = 5 +num[11] = 6 +num[12] = 14 +num[13] = 16 +num[14] = 7 +num[15] = 13 +num[16] = 15 +num[17] = 17 +\end{verbatim} +\end{footnotesize} + +\noindent +The output corresponds to the following vertex numbering: + +\medskip + +\noindent\hfil +\xymatrix @=20pt +{ +8\ar[rrr]&&&9\ar[r]\ar[rddd]&10\ar[rd]&&&&\\ +&&&4\ar[ru]&&11\ar[r]&12\ar[rd]\ar[dd]&&\\ +1\ar[r]&2\ar[r]&3\ar[ruu]\ar[ru]\ar[r]\ar[rd]&5\ar[rr]\ar[rru]&& +6\ar[ru]&&14\ar[r]&16\\ +&&&7\ar[r]&13\ar[rrru]\ar[rr]&&15\ar[rru]\ar[rr]&&17\\ +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Network optimization API routines} + +\section{Minimum cost flow problem} + +\subsection{Background} + +The {\it minimum cost flow problem} (MCFP) is stated as follows. Let +there be given a directed graph (flow network) $G=(V,A)$, where $V$ is +a set of vertices (nodes), and $A\subseteq V\times V$ is a set of arcs. +Let for each node $i\in V$ there be given a quantity $b_i$ having the +following meaning: + +if $b_i>0$, then $|b_i|$ is a {\it supply} at node $i$, which shows +how many flow units are {\it generated} at node $i$ (or, equivalently, +entering the network through node $i$ from outside); + +if $b_i<0$, then $|b_i|$ is a {\it demand} at node $i$, which shows how +many flow units are {\it lost} at node $i$ (or, equivalently, leaving +the network through node $i$ to outside); + +if $b_i=0$, then $i$ is a {\it transshipment} node, at which the flow +is conserved, i.e. neither generated nor lost. + +Let also for each arc $a=(i,j)\in A$ there be given the following three +quantities: + +$l_{ij}$, a (non-negative) lower bound to the flow through arc $(i,j)$; + +$u_{ij}$, an upper bound to the flow through arc $(i,j)$, which is the +{\it arc capacity}; + +$c_{ij}$, a per-unit cost of the flow through arc $(i,j)$. + +The problem is to find flows $x_{ij}$ through every arc of the network, +which satisfy the specified bounds and the conservation constraints at +all nodes, and minimize the total flow cost. Here the conservation +constraint at a node means that the total flow entering this node +through its incoming arcs plus the supply at this node must be equal to +the total flow leaving this node through its outgoing arcs plus the +demand at this node. + +An example of the minimum cost flow problem is shown on Fig.~1. + +\newpage + +\noindent\hfil +\xymatrix @C=48pt +{_{20}\ar@{~>}[d]& +v_2\ar[r]|{_{0,10,\$2}}\ar[dd]|{_{0,9,\$3}}& +v_3\ar[dd]|{_{2,12,\$1}}\ar[r]|{_{0,18,\$0}}& +v_8\ar[rd]|{_{0,20,\$9}}&\\ +v_1\ar[ru]|{_{0,14,\$0}}\ar[rd]|{_{0,23,\$0}}&&& +v_6\ar[d]|{_{0,7,\$0}}\ar[u]|{_{4,8,\$0}}& +v_9\ar@{~>}[d]\\ +&v_4\ar[r]|{_{0,26,\$0}}& +v_5\ar[luu]|{_{0,11,\$1}}\ar[ru]|{_{0,25,\$5}}\ar[r]|{_{0,4,\$7}}& +v_7\ar[ru]|{_{0,15,\$3}}&_{20}\\ +} + +\noindent\hfil +\begin{tabular}{ccc} +\xymatrix @C=48pt{v_i\ar[r]|{\ l,u,\$c\ }&v_j\\}& +\xymatrix{\hbox{\footnotesize supply}\ar@{~>}[r]&v_i\\}& +\xymatrix{v_i\ar@{~>}[r]&\hbox{\footnotesize demand}\\}\\ +\end{tabular} + +\noindent\hfil +Fig.~1. An example of the minimum cost flow problem. + +\medskip + +The minimum cost flow problem can be naturally formulated as the +following LP problem: + +\noindent +\hspace{1in}minimize +$$z=\sum_{(i,j)\in A}c_{ij}x_{ij}\eqno(1)$$ +\hspace{1in}subject to +$$\sum_{(i,j)\in A}x_{ij}-\sum_{(j,i)\in A}x_{ji}=b_i\ \ \ \hbox +{for all}\ i\in V\eqno(2)$$ +$$l_{ij}\leq x_{ij}\leq u_{ij}\ \ \ \hbox{for all}\ (i,j)\in A +\eqno(3)$$ + +\subsection{glp\_read\_mincost --- read minimum cost flow problem data +in DIMACS\\format} + +\synopsis + +\begin{verbatim} + int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_mincost| reads the minimum cost flow problem +data from a text file in DIMACS format. + +The parameter \verb|G| specifies the graph object, to which the problem +data have to be stored. Note that before reading data the current +content of the graph object is completely erased with the routine +\verb|glp_erase_graph|. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores +$b_i$, the supply/demand value. If \verb|v_rhs| $<0$, the value is not +stored. + +The parameter \verb|a_low| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$l_{ij}$, the lower bound to the arc flow. If \verb|a_low| $<0$, the +lower bound is not stored. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$u_{ij}$, the upper bound to the arc flow (the arc capacity). If +\verb|a_cap| $<0$, the upper bound is not stored. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$c_{ij}$, the per-unit cost of the arc flow. If \verb|a_cost| $<0$, the +cost is not stored. + +The character string \verb|fname| specifies the name of a text file to +be read in. (If the file name name ends with the suffix `\verb|.gz|', +the file is assumed to be compressed, in which case the routine +decompresses it ``on the fly''.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\para{Example} + +\begin{footnotesize} +\begin{verbatim} +typedef struct +{ /* vertex data block */ + ... + double rhs; + ... +} v_data; + +typedef struct +{ /* arc data block */ + ... + double low, cap, cost; + ... +} a_data; + +int main(void) +{ glp_graph *G; + int ret; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + ret = glp_read_mincost(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), "sample.min"); + if (ret != 0) goto ... + ... +} +\end{verbatim} +\end{footnotesize} + +\para{DIMACS minimum cost flow problem format\footnote{This +material is based on the paper ``The First DIMACS International +Algorithm Implementation Challenge: Problem Definitions and +Specifications'', which is publically available at +\url{http://dimacs.rutgers.edu/Challenges}.}} +\label{subsecmincost} + +The DIMACS input file is a plain ASCII text file. It contains +{\it lines} of several types described below. A line is terminated with +an end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +Note that DIMACS requires all numerical quantities to be integers in +the range $[-2^{31},\ 2^{31}-1]$ while GLPK allows the quantities to be +floating-point numbers. + +\para{Comment lines.} Comment lines give human-readable information +about the file and are ignored by programs. Comment lines can appear +anywhere in the file. Each comment line begins with a lower-case +character \verb|c|. + +\begin{verbatim} + c This is a comment line +\end{verbatim} + +\newpage + +\para{Problem line.} There is one problem line per data file. The +problem line must appear before any node or arc descriptor lines. It +has the following format: + +\begin{verbatim} + p min NODES ARCS +\end{verbatim} + +\noindent +The lower-case character \verb|p| signifies that this is a problem line. +The three-character problem designator \verb|min| identifies the file as +containing specification information for the minimum cost flow problem. +The \verb|NODES| field contains an integer value specifying the number +of nodes in the network. The \verb|ARCS| field contains an integer value +specifying the number of arcs in the network. + +\para{Node descriptors.} All node descriptor lines must appear before +all arc descriptor lines. The node descriptor lines describe supply and +demand nodes, but not transshipment nodes. That is, only nodes with +non-zero node supply/demand values appear. There is one node descriptor +line for each such node, with the following format: + +\begin{verbatim} + n ID FLOW +\end{verbatim} + +\noindent +The lower-case character \verb|n| signifies that this is a node +descriptor line. The \verb|ID| field gives a node identification +number, an integer between 1 and \verb|NODES|. The \verb|FLOW| field +gives the amount of supply (if positive) or demand (if negative) at +node \verb|ID|. + +\para{Arc descriptors.} There is one arc descriptor line for each arc +in the network. Arc descriptor lines are of the following format: + +\begin{verbatim} + a SRC DST LOW CAP COST +\end{verbatim} + +\noindent +The lower-case character \verb|a| signifies that this is an arc +descriptor line. For a directed arc $(i,j)$ the \verb|SRC| field gives +the identification number $i$ for the tail endpoint, and the \verb|DST| +field gives the identification number $j$ for the head endpoint. +Identification numbers are integers between 1 and \verb|NODES|. The +\verb|LOW| field specifies the minimum amount of flow that can be sent +along arc $(i,j)$, and the \verb|CAP| field gives the maximum amount of +flow that can be sent along arc $(i,j)$ in a feasible flow. The +\verb|COST| field contains the per-unit cost of flow sent along arc +$(i,j)$. + +\para{Example.} Below here is an example of the data file in DIMACS +format corresponding to the minimum cost flow problem shown on Fig~1. + +\begin{footnotesize} +\begin{verbatim} +c sample.min +c +c This is an example of the minimum cost flow problem data +c in DIMACS format. +c +p min 9 14 +c +n 1 20 +n 9 -20 +c +a 1 2 0 14 0 +a 1 4 0 23 0 +a 2 3 0 10 2 +a 2 4 0 9 3 +a 3 5 2 12 1 +a 3 8 0 18 0 +a 4 5 0 26 0 +a 5 2 0 11 1 +a 5 6 0 25 5 +a 5 7 0 4 7 +a 6 7 0 7 0 +a 6 8 4 8 0 +a 7 9 0 15 3 +a 8 9 0 20 9 +c +c eof +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_write\_mincost --- write minimum cost flow problem +data in DIMACS\\format} + +\synopsis + +\begin{verbatim} + int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_mincost| writes the minimum cost flow +problem data to a text file in DIMACS format. + +The parameter \verb|G| is the graph (network) program object, which +specifies the minimum cost flow problem instance. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, which contains $b_i$, the +supply/demand value. If \verb|v_rhs| $<0$, it is assumed that $b_i=0$ +for all nodes. + +The parameter \verb|a_low| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $l_{ij}$, the lower +bound to the arc flow. If \verb|a_low| $<0$, it is assumed that +$l_{ij}=0$ for all arcs. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). If the upper bound is +specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. +the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that +$u_{ij}=1$ for all arcs. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the +per-unit cost of the arc flow. If \verb|a_cost| $<0$, it is assumed +that $c_{ij}=0$ for all arcs. + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine performs +automatic compression on writing it.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\newpage + +\subsection{glp\_mincost\_lp --- convert minimum cost flow problem +to LP} + +\synopsis + +\begin{verbatim} + void glp_mincost_lp(glp_prob *P, glp_graph *G, int names, int v_rhs, + int a_low, int a_cap, int a_cost); +\end{verbatim} + +\description + +The routine \verb|glp_mincost_lp| builds LP problem (1)---(3), which +corresponds to the specified minimum cost flow problem. + +The parameter \verb|P| is the resultant LP problem object to be built. +Note that on entry its current content is erased with the routine +\verb|glp_erase_prob|. + +The parameter \verb|G| is the graph (network) program object, which +specifies the minimum cost flow problem instance. + +The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the +routine uses symbolic names of the graph object components to assign +symbolic names to the LP problem object components. If the flag is +\verb|GLP_OFF|, no symbolic names are assigned. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, which contains $b_i$, the +supply/demand value. If \verb|v_rhs| $<0$, it is assumed that $b_i=0$ +for all nodes. + +The parameter \verb|a_low| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $l_{ij}$, the lower +bound to the arc flow. If \verb|a_low| $<0$, it is assumed that +$l_{ij}=0$ for all arcs. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). If the upper bound is +specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. +the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that +$u_{ij}=1$ for all arcs. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the +per-unit cost of the arc flow. If \verb|a_cost| $<0$, it is assumed that +$c_{ij}=0$ for all arcs. + +\para{Example} + +The example program below reads the minimum cost problem instance in +DIMACS format from file `\verb|sample.min|', converts the instance to +LP, and then writes the resultant LP in CPLEX format to file +`\verb|mincost.lp|'. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <glpk.h> + +typedef struct { double rhs; } v_data; +typedef struct { double low, cap, cost; } a_data; + +int main(void) +{ glp_graph *G; + glp_prob *P; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + glp_read_mincost(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), "sample.min"); + P = glp_create_prob(); + glp_mincost_lp(P, G, GLP_ON, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost)); + glp_delete_graph(G); + glp_write_lp(P, NULL, "mincost.lp"); + glp_delete_prob(P); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.min|' is the example data file from the subsection +describing \verb|glp_read_mincost|, file `\verb|mincost.lp|' may look +like follows: + +\begin{footnotesize} +\begin{verbatim} +Minimize + obj: + 3 x(2,4) + 2 x(2,3) + x(3,5) + 7 x(5,7) + 5 x(5,6) + + x(5,2) + 3 x(7,9) + 9 x(8,9) + +Subject To + r_1: + x(1,2) + x(1,4) = 20 + r_2: - x(5,2) + x(2,3) + x(2,4) - x(1,2) = 0 + r_3: + x(3,5) + x(3,8) - x(2,3) = 0 + r_4: + x(4,5) - x(2,4) - x(1,4) = 0 + r_5: + x(5,2) + x(5,6) + x(5,7) - x(4,5) - x(3,5) = 0 + r_6: + x(6,7) + x(6,8) - x(5,6) = 0 + r_7: + x(7,9) - x(6,7) - x(5,7) = 0 + r_8: + x(8,9) - x(6,8) - x(3,8) = 0 + r_9: - x(8,9) - x(7,9) = -20 + +Bounds + 0 <= x(1,4) <= 23 + 0 <= x(1,2) <= 14 + 0 <= x(2,4) <= 9 + 0 <= x(2,3) <= 10 + 0 <= x(3,8) <= 18 + 2 <= x(3,5) <= 12 + 0 <= x(4,5) <= 26 + 0 <= x(5,7) <= 4 + 0 <= x(5,6) <= 25 + 0 <= x(5,2) <= 11 + 4 <= x(6,8) <= 8 + 0 <= x(6,7) <= 7 + 0 <= x(7,9) <= 15 + 0 <= x(8,9) <= 20 + +End +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_mincost\_okalg --- solve minimum cost flow problem +with out-of-kilter\\algorithm} + +\synopsis + +\begin{verbatim} + int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, double *sol, int a_x, int v_pi); +\end{verbatim} + +\description + +The routine \verb|glp_mincost_okalg| finds optimal solution to the +minimum cost flow problem with the out-of-kilter +algorithm.\footnote{GLPK implementation of the out-of-kilter algorithm +is based on the following book: L.~R.~Ford,~Jr., and D.~R.~Fulkerson, +``Flows in Networks,'' The RAND Corp., Report R-375-PR (August 1962), +Chap. III ``Minimal Cost Flow Problems,'' pp.~113-26.} Note that this +routine requires all the problem data to be integer-valued. + +The parameter \verb|G| is a graph (network) program object which +specifies the minimum cost flow problem instance to be solved. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, which contains $b_i$, the +supply/demand value. This value must be integer in the range +[$-$\verb|INT_MAX|, $+$\verb|INT_MAX|]. If \verb|v_rhs| $<0$, it is +assumed that $b_i=0$ for all nodes. + +The parameter \verb|a_low| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $l_{ij}$, the lower +bound to the arc flow. This bound must be integer in the range +[$0$, \verb|INT_MAX|]. If \verb|a_low| $<0$, it is assumed that +$l_{ij}=0$ for all arcs. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). This bound must be integer in +the range [$l_{ij}$, \verb|INT_MAX|]. If \verb|a_cap| $<0$, it is +assumed that $u_{ij}=1$ for all arcs. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the +per-unit cost of the arc flow. This value must be integer in the range +[$-$\verb|INT_MAX|, $+$\verb|INT_MAX|]. If \verb|a_cost| $<0$, it is +assumed that $c_{ij}=0$ for all arcs. + +The parameter \verb|sol| specifies a location, to which the routine +stores the objective value (that is, the total cost) found. If +\verb|sol| is NULL, the objective value is not stored. + +The parameter \verb|a_x| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$x_{ij}$, the arc flow found. If \verb|a_x| $<0$, the arc flow value is +not stored. + +The parameter \verb|v_pi| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores +$\pi_i$, the node potential, which is the Lagrange multiplier for the +corresponding flow conservation equality constraint (see (2) in +Subsection ``Background''). If necessary, the application program may +use the node potentials to compute $\lambda_{ij}$, reduced costs of the +arc flows $x_{ij}$, which are the Lagrange multipliers for the arc flow +bound constraints (see (3) ibid.), using the following formula: +$$\lambda_{ij}=c_{ij}-(\pi_i-\pi_j),$$ +where $c_{ij}$ is the per-unit cost for arc $(i,j)$. + +\newpage + +Note that all solution components (the objective value, arc flows, and +node potentials) computed by the routine are always integer-valued. + +\returns + +\begin{retlist} +0 & Optimal solution found.\\ + +\verb|GLP_ENOPFS| & No (primal) feasible solution exists.\\ + +\verb|GLP_EDATA| & Unable to start the search, because some problem +data are either not integer-valued or out of range. This code is also +returned if the total supply, which is the sum of $b_i$ over all source +nodes (nodes with $b_i>0$), exceeds \verb|INT_MAX|.\\ + +\verb|GLP_ERANGE| & The search was prematurely terminated because of +integer overflow.\\ + +\verb|GLP_EFAIL| & An error has been detected in the program logic. +(If this code is returned for your problem instance, please report to +\verb|<bug-glpk@gnu.org>|.)\\ +\end{retlist} + +\para{Comments} + +By design the out-of-kilter algorithm is applicable only to networks, +where $b_i=0$ for {\it all} nodes, i.e. actually this algorithm finds a +minimal cost {\it circulation}. Due to this requirement the routine +\verb|glp_mincost_okalg| converts the original network to a network +suitable for the out-of-kilter algorithm in the following +way:\footnote{The conversion is performed internally and does not change +the original network program object passed to the routine.} + +1) it adds two auxiliary nodes $s$ and $t$; + +2) for each original node $i$ with $b_i>0$ the routine adds auxiliary +supply arc $(s\rightarrow i)$, flow $x_{si}$ through which is costless +($c_{si}=0$) and fixed to $+b_i$ ($l_{si}=u_{si}=+b_i$); + +3) for each original node $i$ with $b_i<0$ the routine adds auxiliary +demand arc $(i\rightarrow t)$, flow $x_{it}$ through which is costless +($c_{it}=0$) and fixed to $-b_i$ ($l_{it}=u_{it}=-b_i$); + +4) finally, the routine adds auxiliary feedback arc $(t\rightarrow s)$, +flow $x_{ts}$ through which is also costless ($c_{ts}=0$) and fixed to +$F$ ($l_{ts}=u_{ts}=F$), where $\displaystyle F=\sum_{b_i>0}b_i$ is the +total supply. + +\para{Example} + +The example program below reads the minimum cost problem instance in +DIMACS format from file `\verb|sample.min|', solves it by using the +routine \verb|glp_mincost_okalg|, and writes the solution found on the +standard output. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +typedef struct { double rhs, pi; } v_data; +typedef struct { double low, cap, cost, x; } a_data; + +#define node(v) ((v_data *)((v)->data)) +#define arc(a) ((a_data *)((a)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v, *w; + glp_arc *a; + int i, ret; + double sol; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + glp_read_mincost(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), "sample.min"); + ret = glp_mincost_okalg(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), &sol, offsetof(a_data, x), + offsetof(v_data, pi)); + printf("ret = %d; sol = %5g\n", ret, sol); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + printf("node %d: pi = %5g\n", i, node(v)->pi); + for (a = v->out; a != NULL; a = a->t_next) + { w = a->head; + printf("arc %d->%d: x = %5g; lambda = %5g\n", + v->i, w->i, arc(a)->x, + arc(a)->cost - (node(v)->pi - node(w)->pi)); + } + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.min|' is the example data file from the subsection +describing \verb|glp_read_mincost|, the output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading min-cost flow problem data from `sample.min'... +Flow network has 9 nodes and 14 arcs +24 lines were read +ret = 0; sol = 213 +node 1: pi = -12 +arc 1->4: x = 13; lambda = 0 +arc 1->2: x = 7; lambda = 0 +node 2: pi = -12 +arc 2->4: x = 0; lambda = 3 +arc 2->3: x = 7; lambda = 0 +node 3: pi = -14 +arc 3->8: x = 5; lambda = 0 +arc 3->5: x = 2; lambda = 3 +node 4: pi = -12 +arc 4->5: x = 13; lambda = 0 +node 5: pi = -12 +arc 5->7: x = 4; lambda = -1 +arc 5->6: x = 11; lambda = 0 +arc 5->2: x = 0; lambda = 1 +node 6: pi = -17 +arc 6->8: x = 4; lambda = 3 +arc 6->7: x = 7; lambda = -3 +node 7: pi = -20 +arc 7->9: x = 11; lambda = 0 +node 8: pi = -14 +arc 8->9: x = 9; lambda = 0 +node 9: pi = -23 +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_mincost\_relax4 --- solve minimum cost flow problem +with relaxation\\method of Bertsekas and Tseng (RELAX-IV)} + +\synopsis + +\begin{verbatim} + int glp_mincost_relax4(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, int crash, double *sol, int a_x, int a_rc); +\end{verbatim} + +\description + +The routine \verb|glp_mincost_relax4| finds optimal solution to the +minimum cost flow problem with the relaxation method RELAX-IV developed +by Bertsekas and Tseng.\footnote{GLPK implementation of this method is +based on a C translation of the original Fortran code {\tt RELAX4} +written by Dimitri P. Bertsekas and Paul Tseng, with a contribution by +Jonathan Eckstein in the phase II initialization.} This method is one +of most efficient methods for network optimization. + +Note that this routine requires all the problem data to be +integer-valued. + +The parameter \verb|G| is a graph (network) program object which +specifies the minimum cost flow problem instance to be solved. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, which contains $b_i$, the +supply/demand value. This value must be integer in the range +[$-$\verb|INT_MAX|/4, $+$\verb|INT_MAX|/4]. If \verb|v_rhs| $<0$, it is +assumed that $b_i=0$ for all nodes. + +The parameter \verb|a_low| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $l_{ij}$, the lower +bound to the arc flow. This bound must be integer in the range +{\linebreak} [$0$, \verb|INT_MAX|/4]. If \verb|a_low| $<0$, it is +assumed that $l_{ij}=0$ for all arcs. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). This bound must be integer in +the range [$l_{ij}$, \verb|INT_MAX|/4]. If \verb|a_cap| $<0$, it is +assumed that $u_{ij}=1$ for all arcs. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the +per-unit cost of the arc flow. This value must be integer in the range +[$-$\verb|INT_MAX|/4, $+$\verb|INT_MAX|/4]. If \verb|a_cost| $<0$, it +is assumed that $c_{ij}=0$ for all arcs. + +The parameter \verb|crash| is option specifying initialization method: + +0 --- default initialization is used; + +1 --- auction initialization is used. + +\noindent +If \verb|crash| = 1, initialization is performed with a special crash +procedure based on an auction/shorest path method. This option is +recommended for difficult problems where the default initialization +results in long running times. + +The parameter \verb|sol| specifies a location, to which the routine +stores the objective value (that is, the total cost) found. If +\verb|sol| is NULL, the objective value is not stored. + +\newpage + +The parameter \verb|a_x| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$x_{ij}$, the arc flow found. If \verb|a_x| $<0$, the arc flow value is +not stored. + +The parameter \verb|a_rc| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +the reduced cost for corresponding arc flow (see (3) in Subsection +``Background''). If \verb|a_rc| $<0$, the reduced cost is not stored. + +Note that all solution components (the objective value, arc flows, and +node potentials) computed by the routine are always integer-valued. + +\returns + +\begin{retlist} +0 & Optimal solution found.\\ + +\verb|GLP_ENOPFS| & No (primal) feasible solution exists.\\ + +\verb|GLP_EDATA| & Unable to start the search, because some problem +data are either not integer-valued or out of range.\\ + +\verb|GLP_ERANGE| & Unable to start the search because of integer +overflow.\\ +\end{retlist} + +\para{Example} + +The example program below reads the minimum cost problem instance in +DIMACS format from file `\verb|sample.min|', solves it by using the +routine \verb|glp_mincost_relax4|, and writes the solution found on the +standard output. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +typedef struct { double rhs; } v_data; +typedef struct { double low, cap, cost, x, rc; } a_data; + +#define node(v) ((v_data *)((v)->data)) +#define arc(a) ((a_data *)((a)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v, *w; + glp_arc *a; + int i, ret; + double sol; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + glp_read_mincost(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), "sample.min"); + ret = glp_mincost_relax4(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), 0, &sol, offsetof(a_data, x), + offsetof(a_data, rc)); + printf("ret = %d; sol = %5g\n", ret, sol); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { w = a->head; + printf("arc %d->%d: x = %5g; rc = %5g\n", + v->i, w->i, arc(a)->x, arc(a)->rc); + } + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.min|' is the example data file from the subsection +describing \verb|glp_read_mincost|, the output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading min-cost flow problem data from `sample.min'... +Flow network has 9 nodes and 14 arcs +24 lines were read +ret = 0; sol = 213 +arc 1->4: x = 13; rc = 0 +arc 1->2: x = 7; rc = 0 +arc 2->4: x = 0; rc = 3 +arc 2->3: x = 7; rc = 0 +arc 3->8: x = 5; rc = 0 +arc 3->5: x = 2; rc = 3 +arc 4->5: x = 13; rc = 0 +arc 5->7: x = 4; rc = -1 +arc 5->6: x = 11; rc = 0 +arc 5->2: x = 0; rc = 1 +arc 6->8: x = 4; rc = 3 +arc 6->7: x = 7; rc = -3 +arc 7->9: x = 11; rc = 0 +arc 8->9: x = 9; rc = 0 +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_netgen --- Klingman's network problem generator} + +\synopsis + +\begin{verbatim} + int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, + const int parm[1+15]); +\end{verbatim} + +\description + +The routine \verb|glp_netgen| is a GLPK version of the network problem +generator developed by Dr.~Darwin~Klingman.\footnote{D.~Klingman, +A.~Napier, and J.~Stutz. NETGEN: A program for generating large scale +capacitated assignment, transportation, and minimum cost flow networks. +Management Science 20 (1974), 814-20.} It can create capacitated and +uncapacitated minimum cost flow (or transshipment), transportation, and +assignment problems. + +The parameter \verb|G| specifies the graph object, to which the +generated problem data have to be stored. Note that on entry the graph +object is erased with the routine \verb|glp_erase_graph|. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores the +supply or demand value. If \verb|v_rhs| $<0$, the value is not stored. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +arc capacity. If \verb|a_cap| $<0$, the capacity is not stored. + +\newpage + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +per-unit cost if the arc flow. If \verb|a_cost| $<0$, the cost is not +stored. + +The array \verb|parm| contains description of the network to be +generated: + +\begin{tabular}{@{}lll@{}} +\verb|parm[0] |& ¬ used\\ +\verb|parm[1] |&\verb|iseed |&8-digit positive random number seed\\ +\verb|parm[2] |&\verb|nprob |&8-digit problem id number\\ +\verb|parm[3] |&\verb|nodes |&total number of nodes\\ +\verb|parm[4] |&\verb|nsorc |&total number of source nodes +(including transshipment nodes)\\ +\verb|parm[5] |&\verb|nsink |&total number of sink nodes +(including transshipment nodes)\\ +\verb|parm[6] |&\verb|iarcs |&number of arc\\ +\verb|parm[7] |&\verb|mincst|&minimum cost for arcs\\ +\verb|parm[8] |&\verb|maxcst|&maximum cost for arcs\\ +\verb|parm[9] |&\verb|itsup |&total supply\\ +\verb|parm[10]|&\verb|ntsorc|&number of transshipment source nodes\\ +\verb|parm[11]|&\verb|ntsink|&number of transshipment sink nodes\\ +\verb|parm[12]|&\verb|iphic |&percentage of skeleton arcs to be given +the maximum cost\\ +\verb|parm[13]|&\verb|ipcap |&percentage of arcs to be capacitated\\ +\verb|parm[14]|&\verb|mincap|&minimum upper bound for capacitated arcs\\ +\verb|parm[15]|&\verb|maxcap|&maximum upper bound for capacitated arcs\\ +\end{tabular} + +\returns + +If the instance was successfully generated, the routine +\verb|glp_netgen| returns zero; otherwise, if specified parameters are +inconsistent, the routine returns a non-zero error code. + +\para{Notes} + +1. The routine generates a transportation problem if: +$${\tt nsorc}+{\tt nsink}={\tt nodes}, +\ {\tt ntsorc}=0,\ \mbox{and}\ {\tt ntsink}=0.$$ + +2. The routine generates an assignment problem if the requirements for +a transportation problem are met and: +$${\tt nsorc}={\tt nsink}\ \mbox{and}\ {\tt itsup}={\tt nsorc}.$$ + +3. The routine always generates connected graphs. So, if the number of +requested arcs has been reached and the generated instance is not fully +connected, the routine generates a few remaining arcs to ensure +connectedness. Thus, the actual number of arcs generated by the routine +may be greater than the requested number of arcs. + +\subsection{glp\_netgen\_prob --- Klingman's standard network problem +instance} + +\synopsis + +\begin{verbatim} + void glp_netgen_prob(int nprob, int parm[1+15]); +\end{verbatim} + +\description + +The routine \verb|glp_netgen_prob| provides the set of parameters for +Klingman's network problem generator (see the routine +\verb|glp_netgen|), which describe a standard network problem instance. + +The parameter \verb|nprob| ($101\leq$ \verb|nprob| $\leq 150$) +specifies the problem instance number. + +The array \verb|parm| contains description of the network, provided by +the routine. (For detailed description of these parameters see comments +to the routine \verb|glp_netgen|.) + +\para{Problem characteristics} + +The table below shows characteristics of Klingman's standard network +problem instances. +$$ +\begin{array}{crrr} +{\rm Problem} & {\rm Nodes} & {\rm Arcs} & {\rm Optimum} \\ +\hline +101 & 5000 & 25336 & 6191726 \\ +102 & 5000 & 25387 & 72337144 \\ +103 & 5000 & 25355 & 218947553 \\ +104 & 5000 & 25344 & -19100371 \\ +105 & 5000 & 25332 & 31192578 \\ +106 & 5000 & 12870 & 4314276 \\ +107 & 5000 & 37832 & 7393769 \\ +108 & 5000 & 50309 & 8405738 \\ +109 & 5000 & 75299 & 9190300 \\ +110 & 5000 & 12825 & 8975048 \\ +111 & 5000 & 37828 & 4747532 \\ +112 & 5000 & 50325 & 4012671 \\ +113 & 5000 & 75318 & 2979725 \\ +114 & 5000 & 26514 & 5821181 \\ +115 & 5000 & 25962 & 6353310 \\ +116 & 5000 & 25304 & 5915426 \\ +117 & 5000 & 12816 & 4420560 \\ +118 & 5000 & 37797 & 7045842 \\ +119 & 5000 & 50301 & 7724179 \\ +120 & 5000 & 75330 & 8455200 \\ +121 & 5000 & 25000 & 66366360 \\ +122 & 5000 & 25000 & 30997529 \\ +123 & 5000 & 25000 & 23388777 \\ +124 & 5000 & 25000 & 17803443 \\ +125 & 5000 & 25000 & 14119622 \\ +\end{array} +\hspace{.5in} +\begin{array}{crrr} +{\rm Problem} & {\rm Nodes} & {\rm Arcs} & {\rm Optimum} \\ +\hline +126 & 5000 & 12500 & 18802218 \\ +127 & 5000 & 37500 & 27674647 \\ +128 & 5000 & 50000 & 30906194 \\ +129 & 5000 & 75000 & 40905209 \\ +130 & 5000 & 12500 & 38939608 \\ +131 & 5000 & 37500 & 16752978 \\ +132 & 5000 & 50000 & 13302951 \\ +133 & 5000 & 75000 & 9830268 \\ +134 & 1000 & 25000 & 3804874 \\ +135 & 2500 & 25000 & 11729616 \\ +136 & 7500 & 25000 & 33318101 \\ +137 & 10000 & 25000 & 46426030 \\ +138 & 5000 & 25000 & 60710879 \\ +139 & 5000 & 25000 & 32729682 \\ +140 & 5000 & 25000 & 27183831 \\ +141 & 5000 & 25000 & 19963286 \\ +142 & 5000 & 25000 & 20243457 \\ +143 & 5000 & 25000 & 18586777 \\ +144 & 5000 & 25000 & 2504591 \\ +145 & 5000 & 25000 & 215956138 \\ +146 & 5000 & 25000 & 2253113811 \\ +147 & 5000 & 25000 & -427908373 \\ +148 & 5000 & 25000 & -92965318 \\ +149 & 5000 & 25000 & 86051224 \\ +150 & 5000 & 25000 & 619314919 \\ +\end{array} +$$ + +\subsection{glp\_gridgen --- grid-like network problem generator} + +\synopsis + +\begin{verbatim} + int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, + const int parm[1+14]); +\end{verbatim} + +\description + +The routine \verb|glp_gridgen| is a GLPK version of the grid-like +network problem generator developed by Yusin Lee and Jim +Orlin.\footnote{Y.~Lee and J.~Orlin. GRIDGEN generator., 1991. The +original code is publically available from +\url{ftp://dimacs.rutgers.edu/pub/netflow/generators/network/gridgen}.} + +\newpage + +The parameter \verb|G| specifies the graph object, to which the +generated problem data have to be stored. Note that on entry the graph +object is erased with the routine \verb|glp_erase_graph|. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores the +supply or demand value. If \verb|v_rhs| $<0$, the value is not stored. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +arc capacity. If \verb|a_cap| $<0$, the capacity is not stored. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +per-unit cost if the arc flow. If \verb|a_cost| $<0$, the cost is not +stored. + +The array \verb|parm| contains parameters of the network to be +generated: + +\begin{tabular}{@{}ll@{}} +\verb|parm[0] |¬ used\\ +\verb|parm[1] |&two-ways arcs indicator:\\ + &1 --- if links in both direction should be generated\\ + &0 --- otherwise\\ +\verb|parm[2] |&random number seed (a positive integer)\\ +\verb|parm[3] |&number of nodes (the number of nodes generated might +be slightly different to\\&make the network a grid)\\ +\verb|parm[4] |&grid width\\ +\verb|parm[5] |&number of sources\\ +\verb|parm[6] |&number of sinks\\ +\verb|parm[7] |&average degree\\ +\verb|parm[8] |&total flow\\ +\verb|parm[9] |&distribution of arc costs: +1 --- uniform, 2 --- exponential\\ +\verb|parm[10]|&lower bound for arc cost (uniform), +$100\lambda$ (exponential)\\ +\verb|parm[11]|&upper bound for arc cost (uniform), +not used (exponential)\\ +\verb|parm[12]|&distribution of arc capacities: +1 --- uniform, 2 --- exponential\\ +\verb|parm[13]|&lower bound for arc capacity (uniform), +$100\lambda$ (exponential)\\ +\verb|parm[14]|&upper bound for arc capacity (uniform), +not used (exponential)\\ +\end{tabular} + +\returns + +If the instance was successfully generated, the routine +\verb|glp_gridgen| returns zero; otherwise, if specified parameters are +inconsistent, the routine returns a non-zero error code. + +\para{Comments\footnote{This material is based on comments +to the original version of GRIDGEN.}} + +This network generator generates a grid-like network plus a super node. +In additional to the arcs connecting the nodes in the grid, there is an +arc from each supply node to the super node and from the super node to +each demand node to guarantee feasiblity. These arcs have very high +costs and very big capacities. + +The idea of this network generator is as follows: First, a grid of +$n_1\times n_2$ is generated. For example, $5\times 3$. The nodes are +numbered as 1 to 15, and the supernode is numbered as +$n_1\times n_2+1$. Then arcs between adjacent nodes are generated. +For these arcs, the user is allowed to specify either to generate +two-way arcs or one-way arcs. If two-way arcs are to be generated, two +arcs, one in each direction, will be generated between each adjacent +node pairs. Otherwise, only one arc will be generated. If this is the +case, the arcs will be generated in alterntive directions as shown +below. + +\medskip + +\noindent\hfil +\xymatrix +{1\ar[r]\ar[d]&2\ar[r]&3\ar[r]\ar[d]&4\ar[r]&5\ar[d]\\ +6\ar[d]&7\ar[l]\ar[u]&8\ar[l]\ar[d]&9\ar[l]\ar[u]&10\ar[l]\ar[d]\\ +11\ar[r]&12\ar[r]\ar[u]&13\ar[r]&14\ar[r]\ar[u]&15\\ +} + +\medskip + +Then the arcs between the super node and the source/sink nodes are +added as mentioned before. If the number of arcs still doesn't reach +the requirement, additional arcs will be added by uniformly picking +random node pairs. There is no checking to prevent multiple arcs +between any pair of nodes. However, there will be no self-arcs (arcs +that poins back to its tail node) in the network. + +The source and sink nodes are selected uniformly in the network, and +the imbalances of each source/sink node are also assigned by uniform +distribution. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Maximum flow problem} + +\subsection{Background} + +The {\it maximum flow problem} (MAXFLOW) is stated as follows. Let +there be given a directed graph (flow network) $G=(V,A)$, where $V$ is +a set of vertices (nodes), and $A\subseteq V\times V$ is a set of arcs. +Let also for each arc $a=(i,j)\in A$ there be given its capacity +$u_{ij}$. The problem is, for given {\it source} node $s\in V$ and +{\it sink} node $t\in V$, to find flows $x_{ij}$ through every arc of +the network, which satisfy the specified arc capacities and the +conservation constraints at all nodes, and maximize the total flow $F$ +through the network from $s$ to $t$. Here the conservation constraint +at a node means that the total flow entering this node through its +incoming arcs (plus $F$, if it is the source node) must be equal to the +total flow leaving this node through its outgoing arcs (plus $F$, if it +is the sink node). An example of the maximum flow problem, +where $s=v_1$ and $t=v_9$, is shown on Fig.~2. + +\medskip + +\noindent\hfil +\xymatrix @C=48pt +{_{F}\ar@{~>}[d]& +v_2\ar[r]|{_{10}}\ar[dd]|{_{9}}& +v_3\ar[dd]|{_{12}}\ar[r]|{_{18}}& +v_8\ar[rd]|{_{20}}&\\ +v_1\ar[ru]|{_{14}}\ar[rd]|{_{23}}&&& +v_6\ar[d]|{_{7}}\ar[u]|{_{8}}& +v_9\ar@{~>}[d]\\ +&v_4\ar[r]|{_{26}}& +v_5\ar[luu]|{_{11}}\ar[ru]|{_{25}}\ar[r]|{_{4}}& +v_7\ar[ru]|{_{15}}&_{F}\\ +} + +\medskip + +\noindent\hfil +Fig.~2. An example of the maximum flow problem. + +\medskip + +The maximum flow problem can be naturally formulated as the following +LP problem: + +\noindent +\hspace{1in}maximize +$$F\eqno(4)$$ +\hspace{1in}subject to +$$\sum_{(i,j)\in A}x_{ij}-\sum_{(j,i)\in A}x_{ji}=\left\{ +\begin{array}{@{\ }rl} ++F,&\hbox{for}\ i=s\\ + 0,&\hbox{for all}\ i\in V\backslash\{s,t\}\\ +-F,&\hbox{for}\ i=t\\ +\end{array} +\right.\eqno(5) +$$ +$$0\leq x_{ij}\leq u_{ij}\ \ \ \hbox{for all}\ (i,j)\in A +\eqno(6)$$ + +\noindent +where $F\geq 0$ is an additional variable playing the role of the +objective. + +Another LP formulation of the maximum flow problem, which does not +include the variable $F$, is the following: + +\noindent +\hspace{1in}maximize +$$z=\sum_{(s,j)\in A}x_{sj}-\sum_{(j,s)\in A}x_{js}\ (=F)\eqno(7)$$ +\hspace{1in}subject to +$$\sum_{(i,j)\in A}x_{ij}-\sum_{(j,i)\in A}x_{ji}\left\{ +\begin{array}{@{\ }rl} +\geq 0,&\hbox{for}\ i=s\\ +=0,&\hbox{for all}\ i\in V\backslash\{s,t\}\\ +\leq 0,&\hbox{for}\ i=t\\ +\end{array} +\right.\eqno(8) +$$ +$$0\leq x_{ij}\leq u_{ij}\ \ \ \hbox{for all}\ (i,j)\in A +\eqno(9)$$ + +\subsection{glp\_read\_maxflow --- read maximum flow problem data in +DIMACS\\format} + +\synopsis + +\begin{verbatim} + int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap, + const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_maxflow| reads the maximum flow problem +data from a text file in DIMACS format. + +The parameter \verb|G| specifies the graph object, to which the problem +data have to be stored. Note that before reading data the current +content of the graph object is completely erased with the routine +\verb|glp_erase_graph|. + +The pointer \verb|s| specifies a location, to which the routine stores +the ordinal number of the source node. If \verb|s| is \verb|NULL|, the +source node number is not stored. + +The pointer \verb|t| specifies a location, to which the routine stores +the ordinal number of the sink node. If \verb|t| is \verb|NULL|, the +sink node number is not stored. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$u_{ij}$, the arc capacity. If \verb|a_cap| $<0$, the arc capacity is +not stored. + +The character string \verb|fname| specifies the name of a text file to +be read in. (If the file name name ends with the suffix `\verb|.gz|', +the file is assumed to be compressed, in which case the routine +decompresses it ``on the fly''.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\para{Example} + +\begin{footnotesize} +\begin{verbatim} +typedef struct +{ /* arc data block */ + ... + double cap; + ... +} a_data; + +int main(void) +{ glp_graph *G; + int s, t, ret; + G = glp_create_graph(..., sizeof(a_data)); + ret = glp_read_maxflow(G, &s, &t, offsetof(a_data, cap), + "sample.max"); + if (ret != 0) goto ... + ... +} +\end{verbatim} +\end{footnotesize} + +\newpage + +\para{DIMACS maximum flow problem format\footnote{This material is +based on the paper ``The First DIMACS International Algorithm +Implementation Challenge: Problem Definitions and Specifications'', +which is publically available at +\url{http://dimacs.rutgers.edu/Challenges/}.}} +\label{subsecmaxflow} + +The DIMACS input file is a plain ASCII text file. It contains +{\it lines} of several types described below. A line is terminated with +an end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +Note that DIMACS requires all numerical quantities to be integers in +the range $[-2^{31},\ 2^{31}-1]$ while GLPK allows the quantities to be +floating-point numbers. + +\para{Comment lines.} Comment lines give human-readable information +about the file and are ignored by programs. Comment lines can appear +anywhere in the file. Each comment line begins with a lower-case +character \verb|c|. + +\begin{verbatim} + c This is a comment line +\end{verbatim} + +\para{Problem line.} There is one problem line per data file. The +problem line must appear before any node or arc descriptor lines. +It has the following format: + +\begin{verbatim} + p max NODES ARCS +\end{verbatim} + +\noindent +The lower-case character \verb|p| signifies that this is a problem line. +The three-character problem designator \verb|max| identifies the file as +containing specification information for the maximum flow problem. The +\verb|NODES| field contains an integer value specifying the number of +nodes in the network. The \verb|ARCS| field contains an integer value +specifying the number of arcs in the network. + +\para{Node descriptors.} Two node descriptor lines for the source and +sink nodes must appear before all arc descriptor lines. They may appear +in either order, each with the following format: + +\begin{verbatim} + n ID WHICH +\end{verbatim} + +\noindent +The lower-case character \verb|n| signifies that this a node descriptor +line. The \verb|ID| field gives a node identification number, +an integer between 1 and \verb|NODES|. The \verb|WHICH| field gives +either a lower-case \verb|s| or \verb|t|, designating the source and +sink, respectively. + +\para{Arc descriptors.} There is one arc descriptor line for each arc +in the network. Arc descriptor lines are of the following format: + +\begin{verbatim} + a SRC DST CAP +\end{verbatim} + +\noindent +The lower-case character \verb|a| signifies that this is an arc +descriptor line. For a directed arc $(i,j)$ the \verb|SRC| field gives +the identification number $i$ for the tail endpoint, and the \verb|DST| +field gives the identification number $j$ for the head endpoint. +Identification numbers are integers between 1 and \verb|NODES|. The +\verb|CAP| field gives the arc capacity, i.e. maximum amount of flow +that can be sent along arc $(i,j)$ in a feasible flow. + +\para{Example.} Below here is an example of the data file in DIMACS +format corresponding to the maximum flow problem shown on Fig~2. + +\begin{footnotesize} +\begin{verbatim} +c sample.max +c +c This is an example of the maximum flow problem data +c in DIMACS format. +c +p max 9 14 +c +n 1 s +n 9 t +c +a 1 2 14 +a 1 4 23 +a 2 3 10 +a 2 4 9 +a 3 5 12 +a 3 8 18 +a 4 5 26 +a 5 2 11 +a 5 6 25 +a 5 7 4 +a 6 7 7 +a 6 8 8 +a 7 9 15 +a 8 9 20 +c +c eof +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_write\_maxflow --- write maximum flow problem data in +DIMACS\\format} + +\synopsis + +\begin{verbatim} + int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, + const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_maxflow| writes the maximum flow problem +data to a text file in DIMACS format. + +The parameter \verb|G| is the graph (network) program object, which +specifies the maximum flow problem instance. + +The parameter \verb|s| specifies the ordinal number of the source node. + +The parameter \verb|t| specifies the ordinal number of the sink node. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). If the upper bound is +specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. +the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that +$u_{ij}=1$ for all arcs. + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine performs +automatic compression on writing it.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\newpage + +\subsection{glp\_maxflow\_lp --- convert maximum flow problem to LP} + +\synopsis + +\begin{verbatim} + void glp_maxflow_lp(glp_prob *P, glp_graph *G, int names, int s, int t, + int a_cap); +\end{verbatim} + +\description + +The routine \verb|glp_maxflow_lp| builds LP problem (7)---(9), which +corresponds to the specified maximum flow problem. + +The parameter \verb|P| is the resultant LP problem object to be built. +Note that on entry its current content is erased with the routine +\verb|glp_erase_prob|. + +The parameter \verb|G| is the graph (network) program object, which +specifies the maximum flow problem instance. + +The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the +routine uses symbolic names of the graph object components to assign +symbolic names to the LP problem object components. If the flag is +\verb|GLP_OFF|, no symbolic names are assigned. + +The parameter \verb|s| specifies the ordinal number of the source node. + +The parameter \verb|t| specifies the ordinal number of the sink node. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). If the upper bound is +specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. +the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that +$u_{ij}=1$ for all arcs. + +\para{Example} + +The example program below reads the maximum flow problem in DIMACS +format from file `\verb|sample.max|', converts the instance to LP, and +then writes the resultant LP in CPLEX format to file +`\verb|maxflow.lp|'. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <glpk.h> + +int main(void) +{ glp_graph *G; + glp_prob *P; + int s, t; + G = glp_create_graph(0, sizeof(double)); + glp_read_maxflow(G, &s, &t, 0, "sample.max"); + P = glp_create_prob(); + glp_maxflow_lp(P, G, GLP_ON, s, t, 0); + glp_delete_graph(G); + glp_write_lp(P, NULL, "maxflow.lp"); + glp_delete_prob(P); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.max|' is the example data file from the previous +subsection, the output `\verb|maxflow.lp|' may look like follows: + +\newpage + +\begin{footnotesize} +\begin{verbatim} +Maximize + obj: + x(1,4) + x(1,2) + +Subject To + r_1: + x(1,2) + x(1,4) >= 0 + r_2: - x(5,2) + x(2,3) + x(2,4) - x(1,2) = 0 + r_3: + x(3,5) + x(3,8) - x(2,3) = 0 + r_4: + x(4,5) - x(2,4) - x(1,4) = 0 + r_5: + x(5,2) + x(5,6) + x(5,7) - x(4,5) - x(3,5) = 0 + r_6: + x(6,7) + x(6,8) - x(5,6) = 0 + r_7: + x(7,9) - x(6,7) - x(5,7) = 0 + r_8: + x(8,9) - x(6,8) - x(3,8) = 0 + r_9: - x(8,9) - x(7,9) <= 0 + +Bounds + 0 <= x(1,4) <= 23 + 0 <= x(1,2) <= 14 + 0 <= x(2,4) <= 9 + 0 <= x(2,3) <= 10 + 0 <= x(3,8) <= 18 + 0 <= x(3,5) <= 12 + 0 <= x(4,5) <= 26 + 0 <= x(5,7) <= 4 + 0 <= x(5,6) <= 25 + 0 <= x(5,2) <= 11 + 0 <= x(6,8) <= 8 + 0 <= x(6,7) <= 7 + 0 <= x(7,9) <= 15 + 0 <= x(8,9) <= 20 + +End +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_maxflow\_ffalg --- solve maximum flow problem with +Ford-Fulkerson\\algorithm} + +\synopsis + +\begin{verbatim} + int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap, double *sol, + int a_x, int v_cut); +\end{verbatim} + +\description + +The routine \verb|glp_mincost_ffalg| finds optimal solution to the +maximum flow problem with the Ford-Fulkerson algorithm.\footnote{GLPK +implementation of the Ford-Fulkerson algorithm is based on the +following book: L.~R.~Ford,~Jr., and D.~R.~Fulkerson, ``Flows in +Networks,'' The RAND Corp., Report R-375-PR (August 1962), Chap. I +``Static Maximal Flow,'' pp.~30-33.} Note that this routine requires +all the problem data to be integer-valued. + +The parameter \verb|G| is a graph (network) program object which +specifies the maximum flow problem instance to be solved. + +The parameter $s$ specifies the ordinal number of the source node. + +\newpage + +The parameter $t$ specifies the ordinal number of the sink node. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). This bound must be integer in +the range [0, \verb|INT_MAX|]. If \verb|a_cap| $<0$, it is assumed that +$u_{ij}=1$ for all arcs. + +The parameter \verb|sol| specifies a location, to which the routine +stores the objective value (that is, the total flow from $s$ to $t$) +found. If \verb|sol| is NULL, the objective value is not stored. + +The parameter \verb|a_x| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$x_{ij}$, the arc flow found. If \verb|a_x| $<0$, the arc flow values +are not stored. + +The parameter \verb|v_cut| specifies an offset of the field of type +\verb|int| in the vertex data block, to which the routine stores node +flags corresponding to the optimal solution found: if the node flag is +1, the node is labelled, and if the node flag is 0, the node is +unlabelled. The calling program may use these node flags to determine +the {\it minimal cut}, which is a subset of arcs whose one endpoint is +labelled and other is not. If \verb|v_cut| $<0$, the node flags are not +stored. + +Note that all solution components (the objective value and arc flows) +computed by the routine are always integer-valued. + +\returns + +\begin{retlist} +0 & Optimal solution found.\\ + +\verb|GLP_EDATA| & Unable to start the search, because some problem +data are either not integer-valued or out of range.\\ +\end{retlist} + +\para{Example} + +The example program shown below reads the maximum flow problem instance +in DIMACS format from file `\verb|sample.max|', solves it using the +routine \verb|glp_maxflow_ffalg|, and write the solution found to the +standard output. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +typedef struct { int cut; } v_data; +typedef struct { double cap, x; } a_data; + +#define node(v) ((v_data *)((v)->data)) +#define arc(a) ((a_data *)((a)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v, *w; + glp_arc *a; + int i, s, t, ret; + double sol; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + glp_read_maxflow(G, &s, &t, offsetof(a_data, cap), + "sample.max"); + ret = glp_maxflow_ffalg(G, s, t, offsetof(a_data, cap), + &sol, offsetof(a_data, x), offsetof(v_data, cut)); + printf("ret = %d; sol = %5g\n", ret, sol); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { w = a->head; + printf("x[%d->%d] = %5g (%d)\n", v->i, w->i, + arc(a)->x, node(v)->cut ^ node(w)->cut); + } + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.max|' is the example data file from the subsection +describing \verb|glp_read_maxflow|, the output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading maximum flow problem data from `sample.max'... +Flow network has 9 nodes and 14 arcs +24 lines were read +ret = 0; sol = 29 +x[1->4] = 19 (0) +x[1->2] = 10 (0) +x[2->4] = 0 (0) +x[2->3] = 10 (1) +x[3->8] = 10 (0) +x[3->5] = 0 (1) +x[4->5] = 19 (0) +x[5->7] = 4 (1) +x[5->6] = 15 (0) +x[5->2] = 0 (0) +x[6->8] = 8 (1) +x[6->7] = 7 (1) +x[7->9] = 11 (0) +x[8->9] = 18 (0) +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_rmfgen --- Goldfarb's maximum flow problem generator} + +\synopsis + +\begin{verbatim} + int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap, const int parm[1+5]); +\end{verbatim} + +\description + +The routine \verb|glp_rmfgen| is a GLPK version of the maximum flow +problem generator developed by D.~Goldfarb and +M.~Grigoriadis.\footnote{D.~Goldfarb and M.~D.~Grigoriadis, +``A computational comparison of the Dinic and network simplex methods +for maximum flow.'' Annals of Op. Res. 13 (1988), +pp.~83-123.}$^{,}$\footnote{U.~Derigs and W.~Meier, ``Implementing +Goldberg's max-flow algorithm: A computational investigation.'' +Zeitschrift f\"ur Operations Research 33 (1989), +pp.~383-403.}$^{,}$\footnote{The original code of RMFGEN implemented by +Tamas Badics is publically available from +\url{ftp://dimacs.rutgers.edu/pub/netflow/generators/network/genrmf}.} + +The parameter \verb|G| specifies the graph object, to which the +generated problem data have to be stored. Note that on entry the graph +object is erased with the routine \verb|glp_erase_graph|. + +\newpage + +The pointers \verb|s| and \verb|t| specify locations, to which the +routine stores the source and sink node numbers, respectively. If +\verb|s| or \verb|t| is \verb|NULL|, corresponding node number is not +stored. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the arc +capacity. If \verb|a_cap| $<0$, the capacity is not stored. + +The array \verb|parm| contains description of the network to be +generated: + +\begin{tabular}{@{}lll@{}} +\verb|parm[0]|& ¬ used\\ +\verb|parm[1]|&\verb|seed|&random number seed (a positive integer)\\ +\verb|parm[2]|&\verb|a |&frame size\\ +\verb|parm[3]|&\verb|b |&depth\\ +\verb|parm[4]|&\verb|c1 |&minimal arc capacity\\ +\verb|parm[5]|&\verb|c2 |&maximal arc capacity\\ +\end{tabular} + +\returns + +If the instance was successfully generated, the routine +\verb|glp_netgen| returns zero; otherwise, if specified parameters are +inconsistent, the routine returns a non-zero error code. + +\para{Comments\footnote{This material is based on comments to the +original version of RMFGEN.}} + +The generated network is as follows. It has $b$ pieces of frames of +size $a\times a$. (So alltogether the number of vertices is +$a\times a\times b$.) + +In each frame all the vertices are connected with their neighbours +(forth and back). In addition the vertices of a frame are connected +one to one with the vertices of next frame using a random permutation +of those vertices. + +The source is the lower left vertex of the first frame, the sink is +the upper right vertex of the $b$-th frame. + +\begin{verbatim} + t + +-------+ + | .| + | . | + / | / | + +-------+/ -+ b + | | |/. + a | -v- |/ + | | |/ + +-------+ 1 + s a +\end{verbatim} + +The capacities are randomly chosen integers from the range of +$[c_1,c_2]$ in the case of interconnecting edges, and $c_2\cdot a^2$ +for the in-frame edges. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Assignment problem} + +\subsection{Background} + +Let there be given an undirected bipartite graph $G=(R\cup S,E)$, where +$R$ and $S$ are disjoint sets of vertices (nodes), and +$E\subseteq R\times S$ is a set of edges. Let also for each edge +$e=(i,j)\in E$ there be given its cost $c_{ij}$. A {\it matching} +(which in case of bipartite graph is also called {\it assignment}) +$M\subseteq E$ in $G$ is a set of pairwise non-adjacent edges, that is, +no two edges in $M$ share a common vertex. A matching, which matches +all vertices of the graph, is called a {\it perfect matching}. +Obviously, a perfect matching in bipartite graph $G=(R\cup S,E)$ +defines some bijection $R\leftrightarrow S$. + +The {\it assignment problem} has two different variants. In the first +variant the problem is to find matching (assignment) $M$, which +maximizes the sum: +$$\sum_{(i,j)\in M}c_{ij}\eqno(10)$$ +(so this variant is also called the {\it maximum weighted bipartite +matching problem} or, if all $c_{ij}=1$, the {\it maximum cardinality +bipartite matching problem}). In the second, classic variant the +problem is to find {\it perfect} matching (assignment) $M$, which +minimizes or maximizes the sum (10). + +An example of the assignment problem, which is the maximum weighted +bipartite matching problem, is shown on Fig. 3. + +The maximum weighted bipartite matching problem can be naturally +formulated as the following LP problem: + +\noindent +\hspace{1in}maximize +$$z=\sum_{(i,j)\in E}c_{ij}x_{ij}\eqno(11)$$ +\hspace{1in}subject to +$$\sum_{(i,j)\in E}x_{ij}\leq 1\ \ \ \hbox{for all}\ i\in R\eqno(12)$$ +$$\sum_{(i,j)\in E}x_{ij}\leq 1\ \ \ \hbox{for all}\ j\in S\eqno(13)$$ +$$\ \ \ \ \ \ \ \ 0\leq x_{ij}\leq 1\ \ \ \hbox{for all}\ (i,j)\in E +\eqno(14)$$ + +\noindent +where $x_{ij}=1$ means that $(i,j)\in M$, and $x_{ij}=0$ means that +$(i,j)\notin M$.\footnote{The constraint matrix of LP formulation +(11)---(14) is totally unimodular, due to which $x_{ij}\in\{0,1\}$ for +any basic solution.} + +\newpage + +\noindent\hfil +\xymatrix @C=48pt +{v_1\ar@{-}[rr]|{_{13}}\ar@{-}[rrd]|{_{21}}\ar@{-}[rrddd]|(.2){_{20}}&& +v_9\\ +v_2\ar@{-}[rr]|{_{12}}\ar@{-}[rrdd]|(.3){_{8}} +\ar@{-}[rrddd]|(.4){_{26}}&&v_{10}\\ +v_3\ar@{-}[rr]|(.2){_{22}}\ar@{-}[rrdd]|(.3){_{11}}&&v_{11}\\ +v_4\ar@{-}[rruuu]|(.6){_{12}}\ar@{-}[rr]|(.2){_{36}} +\ar@{-}[rrdd]|(.7){_{25}}&&v_{12}\\ +v_5\ar@{-}[rruu]|(.42){_{41}}\ar@{-}[rru]|(.4){_{40}} +\ar@{-}[rr]|(.75){_{11}}\ar@{-}[rrd]|(.6){_{4}}\ar@{-}[rrdd]|{_{8}} +\ar@{-}[rrddd]|{_{35}}\ar@{-}[rrdddd]|{_{32}}&&v_{13}\\ +v_6\ar@{-}[rruuuuu]|(.7){_{13}}&&v_{14}\\ +v_7\ar@{-}[rruuuuu]|(.15){_{19}}&&v_{15}\\ +v_8\ar@{-}[rruuuuuu]|(.25){_{39}}\ar@{-}[rruuuuu]|(.65){_{15}}&& +v_{16}\\ +&&v_{17}\\ +} + +\medskip + +\noindent\hfil +Fig.~3. An example of the assignment problem. + +\medskip + +Similarly, the perfect assignment problem can be naturally formulated +as the following LP problem: + +\noindent +\hspace{1in}minimize (or maximize) +$$z=\sum_{(i,j)\in E}c_{ij}x_{ij}\eqno(15)$$ +\hspace{1in}subject to +$$\sum_{(i,j)\in E}x_{ij}=1\ \ \ \hbox{for all}\ i\in R\eqno(16)$$ +$$\sum_{(i,j)\in E}x_{ij}=1\ \ \ \hbox{for all}\ j\in S\eqno(17)$$ +$$\ \ \ \ \ \ \ \ 0\leq x_{ij}\leq 1\ \ \ \hbox{for all}\ (i,j)\in E +\eqno(18)$$ + +\noindent +where variables $x_{ij}$ have the same meaning as for (11)---(14) +above. + +In GLPK an undirected bipartite graph $G=(R\cup S,E)$ is represented as +directed graph $\overline{G}=(V,A)$, where $V=R\cup S$ and +$A=\{(i,j):(i,j)\in E\}$, i.e. every edge $(i,j)\in E$ in $G$ +corresponds to arc $(i\rightarrow j)\in A$ in $\overline{G}$. + +\subsection{glp\_read\_asnprob --- read assignment problem data in +DIMACS format} + +\synopsis + +\begin{verbatim} + int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_asnprob| reads the assignment problem data +from a text file in DIMACS format. + +The parameter \verb|G| specifies the graph object, to which the problem +data have to be stored. Note that before reading data the current +content of the graph object is completely erased with the routine +\verb|glp_erase_graph|. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, to which the routine stores the +node set indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, the node set indicator is not stored. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +edge cost $c_{ij}$. If \verb|a_cost| $<0$, the edge cost is not stored. + +The character string \verb|fname| specifies the name of a text file to +be read in. (If the file name name ends with the suffix `\verb|.gz|', +the file is assumed to be compressed, in which case the routine +decompresses it ``on the fly''.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\para{Example.} Below here is an example program that read the +assignment problem data in DIMACS format from a text file +`\verb|sample.asn|'. + +\begin{footnotesize} +\begin{verbatim} +typedef struct +{ /* vertex data block */ + ... + int set; + ... +} v_data; + +typedef struct +{ /* arc data block */ + ... + double cost; + ... +} a_data; + +int main(void) +{ glp_graph *G; + int ret; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + ret = glp_read_asnprob(G, offsetof(v_data, set), + offsetof(a_data, cost), "sample.asn"); + if (ret != 0) goto ... + ... +} +\end{verbatim} +\end{footnotesize} + +\para{DIMACS assignment problem format\footnote{This material is based +on the paper ``The First DIMACS International Algorithm Implementation +Challenge: Problem Definitions and Specifications'', which is +publically available at \url{http://dimacs.rutgers.edu/Challenges/}.}} +\label{subsecasnprob} + +The DIMACS input file is a plain ASCII text file. It contains +{\it lines} of several types described below. A line is terminated with +an end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +Note that DIMACS requires all numerical quantities to be integers in +the range $[-2^{31},\ 2^{31}-1]$ while GLPK allows the quantities to be +floating-point numbers. + +\para{Comment lines.} Comment lines give human-readable information +about the file and are ignored by programs. Comment lines can appear +anywhere in the file. Each comment line begins with a lower-case +character \verb|c|. + +\begin{verbatim} + c This is a comment line +\end{verbatim} + +\para{Problem line.} There is one problem line per data file. The +problem line must appear before any node or arc descriptor lines. It +has the following format: + +\begin{verbatim} + p asn NODES EDGES +\end{verbatim} + +\noindent +The lower-case character \verb|p| signifies that this is a problem line. +The three-character problem designator \verb|asn| identifies the file as +containing specification information for the assignment problem. +The \verb|NODES| field contains an integer value specifying the total +number of nodes in the graph (i.e. in both sets $R$ and $S$). The +\verb|EDGES| field contains an integer value specifying the number of +edges in the graph. + +\para{Node descriptors.} All node descriptor lines must appear before +all edge descriptor lines. The node descriptor lines lists the nodes in +set $R$ only, and all other nodes are assumed to be in set $S$. There +is one node descriptor line for each such node, with the following +format: + +\begin{verbatim} + n ID +\end{verbatim} + +\noindent +The lower-case character \verb|n| signifies that this is a node +descriptor line. The \verb|ID| field gives a node identification number, +an integer between 1 and \verb|NODES|. + +\para{Edge descriptors.} There is one edge descriptor line for each +edge in the graph. Edge descriptor lines are of the following format: + +\begin{verbatim} + a SRC DST COST +\end{verbatim} + +\noindent +The lower-case character \verb|a| signifies that this is an edge +descriptor line. For each edge $(i,j)$, where $i\in R$ and $j\in S$, +the \verb|SRC| field gives the identification number of vertex $i$, and +the \verb|DST| field gives the identification number of vertex $j$. +Identification numbers are integers between 1 and \verb|NODES|. The +\verb|COST| field contains the cost of edge $(i,j)$. + +\para{Example.} Below here is an example of the data file in DIMACS +format corresponding to the assignment problem shown on Fig~3. + +\begin{footnotesize} +\begin{verbatim} +c sample.asn +c +c This is an example of the assignment problem data +c in DIMACS format. +c +p asn 17 22 +c +n 1 +n 2 +n 3 +n 4 +n 5 +n 6 +n 7 +n 8 +c +a 1 9 13 +a 1 10 21 +a 1 12 20 +a 2 10 12 +a 2 12 8 +a 2 13 26 +a 3 11 22 +a 3 13 11 +a 4 9 12 +a 4 12 36 +a 4 14 25 +a 5 11 41 +a 5 12 40 +a 5 13 11 +a 5 14 4 +a 5 15 8 +a 5 16 35 +a 5 17 32 +a 6 9 13 +a 7 10 19 +a 8 10 39 +a 8 11 15 +c +c eof +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_write\_asnprob --- write assignment problem data in +DIMACS format} + +\synopsis + +\begin{verbatim} + int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_asnprob| writes the assignment problem data +to a text file in DIMACS format. + +The parameter \verb|G| is the graph program object, which specifies the +assignment problem instance. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, which contains the node set +indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs +is in set $R$, and a node having no outgoing arcs is in set $S$. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the edge +cost. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=1$ for all +edges. + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine performs +automatic compression on writing it.) + +\para{Note} + +The routine \verb|glp_write_asnprob| does not check that the specified +graph object correctly represents a bipartite graph. To make sure that +the problem data are correct, use the routine \verb|glp_check_asnprob|. + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\vspace*{-4pt} + +\subsection{glp\_check\_asnprob --- check correctness of assignment +problem data} + +\synopsis + +\begin{verbatim} + int glp_check_asnprob(glp_graph *G, int v_set); +\end{verbatim} + +\description + +The routine \verb|glp_check_asnprob| checks that the specified graph +object \verb|G| correctly represents a bipartite graph. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, which contains the node set +indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs +is in set $R$, and a node having no outgoing arcs is in set $S$. + +\returns + +0 --- the data are correct; + +1 --- the set indicator of some node is 0, however, that node has one +or more incoming arcs; + +2 --- the set indicator of some node is 1, however, that node has one +or more outgoing arcs; + +3 --- the set indicator of some node is invalid (neither 0 nor 1); + +4 --- some node has both incoming and outgoing arcs. + +\subsection{glp\_asnprob\_lp --- convert assignment problem to LP} + +\synopsis + +\begin{verbatim} + int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, int v_set, + int a_cost); +\end{verbatim} + +\description + +The routine \verb|glp_asnprob_lp| builds LP problem, which corresponds +to the specified assignment problem. + +The parameter \verb|P| is the resultant LP problem object to be built. +Note that on entry its current content is erased with the routine +\verb|glp_erase_prob|. + +The parameter \verb|form| defines which LP formulation should be used: + +\verb|GLP_ASN_MIN| --- perfect matching (15)---(18), minimization; + +\verb|GLP_ASN_MAX| --- perfect matching (15)---(18), maximization; + +\verb|GLP_ASN_MMP| --- maximum weighted matching (11)---(14). + +The parameter \verb|G| is the graph program object, which specifies the +assignment problem instance. + +The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the +routine uses symbolic names of the graph object components to assign +symbolic names to the LP problem object components. If the \verb|flag| +is \verb|GLP_OFF|, no symbolic names are assigned. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, which contains the node set +indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs +is in set $R$, and a node having no outgoing arcs is in set $S$. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the edge +cost. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=1$ for all +edges. + +\newpage + +\returns + +If the LP problem has been successfully built, the routine +\verb|glp_asnprob_lp| returns zero, otherwise, non-zero (see the +routine \verb|glp_check_asnprob|). + +\para{Example} + +The example program below reads the assignment problem instance in +DIMACS format from file `\verb|sample.asn|', converts the instance to +LP (11)---(14), and writes the resultant LP in CPLEX format to file +`\verb|matching.lp|'. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <glpk.h> + +typedef struct { int set; } v_data; +typedef struct { double cost; } a_data; + +int main(void) +{ glp_graph *G; + glp_prob *P; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + glp_read_asnprob(G, offsetof(v_data, set), + offsetof(a_data, cost), "sample.asn"); + P = glp_create_prob(); + glp_asnprob_lp(P, GLP_ASN_MMP, G, GLP_ON, + offsetof(v_data, set), offsetof(a_data, cost)); + glp_delete_graph(G); + glp_write_lp(P, NULL, "matching.lp"); + glp_delete_prob(P); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.asn|' is the example data file from the subsection +describing \verb|glp_read_asnprob|, file `\verb|matching.lp|' may look +like follows: + +\begin{footnotesize} +\begin{verbatim} +Maximize + obj: + 20 x(1,12) + 21 x(1,10) + 13 x(1,9) + 26 x(2,13) + 8 x(2,12) + + 12 x(2,10) + 11 x(3,13) + 22 x(3,11) + 25 x(4,14) + 36 x(4,12) + + 12 x(4,9) + 32 x(5,17) + 35 x(5,16) + 8 x(5,15) + 4 x(5,14) + + 11 x(5,13) + 40 x(5,12) + 41 x(5,11) + 13 x(6,9) + 19 x(7,10) + + 15 x(8,11) + 39 x(8,10) + +Subject To + r_1: + x(1,9) + x(1,10) + x(1,12) <= 1 + r_2: + x(2,10) + x(2,12) + x(2,13) <= 1 + r_3: + x(3,11) + x(3,13) <= 1 + r_4: + x(4,9) + x(4,12) + x(4,14) <= 1 + r_5: + x(5,11) + x(5,12) + x(5,13) + x(5,14) + x(5,15) + x(5,16) + + x(5,17) <= 1 + r_6: + x(6,9) <= 1 + r_7: + x(7,10) <= 1 + r_8: + x(8,10) + x(8,11) <= 1 + r_9: + x(6,9) + x(4,9) + x(1,9) <= 1 + r_10: + x(8,10) + x(7,10) + x(2,10) + x(1,10) <= 1 + r_11: + x(8,11) + x(5,11) + x(3,11) <= 1 + r_12: + x(5,12) + x(4,12) + x(2,12) + x(1,12) <= 1 + r_13: + x(5,13) + x(3,13) + x(2,13) <= 1 + r_14: + x(5,14) + x(4,14) <= 1 + r_15: + x(5,15) <= 1 + r_16: + x(5,16) <= 1 + r_17: + x(5,17) <= 1 + +Bounds + 0 <= x(1,12) <= 1 + 0 <= x(1,10) <= 1 + 0 <= x(1,9) <= 1 + 0 <= x(2,13) <= 1 + 0 <= x(2,12) <= 1 + 0 <= x(2,10) <= 1 + 0 <= x(3,13) <= 1 + 0 <= x(3,11) <= 1 + 0 <= x(4,14) <= 1 + 0 <= x(4,12) <= 1 + 0 <= x(4,9) <= 1 + 0 <= x(5,17) <= 1 + 0 <= x(5,16) <= 1 + 0 <= x(5,15) <= 1 + 0 <= x(5,14) <= 1 + 0 <= x(5,13) <= 1 + 0 <= x(5,12) <= 1 + 0 <= x(5,11) <= 1 + 0 <= x(6,9) <= 1 + 0 <= x(7,10) <= 1 + 0 <= x(8,11) <= 1 + 0 <= x(8,10) <= 1 + +End +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_asnprob\_okalg --- solve assignment problem with +out-of-kilter\\algorithm} + +\synopsis + +\begin{verbatim} + int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost, + double *sol, int a_x); +\end{verbatim} + +\description + +The routine \verb|glp_mincost_okalg| finds optimal solution to the +assignment problem with the out-of-kilter +algorithm.\footnote{GLPK implementation of the out-of-kilter algorithm +is based on the following book: L.~R.~Ford,~Jr., and D.~R.~Fulkerson, +``Flows in Networks,'' The RAND Corp., Report R-375-PR (August 1962), +Chap. III ``Minimal Cost Flow Problems,'' pp.~113-26.} Note that this +routine requires all the problem data to be integer-valued. + +The parameter \verb|form| defines which LP formulation should be used: + +\verb|GLP_ASN_MIN| --- perfect matching (15)---(18), minimization; + +\verb|GLP_ASN_MAX| --- perfect matching (15)---(18), maximization; + +\verb|GLP_ASN_MMP| --- maximum weighted matching (11)---(14). + +\newpage + +The parameter \verb|G| is the graph program object, which specifies the +assignment problem instance. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, which contains the node set +indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs +is in set $R$, and a node having no outgoing arcs is in set $S$. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the edge +cost. This value must be integer in the range [\verb|-INT_MAX|, +\verb|+INT_MAX|]. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=1$ +for all edges. + +The parameter \verb|sol| specifies a location, to which the routine +stores the objective value (that is, the total cost) found. +If \verb|sol| is \verb|NULL|, the objective value is not stored. + +The parameter \verb|a_x| specifies an offset of the field of type +\verb|int| in the arc data block, to which the routine stores $x_{ij}$. +If \verb|a_x| $<0$, this value is not stored. + +\returns + +\begin{retlist} +0 & Optimal solution found.\\ + +\verb|GLP_ENOPFS| & No (primal) feasible solution exists.\\ + +\verb|GLP_EDATA| & Unable to start the search, because the assignment +problem data are either incorrect (this error is detected by the +routine \verb|glp_check_asnprob|), not integer-valued or out of range.\\ + +\verb|GLP_ERANGE| & The search was prematurely terminated because of +integer overflow.\\ + +\verb|GLP_EFAIL| & An error has been detected in the program logic. +(If this code is returned for your problem instance, please report to +\verb|<bug-glpk@gnu.org>|.)\\ +\end{retlist} + +\para{Comments} + +Since the out-of-kilter algorithm is designed to find a minimal cost +circulation, the routine \verb|glp_asnprob_okalg| converts the original +graph to a network suitable for this algorithm in the following +way:\footnote{The conversion is performed internally and does not +change the original graph program object passed to the routine.} + +1) it replaces each edge $(i,j)$ by arc $(i\rightarrow j)$, +flow $x_{ij}$ through which has zero lower bound ($l_{ij}=0$), unity +upper bound ($u_{ij}=1$), and per-unit cost $+c_{ij}$ (in case of +\verb|GLP_ASN_MIN|), or $-c_{ij}$ (in case of \verb|GLP_ASN_MAX| and +\verb|GLP_ASN_MMP|); + +2) then it adds one auxiliary feedback node $k$; + +3) for each original node $i\in R$ the routine adds auxiliary supply +arc $(k\rightarrow i)$, flow $x_{ki}$ through which is costless +($c_{ki}=0$) and either fixed at 1 ($l_{ki}=u_{ki}=1$, in case of +\verb|GLP_ASN_MIN| and \verb|GLP_ASN_MAX|) or has zero lower bound and +unity upper bound ($l_{ij}=0$, $u_{ij}=1$, in case of +\verb|GLP_ASN_MMP|); + +\newpage + +4) similarly, for each original node $j\in S$ the routine adds +auxiliary demand arc $(j\rightarrow k)$, flow $x_{jk}$ through which is +costless ($c_{jk}=0$) and either fixed at 1 ($l_{jk}=u_{jk}=1$, in case +of \verb|GLP_ASN_MIN| and \verb|GLP_ASN_MAX|) or has zero lower bound +and unity upper bound ($l_{jk}=0$, $u_{jk}=1$, in case of +\verb|GLP_ASN_MMP|). + +\para{Example} + +The example program shown below reads the assignment problem instance +in DIMACS format from file `\verb|sample.asn|', solves it by using the +routine \verb|glp_asnprob_okalg|, and writes the solution found to the +standard output. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +typedef struct { int set; } v_data; +typedef struct { double cost; int x; } e_data; + +#define node(v) ((v_data *)((v)->data)) +#define edge(e) ((e_data *)((e)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v; + glp_arc *e; + int i, ret; + double sol; + G = glp_create_graph(sizeof(v_data), sizeof(e_data)); + glp_read_asnprob(G, offsetof(v_data, set), + offsetof(e_data, cost), "sample.asn"); + ret = glp_asnprob_okalg(GLP_ASN_MMP, G, + offsetof(v_data, set), offsetof(e_data, cost), &sol, + offsetof(e_data, x)); + printf("ret = %d; sol = %5g\n", ret, sol); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (e = v->out; e != NULL; e = e->t_next) + printf("edge %2d %2d: x = %d; c = %g\n", + e->tail->i, e->head->i, edge(e)->x, edge(e)->cost); + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.asn|' is the example data file from the subsection +describing \verb|glp_read_asnprob|, the output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading assignment problem data from `sample.asn'... +Assignment problem has 8 + 9 = 17 nodes and 22 arcs +38 lines were read +ret = 0; sol = 180 +edge 1 12: x = 1; c = 20 +edge 1 10: x = 0; c = 21 +edge 1 9: x = 0; c = 13 +edge 2 13: x = 1; c = 26 +edge 2 12: x = 0; c = 8 +edge 2 10: x = 0; c = 12 +edge 3 13: x = 0; c = 11 +edge 3 11: x = 1; c = 22 +edge 4 14: x = 1; c = 25 +edge 4 12: x = 0; c = 36 +edge 4 9: x = 0; c = 12 +edge 5 17: x = 0; c = 32 +edge 5 16: x = 1; c = 35 +edge 5 15: x = 0; c = 8 +edge 5 14: x = 0; c = 4 +edge 5 13: x = 0; c = 11 +edge 5 12: x = 0; c = 40 +edge 5 11: x = 0; c = 41 +edge 6 9: x = 1; c = 13 +edge 7 10: x = 0; c = 19 +edge 8 11: x = 0; c = 15 +edge 8 10: x = 1; c = 39 +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_asnprob\_hall --- find bipartite matching of maximum +cardinality} + +\synopsis + +\begin{verbatim} + int glp_asnprob_hall(glp_graph *G, int v_set, int a_x); +\end{verbatim} + +\description + +The routine \verb|glp_asnprob_hall| finds a matching of maximal +cardinality in the specified bipartite graph. It uses a version of the +Fortran routine \verb|MC21A| developed by +I.~S.~Duff\footnote{I.~S.~Duff, Algorithm 575: Permutations for +zero-free diagonal, ACM Trans. on Math. Softw. 7 (1981),\linebreak +pp.~387-390.}, which implements Hall's algorithm.\footnote{M.~Hall, +``An Algorithm for Distinct Representatives,'' Am. Math. Monthly 63 +(1956), pp.~716-717.} + +The parameter \verb|G| is a pointer to the graph program object. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, which contains the node set +indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs +is in set $R$, and a node having no outgoing arcs is in set $S$. + +The parameter \verb|a_x| specifies an offset of the field of type +\verb|int| in the arc data block, to which the routine stores $x_{ij}$. +If \verb|a_x| $<0$, this value is not stored. + +\returns + +The routine \verb|glp_asnprob_hall| returns the cardinality of the +matching found. However, if the specified graph is incorrect (as +detected by the routine \verb|glp_check_asnprob|), this routine returns +a negative value. + +\newpage + +\para{Comments} + +The same solution may be obtained with the routine +\verb|glp_asnprob_okalg| (for LP formulation \verb|GLP_ASN_MMP| and +all edge costs equal to 1). However, the routine +\verb|glp_asnprob_hall| is much faster. + +\para{Example} + +The example program shown below reads the assignment problem instance +in DIMACS format from file `\verb|sample.asn|', finds a bipartite +matching of maximal cardinality by using the routine +\verb|glp_asnprob_hall|, and writes the solution found to the standard +output. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +typedef struct { int set; } v_data; +typedef struct { int x; } e_data; + +#define node(v) ((v_data *)((v)->data)) +#define edge(e) ((e_data *)((e)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v; + glp_arc *e; + int i, card; + G = glp_create_graph(sizeof(v_data), sizeof(e_data)); + glp_read_asnprob(G, offsetof(v_data, set), -1, + "sample.asn"); + card = glp_asnprob_hall(G, offsetof(v_data, set), + offsetof(e_data, x)); + printf("card = %d\n", card); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (e = v->out; e != NULL; e = e->t_next) + printf("edge %2d %2d: x = %d\n", + e->tail->i, e->head->i, edge(e)->x); + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.asn|' is the example data file from the subsection +describing \verb|glp_read_asnprob|, the output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading assignment problem data from `sample.asn'... +Assignment problem has 8 + 9 = 17 nodes and 22 arcs +38 lines were read +card = 7 +edge 1 12: x = 1 +edge 1 10: x = 0 +edge 1 9: x = 0 +edge 2 13: x = 1 +edge 2 12: x = 0 +edge 2 10: x = 0 +edge 3 13: x = 0 +edge 3 11: x = 1 +edge 4 14: x = 1 +edge 4 12: x = 0 +edge 4 9: x = 0 +edge 5 17: x = 1 +edge 5 16: x = 0 +edge 5 15: x = 0 +edge 5 14: x = 0 +edge 5 13: x = 0 +edge 5 12: x = 0 +edge 5 11: x = 0 +edge 6 9: x = 1 +edge 7 10: x = 1 +edge 8 11: x = 0 +edge 8 10: x = 0 +\end{verbatim} +\end{footnotesize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Critical path problem} + +\subsection{Background} + +The {\it critical path problem} (CPP) is stated as follows. Let there +be given a project $J$, which is a set of jobs (tasks, activities, +etc.). Performing each job $i\in J$ requires time $t_i\geq 0$. Besides, +over the set $J$ there is given a precedence relation +$R\subseteq J\times J$, where $(i,j)\in R$ means that job $i$ +immediately precedes job $j$, i.e. performing job $j$ cannot start +until job $i$ has been completely performed. The problem is to find +starting times $x_i$ for each job $i\in J$, which satisfy to the +precedence relation and minimize the total duration (makespan) of the +project. + +The following is an example of the critical path problem: + +\bigskip + +\begin{center} +\begin{tabular}{|c|l|c|c|} +\hline +Job&Desription&Time&Predecessors\\ +\hline +A&Excavate&3&---\\ +B&Lay foundation&4&A\\ +C&Rough plumbing&3&B\\ +D&Frame&10&B\\ +E&Finish exterior&8&D\\ +F&Install HVAC&4&D\\ +G&Rough electric&6&D\\ +H&Sheet rock&8&C, E, F, G\\ +I&Install cabinets&5&H\\ +J&Paint&5&H\\ +K&Final plumbing&4&I\\ +L&Final electric&2&J\\ +M&Install flooring&4&K, L\\ +\hline +\end{tabular} +\end{center} + +\bigskip + +Obviously, the project along with the precedence relation can be +represented as a directed graph $G=(J,R)$ called {\it project network}, +where each node $i\in J$ corresponds to a job, and arc +$(i\rightarrow j)\in R$ means that job $i$ immediately precedes job +$j$.\footnote{There exists another network representation of the +critical path problem, where jobs correspond to arcs while nodes +correspond to events introduced to express the precedence relation. +That representation, however, is much less convenient than the one, +where jobs are represented as nodes of the network.} The project network +for the example above is shown on Fig.~4. + +May note that the project network must be acyclic; otherwise, it would +be impossible to satisfy to the precedence relation for any job that +belongs to a cycle. + +\newpage + +\hspace*{.5in} +\xymatrix +{&&&C|3\ar[rd]&&I|5\ar[r]&K|4\ar[rd]&\\ +A|3\ar[r]&B|4\ar[rru]\ar[rd]&&E|8\ar[r]&H|8\ar[ru]\ar[rd]&&&M|4\\ +&&D|10\ar[ru]\ar[r]\ar[rd]&F|4\ar[ru]&&J|5\ar[r]&L|2\ar[ru]&\\ +&&&G|6\ar[ruu]&&&&\\ +} + +\medskip + +\noindent\hfil +Fig.~4. An example of the project network. + +\medskip + +The critical path problem can be naturally formulated as the following +LP problem: + +\medskip + +\noindent +\hspace{.5in}minimize +$$z\eqno(19)$$ +\hspace{.5in}subject to +$$x_i+t_i\leq z\ \ \ \hbox{for all}\ i\in J\ \ \ \ \eqno(20)$$ +$$x_i+t_i\leq x_j\ \ \ \hbox{for all}\ (i,j)\in R\eqno(21)$$ +$$x_i\geq 0\ \ \ \ \ \ \ \hbox{for all}\ i\in J\ \ \eqno(22)$$ + +The inequality constraints (21), which are active in the optimal +solution, define so called {\it critical path} having the following +property: the minimal project duration $z$ can be decreased only by +decreasing the times $t_j$ for jobs on the critical path, and delaying +any critical job delays the entire project. + +\subsection{glp\_cpp --- solve critical path problem} + +\synopsis + +\begin{verbatim} + double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls); +\end{verbatim} + +\description + +The routine \verb|glp_cpp| solves the critical path problem represented +in the form of the project network. + +The parameter \verb|G| is a pointer to the graph object, which +specifies the project network. This graph must be acyclic. Multiple +arcs are allowed being considered as single arcs. + +The parameter \verb|v_t| specifies an offset of the field of type +\verb|double| in the vertex data block, which contains time $t_i\geq 0$ +needed to perform corresponding job $j\in J$. If \verb|v_t| $<0$, it is +assumed that $t_i=1$ for all jobs. + +The parameter \verb|v_es| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores +the {\it earliest start time} for corresponding job. If \verb|v_es| +$<0$, this time is not stored. + +\newpage + +The parameter \verb|v_ls| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores +the {\it latest start time} for corresponding job. If \verb|v_ls| +$<0$, this time is not stored. + +The difference between the latest and earliest start times of some job +is called its {\it time reserve}. Delaying a job within its time +reserve does not affect the project duration, so if the time reserve is +zero, the corresponding job is critical. + +\para{Returns} + +The routine \verb|glp_cpp| returns the minimal project duration, i.e. +minimal time needed to perform all jobs in the project. + +\para{Example} + +The example program below solves the critical path problem shown on +Fig.~4 by using the routine \verb|glp_cpp| and writes the solution +found on the standard output. + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +typedef struct { double t, es, ls; } v_data; + +#define node(v) ((v_data *)((v)->data)) + +int main(void) +{ glp_graph *G; + int i; + double t, es, ef, ls, lf, total; + G = glp_create_graph(sizeof(v_data), 0); + glp_add_vertices(G, 13); + node(G->v[1])->t = 3; /* A: Excavate */ + node(G->v[2])->t = 4; /* B: Lay foundation */ + node(G->v[3])->t = 3; /* C: Rough plumbing */ + node(G->v[4])->t = 10; /* D: Frame */ + node(G->v[5])->t = 8; /* E: Finish exterior */ + node(G->v[6])->t = 4; /* F: Install HVAC */ + node(G->v[7])->t = 6; /* G: Rough elecrtic */ + node(G->v[8])->t = 8; /* H: Sheet rock */ + node(G->v[9])->t = 5; /* I: Install cabinets */ + node(G->v[10])->t = 5; /* J: Paint */ + node(G->v[11])->t = 4; /* K: Final plumbing */ + node(G->v[12])->t = 2; /* L: Final electric */ + node(G->v[13])->t = 4; /* M: Install flooring */ + glp_add_arc(G, 1, 2); /* A precedes B */ + glp_add_arc(G, 2, 3); /* B precedes C */ + glp_add_arc(G, 2, 4); /* B precedes D */ + glp_add_arc(G, 4, 5); /* D precedes E */ + glp_add_arc(G, 4, 6); /* D precedes F */ + glp_add_arc(G, 4, 7); /* D precedes G */ + glp_add_arc(G, 3, 8); /* C precedes H */ + glp_add_arc(G, 5, 8); /* E precedes H */ + glp_add_arc(G, 6, 8); /* F precedes H */ + glp_add_arc(G, 7, 8); /* G precedes H */ + glp_add_arc(G, 8, 9); /* H precedes I */ + glp_add_arc(G, 8, 10); /* H precedes J */ + glp_add_arc(G, 9, 11); /* I precedes K */ + glp_add_arc(G, 10, 12); /* J precedes L */ + glp_add_arc(G, 11, 13); /* K precedes M */ + glp_add_arc(G, 12, 13); /* L precedes M */ + total = glp_cpp(G, offsetof(v_data, t), offsetof(v_data, es), + offsetof(v_data, ls)); + printf("Minimal project duration is %.2f\n\n", total); + printf("Job Time ES EF LS LF\n"); + printf("--- ------ ------ ------ ------ ------\n"); + for (i = 1; i <= G->nv; i++) + { t = node(G->v[i])->t; + es = node(G->v[i])->es; + ef = es + node(G->v[i])->t; + ls = node(G->v[i])->ls; + lf = ls + node(G->v[i])->t; + printf("%3d %6.2f %s %6.2f %6.2f %6.2f %6.2f\n", + i, t, ls - es < 0.001 ? "*" : " ", es, ef, ls, lf); + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +The output from the example program shown below includes job number, +the time needed to perform a job, earliest start time (\verb|ES|), +earliest finish time (\verb|EF|), latest start time (\verb|LS|), and +latest finish time (\verb|LF|) for each job in the project. Critical +jobs are marked by asterisks. + +\begin{footnotesize} +\begin{verbatim} +Minimal project duration is 46.00 + +Job Time ES EF LS LF +--- ------ ------ ------ ------ ------ + 1 3.00 * 0.00 3.00 0.00 3.00 + 2 4.00 * 3.00 7.00 3.00 7.00 + 3 3.00 7.00 10.00 22.00 25.00 + 4 10.00 * 7.00 17.00 7.00 17.00 + 5 8.00 * 17.00 25.00 17.00 25.00 + 6 4.00 17.00 21.00 21.00 25.00 + 7 6.00 17.00 23.00 19.00 25.00 + 8 8.00 * 25.00 33.00 25.00 33.00 + 9 5.00 * 33.00 38.00 33.00 38.00 + 10 5.00 33.00 38.00 35.00 40.00 + 11 4.00 * 38.00 42.00 38.00 42.00 + 12 2.00 38.00 40.00 40.00 42.00 + 13 4.00 * 42.00 46.00 42.00 46.00 +\end{verbatim} +\end{footnotesize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Graph Optimization API Routines} + +\section{Maximum clique problem} + +\subsection{Background} + +The {\it maximum clique problem (MCP)} is a classic combinatorial +optimization problem. Given an undirected graph $G=(V,E)$, where $V$ is +a set of vertices, and $E$ is a set of edges, this problem is to find +the largest {\it clique} $C\subseteq G$, i.e. the largest induced +complete subgraph. A generalization of this problem is the {\it maximum +weight clique problem (MWCP)}, which is to find a clique $C\subseteq G$ +of the largest weight $\displaystyle\sum_{v\in C}w(v)\rightarrow\max$, +where $w(v)$ is a weight of vertex $v\in V$. + +An example of the maximum weight clique problem is shown on Fig.~5. + +\begin{figure} +\noindent\hfil +\begin{tabular}{c} +{\xymatrix %@C=16pt +{&&&{v_1}\ar@{-}[lllddd]\ar@{-}[llddddd]\ar@{-}[dddddd] +\ar@{-}[rrrddd]&&&\\ +&{v_2}\ar@{-}[rrrr]\ar@{-}[rrrrdddd]\ar@{-}[rrddddd]\ar@{-}[dddd]&&&& +{v_3}\ar@{-}[llllldd]\ar@{-}[lllldddd]\ar@{-}[dddd]&\\ +&&&&&&\\ +{v_4}\ar@{-}[rrrrrr]\ar@{-}[rrrddd]&&&&&&{v_5}\ar@{-}[lllddd] +\ar@{-}[ldd]\\ +&&&&&&\\ +&{v_6}\ar@{-}[rrrr]&&&&{v_7}&\\ +&&&{v_8}&&&\\ +}} +\end{tabular} +\begin{tabular}{r@{\ }c@{\ }l} +$w(v_1)$&=&3\\$w(v_2)$&=&4\\$w(v_3)$&=&8\\$w(v_4)$&=&1\\ +$w(v_5)$&=&5\\$w(v_6)$&=&2\\$w(v_7)$&=&1\\$w(v_8)$&=&3\\ +\end{tabular} + +\bigskip + +\begin{center} +Fig.~5. An example of the maximum weight clique problem. +\end{center} +\end{figure} + +\subsection{glp\_wclique\_exact --- find maximum weight clique with +exact algorithm} + +\synopsis + +\begin{verbatim} + int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set); +\end{verbatim} + +\description + +The routine {\tt glp\_wclique\_exact} finds a maximum weight clique in +the specified undirected graph with the exact algorithm developed by +Patric \"Osterg{\aa}rd.\footnote{P.~R.~J.~\"Osterg{\aa}rd, A new +algorithm for the maximum-weight clique problem, Nordic J. of +Computing, Vol.~8, No.~4, 2001, pp.~424--36.} + +The parameter {\tt G} is the program object, which specifies +an undirected graph. Each arc $(x\rightarrow y)$ in {\tt G} is +considered as edge $(x,y)$, self-loops are ignored, and multiple edges, +if present, are replaced (internally) by simple edges. + +The parameter {\tt v\_wgt} specifies an offset of the field of type +{\tt double} in the vertex data block, which contains a weight of +corresponding vertex. Vertex weights must be integer-valued in the +range $[0,$ {\tt INT\_MAX}$]$. If {\tt v\_wgt} $<0$, it is assumed that +all vertices of the graph have the weight 1. + +\newpage + +The parameter {\tt sol} specifies a location, to which the routine +stores the weight of the clique found (the clique weight is the sum +of weights of all vertices included in the clique.) If {\tt sol} is +{\tt NULL}, the solution is not stored. + +The parameter {\tt v\_set} specifies an offset of the field of type +{\tt int} in the vertex data block, to which the routines stores a +vertex flag: 1 means that the corresponding vertex is included in the +clique found, and 0 otherwise. If {\tt v\_set} $<0$, vertex flags are +not stored. + +\returns + +\begin{retlist} +0 & Optimal solution found.\\ + +\verb|GLP_EDATA| & Unable to start the search, because some vertex +weights are either not integer-valued or out of range. This code is +also returned if the sum of weights of all vertices exceeds +{\tt INT\_MAX}. \\ +\end{retlist} + +\para{Notes} + +1. The routine {\it glp\_wclique\_exact} finds exact solution. Since +both MCP and MWCP problems are NP-complete, the algorithm may require +exponential time in worst cases. + +2. Internally the specified graph is converted to an adjacency matrix +in {\it dense} format. This requires about $|V|^2/16$ bytes of memory, +where $|V|$ is the number of vertices in the graph. + +\para{Example} + +The example program shown below reads a MWCP instance in DIMACS +clique/coloring format from file `\verb|sample.clq|', finds the clique +of largest weight, and writes the solution found on the standard +output. + +\newpage + +\begin{footnotesize} +\begin{verbatim} +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +typedef struct { double wgt; int set; } v_data; + +#define vertex(v) ((v_data *)((v)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v; + int i, ret; + double sol; + G = glp_create_graph(sizeof(v_data), 0); + glp_read_ccdata(G, offsetof(v_data, wgt), "sample.clq"); + ret = glp_wclique_exact(G, offsetof(v_data, wgt), &sol, + offsetof(v_data, set)); + printf("ret = %d; sol = %g\n", ret, sol); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + printf("vertex %d: weight = %g, flag = %d\n", + i, vertex(v)->wgt, vertex(v)->set); + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +For the example shown on Fig.~5 the data file may look like follows: + +\begin{footnotesize} +\begin{verbatim} +c sample.clq +c +c This is an example of the maximum weight clique +c problem in DIMACS clique/coloring format. +c +p edge 8 16 +n 1 3 +n 2 4 +n 3 8 +n 5 5 +n 6 2 +n 8 3 +e 1 4 +e 1 5 +e 1 6 +e 1 8 +e 2 3 +e 2 6 +e 2 7 +e 2 8 +e 3 4 +e 3 6 +e 3 7 +e 4 5 +e 4 8 +e 5 7 +e 5 8 +e 6 7 +c +c eof +\end{verbatim} +\end{footnotesize} + +The corresponding output from the example program is the following: + +\begin{footnotesize} +\begin{verbatim} +Reading graph from `sample.clq'... +Graph has 8 vertices and 16 edges +28 lines were read +ret = 0; sol = 15 +vertex 1: weight = 3, flag = 0 +vertex 2: weight = 4, flag = 1 +vertex 3: weight = 8, flag = 1 +vertex 4: weight = 1, flag = 0 +vertex 5: weight = 5, flag = 0 +vertex 6: weight = 2, flag = 1 +vertex 7: weight = 1, flag = 1 +vertex 8: weight = 3, flag = 0 +\end{verbatim} +\end{footnotesize} + +\end{document} diff --git a/resources/3rdparty/glpk-4.53/doc/miplib2.txt b/resources/3rdparty/glpk-4.53/doc/miplib2.txt new file mode 100644 index 000000000..762c83f89 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/miplib2.txt @@ -0,0 +1,135 @@ +Solver: GLPSOL 4.40 (options used: --pcost) +Computer: Intel Pentium 4, 3.0 GHz +Platform: Cygwin 1.5.25 +Compiler: GCC 3.4.4 (options used: -O3) +Test set: MIPLIB 2.0 <http://miplib.zib.de/miplib3/miplib/> + +Problem Optimal Solution Cuts Used Nodes Iters Time,s Mem,MB +-------- ---------------- --------- -------- ------ ------ ------ +air01 +6.796000000e+03 3 41 < 1 1.2 +air02 +7.810000000e+03 43 201 6 13.8 +air03 +3.401600000e+05 33 414 12 21.0 +air04 +5.613700000e+04 1901 109800 396 32.4 +air05 +2.637400000e+04 6445 201649 452 45.0 +air06 +4.964900000e+04 11 6868 31 18.1 +bell3a +8.784303160e+05 --gomory 7965 42363 17 6.1 +bell3b +1.178616062e+07 --gomory 6031 30467 19 3.2 +bell4 +1.854148420e+07 --gomory 7203 25019 16 2.9 +bell5 +8.966406492e+06 --gomory 5605 18555 8 1.5 +bm23 +3.400000000e+01 373 878 < 1 0.2 +cracpb1 +2.219900000e+04 47 5258 2 1.3 +dcmulti +1.881820000e+05 743 3366 2 1.1 +diamond infeasible 3 4 < 1 0.1 +dsbmip -3.051981750e+02 --mir 217 46088 24 4.5 +egout +5.681007000e+02 91 137 < 1 0.3 +enigma +0.000000000e+00 16419 55071 6 3.2 +fixnet3 +5.197300000e+04 81 380 < 1 1.4 +fixnet4 +8.936000000e+03 211 1095 1 1.4 +fixnet6 +3.983000000e+03 1031 3136 2 1.7 +flugpl +1.201500000e+06 397 231 < 1 0.1 +gen +1.123133627e+05 195 3991 1 1.7 +khb05250 +1.069402260e+08 2163 14498 5 2.8 +l152lav +4.722000000e+03 7419 95299 68 12.0 +lp4l +2.967000000e+03 173 1331 2 1.7 +lseu +1.120000000e+03 10821 31954 5 2.5 +misc01 +5.635000000e+02 769 4593 1 0.5 +misc02 +1.690000000e+03 29 282 < 1 0.2 +misc03 +3.360000000e+03 957 6742 2 1.1 +misc04 +2.666699247e+03 17 2052 1 7.0 +misc05 +2.984500000e+03 293 2520 1 1.1 +misc06 +1.285086074e+04 57 941 < 1 2.7 +misc07 +2.810000000e+03 --mir 66075 579129 424 33.4 +mod008 +3.070000000e+02 8185 24245 8 2.3 +mod010 +6.548000000e+03 315 6283 7 5.3 +mod011 +mod013 +2.809500000e+02 545 1155 < 1 0.3 +modglob +2.074050809e+07 --mir 5197 31985 20 2.8 +noswot +p0033 +3.089000000e+03 305 955 < 1 0.2 +p0040 +6.202700000e+04 17 66 < 1 0.1 +p0201 +7.615000000e+03 521 3660 1 0.9 +p0282 +2.584110000e+05 623 1204 1 0.8 +p0291 +5.223749000e+03 71 154 < 1 0.7 +p0548 +8.691000000e+03 7617 23556 9 2.9 +p2756 +3.124000000e+03 --mir 3911 15157 57 10.9 +p6000 -2.451377000e+06 19209 40906 570 15.8 +pipex +7.882630000e+02 1569 2469 < 1 0.4 +qiu -1.328731369e+02 80473 1918742 1174 69.2 +rentacar +3.035676098e+07 43 1649 3 12.1 +rgn +8.219999924e+01 3325 18700 2 1.2 +sample2 +3.750000000e+02 163 347 < 1 0.2 +sentoy -7.772000000e+03 335 723 < 1 0.4 +set1al +1.586975000e+04 --mir 17 532 < 1 1.5 +set1ch +set1cl +6.484250000e+03 --mir 1 502 < 1 1.1 +stein15 +9.000000000e+00 87 375 < 1 0.2 +stein27 +1.800000000e+01 3255 15327 2 1.0 +stein45 +3.000000000e+01 52301 389140 139 19.2 +stein9 +5.000000000e+00 17 45 < 1 0.1 +vpm1 +2.000000000e+01 --mir 9 836 < 1 0.9 + +PROBLEM CHARACTERISTICS + +Problem Rows Cols ( Int 0/1) Nonz Best Solution +-------- ------ ---------------------- ------ -------------------------- +air01 24 771 ( all all) 4986 6796 (opt) +air02 51 6774 ( all all) 68329 7810 (opt) +air03 125 10757 ( all all) 101785 340160 (opt) +air04 824 8904 ( all all) 81869 56138 (opt) +air05 427 7195 ( all all) 59316 26402 (not opt) +air06 826 8627 ( all all) 79433 49649 (opt) +bell3a 124 133 ( 71 39) 441 878430.32 (opt) +bell3b 124 133 ( 71 39) 441 11786160.62 (opt) +bell4 106 117 ( 64 34) 385 18541484.20 (opt) +bell5 92 104 ( 58 30) 340 8966406.49 (opt) +bm23 21 27 ( all all) 505 34 (opt) +cracpb1 144 572 ( all all) 4730 22199 (opt) +dcmulti 291 548 ( 75 all) 1833 188182.0000 (opt) +diamond 5 2 ( all all) 9 integer infeasible +dsbmip 1855 1886 ( 192 160) 9768 -305.198 (opt) +egout 99 141 ( 55 all) 392 568.101 (opt) +enigma 22 100 ( all all) 298 0.0 (opt) +fixnet3 479 878 ( 378 all) 2631 51973 (opt) +fixnet4 479 878 ( 378 all) 2621 8936 (opt) +fixnet6 479 878 ( 378 all) 2550 3983 (opt) +flugpl 19 18 ( 11 none) 64 1201500 (opt) +gen 781 870 ( 150 144) 3174 112313 (opt) +khb05250 102 1350 ( 24 all) 3973 106940226 (opt) +l152lav 98 1989 ( all all) 11911 4750 (not opt) +lp4l 86 1086 ( all all) 5763 2967 (opt) +lseu 29 89 ( all all) 394 1120 (opt) +misc01 55 83 ( 82 all) 746 563.5 (opt) +misc02 40 59 ( 58 all) 414 1690 (opt) +misc03 97 160 ( 159 all) 2054 3360 (opt) +misc04 1726 4897 ( 30 all) 17253 2666.699 (opt) +misc05 301 136 ( 74 all) 2946 2984.5 (opt) +misc06 821 1808 ( 112 all) 5860 12850.8607 (opt) +misc07 213 260 ( 259 all) 8620 2810 (not opt) +mod008 7 319 ( all all) 1562 307 (opt) +mod010 147 2655 ( all all) 13858 6548 (opt) +mod011 4482 10958 ( 96 all) 37425 -54558535 (opt) +mod013 63 96 ( 48 all) 288 280.95 (opt) +modglob 292 422 ( 98 all) 1390 20740508 (opt) +noswot 183 128 ( 100 75) 760 -43 (opt) +p0033 17 33 ( all all) 131 3089 (opt) +p0040 24 40 ( all all) 150 62027 (opt) +p0201 134 201 ( all all) 2124 7615 (opt) +p0282 242 282 ( all all) 2248 258411 (opt) +p0291 253 291 ( all all) 349 5223.7490 (opt) +p0548 177 548 ( all all) 2127 8691 (opt) +p2756 756 2756 ( all all) 11103 3124 (opt) +p6000 2177 6000 ( all all) 54238 -2451377 (opt) +pipex 26 48 ( all all) 240 788.263 (opt) +qiu 1193 840 ( 48 all) 3432 -132.873137 (opt) +rentacar 6804 9557 ( 55 all) 42019 30356761 (opt) +rgn 25 180 ( 100 all) 540 82.1999 (opt) +sample2 46 67 ( 21 all) 179 375 (opt) +sentoy 31 60 ( all all) 1860 -7772 (opt) +set1al 493 712 ( 240 all) 1884 15869.7 (opt) +set1ch 493 712 ( 240 all) 1884 54537.7 (opt) +set1cl 493 712 ( 240 all) 1884 6484.25 (opt) +stein15 37 15 ( all all) 135 9 (opt) +stein27 119 27 ( all all) 405 18 (opt) +stein45 332 45 ( all all) 1079 30 (opt) +stein9 14 9 ( all all) 54 5 (opt) +vpm1 235 378 ( 168 all) 917 20 (opt) diff --git a/resources/3rdparty/glpk-4.53/doc/miplib3.txt b/resources/3rdparty/glpk-4.53/doc/miplib3.txt new file mode 100644 index 000000000..ad7884bb2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/miplib3.txt @@ -0,0 +1,143 @@ +Solver: GLPSOL 4.40 +Computer: Intel Pentium 4, 3.0 GHz +Platform: Cygwin 1.5.25 +Compiler: GCC 3.4.4 (options used: -O3) +Test set: MIPLIB 3.0 <http://miplib.zib.de/miplib3/miplib.html> + +Problem Optimal Solution Options Used Nodes Iters Time,s Mem,MB +-------- ---------------- ---------------- -------- ------ ------ ------ +10teams +9.240000000e+02 --pcost --gomory 6013 349276 207 12.7 +air03 +3.401600000e+05 --pcost 33 414 12 21.0 +air04 +5.613700000e+04 --pcost 1901 109800 396 32.4 +air05 +2.637400000e+04 --pcost 6445 201649 452 45.0 +arki001 +bell3a +8.784303160e+05 --pcost --gomory 7965 42363 17 6.1 +bell5 +8.966406492e+06 --pcost --gomory 5605 18555 8 1.5 +blend2 +7.598985000e+00 --pcost 7185 24256 7 2.1 +cap6000 -2.451377000e+06 --pcost 19209 40906 569 15.8 +dano3mip +danoint +dcmulti +1.881820000e+05 --pcost 743 3366 2 1.1 +dsbmip -3.051981750e+02 --pcost --mir 217 46088 24 4.5 +egout +5.681007000e+02 --pcost 91 137 < 1 0.3 +enigma +0.000000000e+00 --pcost 16419 55071 6 3.2 +fast0507 +fiber +4.059351800e+05 --pcost --mir 407 3108 4 2.4 +fixnet6 +3.983000000e+03 --pcost 1031 3136 2 1.7 +flugpl +1.201500000e+06 --pcost 397 231 < 1 0.1 +gen +1.123133627e+05 --pcost 195 3991 1 1.7 +gesa2 +2.577985637e+07 --pcost --mir 59 2723 4 4.1 +gesa2_o +2.577985637e+07 --pcost --mir 69 2588 5 3.7 +gesa3 +2.799104265e+07 --pcost --mir 93 2774 5 3.7 +gesa3_o +2.799104265e+07 --pcost --mir 117 3271 6 3.6 +gt2 +2.116600000e+04 --pcost 5613 26115 2 1.2 +harp2 +khb05250 +1.069402260e+08 --pcost 2163 14498 5 2.8 +l152lav +4.722000000e+03 --pcost 7419 95299 68 12.0 +lseu +1.120000000e+03 --pcost 10821 31954 5 2.5 +marksh1 +marksh2 +mas74 +mas76 +misc03 +3.360000000e+03 --pcost 957 6742 2 1.1 +misc06 +1.285086074e+04 --pcost 57 941 < 1 2.7 +misc07 +2.810000000e+03 --pcost --mir 66075 579129 424 33.4 +mitre +mkc +mod008 +3.070000000e+02 --pcost 8185 24245 8 2.3 +mod010 +6.548000000e+03 --pcost 315 6283 7 5.3 +mod011 +modglob +2.074050809e+07 --pcost --mir 5197 31985 20 2.8 +noswot +nw04 +1.686200000e+04 (none) 361 5544 345 138.3 +p0033 +3.089000000e+03 --pcost 305 955 < 1 0.2 +p0201 +7.615000000e+03 --pcost 521 3660 1 0.9 +p0282 +2.584110000e+05 --pcost 623 1204 1 0.8 +p0548 +8.691000000e+03 --pcost 7617 23556 9 2.9 +p2756 +3.124000000e+03 --pcost --mir 3911 15157 57 10.9 +pk1 +pp08a +7.350000000e+03 --pcost --mir 663 9196 4 1.3 +pp08acut +7.350000000e+03 --pcost --mir 17233 260160 154 21.1 +qiu -1.328731369e+02 --pcost 80473 1918742 1174 69.2 +qnet1 +1.602969268e+04 --pcost --mir 183 20352 16 3.6 +qnet1_o +1.602969268e+04 --pcost --mir 75 7645 9 3.3 +rentacar +3.035676098e+07 --pcost 43 1649 3 12.1 +rgn +8.219999924e+01 --pcost 3325 18700 2 1.2 +rout +set1ch +seymour +stein27 +1.800000000e+01 --pcost 3255 15327 2 1.0 +stein45 +3.000000000e+01 --pcost 52301 389140 139 19.2 +swath +vpm1 +2.000000000e+01 --pcost --mir 9 836 < 1 0.9 +vpm2 +1.375000000e+01 --pcost --mir 11729 164856 91 9.2 + +PROBLEM CHARACTERISTICS + +Problem Rows Cols ( Int 0/1) Nonz Best Solution +-------- ------ ---------------------- ------ -------------------------- +10teams 230 2025 ( 1800 all) 12150 924 (opt) +air03 125 10757 ( all all) 101785 340160 (opt) +air04 824 8904 ( all all) 81869 56138 (opt) +air05 427 7195 ( all all) 59316 26402 (not opt) +arki001 1048 1388 ( 538 415) 20439 7580813.0459 (not opt) +bell3a 124 133 ( 71 39) 441 878430.32 (opt) +bell5 92 104 ( 58 30) 340 8966406.49 (opt) +blend2 274 353 ( 264 231) 1409 7.598985 (opt) +cap6000 2176 6000 ( all all) 48249 -2451377 (opt) +dano3mip 3202 13873 ( 552 all) 79655 728.1111 (not opt) +danoint 664 521 ( 56 all) 3232 65.67 (opt) +dcmulti 291 548 ( 75 all) 1833 188182.0000 (opt) +dsbmip 1855 1886 ( 192 160) 9768 -305.198 (opt) +egout 99 141 ( 55 all) 392 568.101 (opt) +enigma 22 100 ( all all) 298 0.0 (opt) +fast0507 507 63009 ( all all) 409439 174 (opt) +fiber 363 1298 ( 1254 all) 2944 405935.18000 (opt) +fixnet6 479 878 ( 378 all) 2550 3983 (opt) +flugpl 19 18 ( 11 none) 64 1201500 (opt) +gen 781 870 ( 150 144) 3174 112313 (opt) +gesa2 1392 1224 ( 408 240) 5064 25779856.372 (opt) +gesa2_o 1248 1224 ( 720 384) 3672 25779856.372 (opt) +gesa3 1368 1152 ( 384 216) 4944 27991042.648 (opt) +gesa3_o 1224 1152 ( 672 336) 3624 27991042.648 (opt) +gt2 29 188 ( all 24) 376 21166.000 (opt) +harp2 112 2993 ( all all) 5840 -73899798.00 (opt) +khb05250 102 1350 ( 24 all) 3973 106940226 (opt) +l152lav 98 1989 ( all all) 11911 4750 (not opt) +lseu 29 89 ( all all) 394 1120 (opt) +marksh1 7 62 ( 50 all) 324 +marksh2 8 74 ( 60 all) 448 +mas74 13 151 ( 150 all) 1705 11801.1857 (opt) +mas76 12 151 ( 150 all) 1639 40005.0541 (opt) +misc03 97 160 ( 159 all) 2054 3360 (opt) +misc06 821 1808 ( 112 all) 5860 12850.8607 (opt) +misc07 213 260 ( 259 all) 8620 2810 (not opt) +mitre 2054 10724 ( all all) 39704 115155 (opt) +mkc 3412 5325 ( 5323 all) 20621 +mod008 7 319 ( all all) 1562 307 (opt) +mod010 147 2655 ( all all) 13858 6548 (opt) +mod011 4482 10958 ( 96 all) 37425 -54558535 (opt) +modglob 292 422 ( 98 all) 1390 20740508 (opt) +noswot 183 128 ( 100 75) 760 -43 (opt) +nw04 36 87482 ( all all) 636666 16862 (opt) +p0033 17 33 ( all all) 131 3089 (opt) +p0201 134 201 ( all all) 2124 7615 (opt) +p0282 242 282 ( all all) 2248 258411 (opt) +p0548 177 548 ( all all) 2127 8691 (opt) +p2756 756 2756 ( all all) 11103 3124 (opt) +pk1 45 86 ( 55 all) 915 11 (opt) +pp08a 136 240 ( 64 all) 480 7350 (opt) +pp08acut 246 240 ( 64 all) 839 7350 (opt) +qiu 1193 840 ( 48 all) 3432 -132.873137 (opt) +qnet1 503 1541 ( 1417 1288) 4622 16029.692681 (opt) +qnet1_o 456 1541 ( 1417 1288) 4214 16029.692681 (opt) +rentacar 6804 9557 ( 55 all) 42019 30356761 (opt) +rgn 25 180 ( 100 all) 540 82.1999 (opt) +rout 291 556 ( 315 300) 2431 1077.56 (opt) +set1ch 493 712 ( 240 all) 1884 54537.7 (opt) +seymour 4944 1372 ( all all) 33549 423 (not opt) +stein27 119 27 ( all all) 405 18 (opt) +stein45 332 45 ( all all) 1079 30 (opt) +swath 885 6805 ( 6724 all) 34966 +vpm1 235 378 ( 168 all) 917 20 (opt) +vpm2 234 378 ( 168 all) 917 13.75 (opt) diff --git a/resources/3rdparty/glpk-4.53/doc/netlib.txt b/resources/3rdparty/glpk-4.53/doc/netlib.txt new file mode 100644 index 000000000..a5c01ca80 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/doc/netlib.txt @@ -0,0 +1,103 @@ +Solver: GLPSOL 4.40 (default options used) +Computer: Intel Pentium 4, 3.0 GHz +Platform: Cygwin 1.5.25 +Compiler: GCC 3.4.4 (options used: -O3) +Test set: Netlib LP collection <ftp://ftp.netlib.org/lp/data/> + +Problem Rows Cols Nonz Optimum Iters Time,s Mem,MB +-------- ----- ----- ------ ---------------- ------ ------ ------ +25fv47 822 1571 11127 +5.501845888e+03 1651 < 1 2.1 +80bau3b 2263 9799 29063 +9.872241924e+05 5358 3 6.4 +adlittle 57 97 465 +2.254949632e+05 71 < 1 0.1 +afiro 28 32 88 -4.647531429e+02 10 < 1 0.1 +agg 489 163 2541 -3.599176729e+07 100 < 1 0.5 +agg2 517 302 4515 -2.023925236e+07 178 < 1 0.8 +agg3 517 302 4531 +1.031211594e+07 182 < 1 0.8 +bandm 306 472 2659 -1.586280185e+02 252 < 1 0.6 +beaconfd 174 262 3476 +3.359248581e+04 61 < 1 0.4 +blend 75 83 521 -3.081214985e+01 41 < 1 0.1 +bnl1 644 1175 6129 +1.977629562e+03 581 < 1 1.4 +bnl2 2325 3489 16124 +1.811236540e+03 1730 1 3.7 +boeing1 351 384 3865 -3.352135675e+02 419 < 1 0.7 +boeing2 167 143 1339 -3.150187280e+02 161 < 1 0.3 +bore3d 234 315 1525 +1.373080394e+03 38 < 1 0.3 +brandy 221 249 2150 +1.518509896e+03 191 < 1 0.5 +capri 272 353 1786 +2.690012914e+03 203 < 1 0.4 +cycle 1904 2857 21322 -5.226393025e+00 953 < 1 3.5 +czprob 930 3523 14173 +2.185196699e+06 754 < 1 2.6 +d2q06c 2172 5167 35674 +1.227842108e+05 5368 7 6.2 +d6cube 416 6184 43888 +3.154916667e+02 6596 6 6.0 +degen2 445 534 4449 -1.435178000e+03 506 < 1 1.0 +degen3 1504 1818 26230 -9.872940000e+02 2205 2 4.1 +dfl001 6072 12230 41873 +1.126639605e+07 39863 117 11.0 +e226 224 282 2767 -2.586492907e+01 206 < 1 0.5 +etamacro 401 688 2489 -7.557152333e+02 444 < 1 0.7 +fffff800 525 854 6235 +5.556795648e+05 167 < 1 1.0 +finnis 498 614 2714 +1.727910656e+05 338 < 1 0.6 +fit1d 25 1026 14430 -9.146378092e+03 488 < 1 1.7 +fit1p 628 1677 10894 +9.146378092e+03 1379 < 1 1.9 +fit2d 26 10500 138018 -6.846429329e+04 5751 16 15.8 +fit2p 3001 13525 60784 +6.846429329e+04 11960 17 11.3 +forplan 162 421 4916 -6.642189613e+02 170 < 1 0.7 +ganges 1310 1681 7021 -1.095857361e+05 724 < 1 1.9 +gfrd-pnc 617 1092 3467 +6.902236000e+06 416 < 1 1.0 +greenbea 2393 5405 31499 -7.255524813e+07 3012 3 5.8 +greenbeb 2393 5405 31499 -4.302260261e+06 2153 2 5.8 +grow15 301 645 5665 -1.068709413e+08 358 < 1 1.1 +grow22 441 946 8318 -1.608343365e+08 606 < 1 1.6 +grow7 141 301 2633 -4.778781181e+07 159 < 1 0.5 +israel 175 142 2358 -8.966448219e+05 123 < 1 0.4 +kb2 44 41 291 -1.749900130e+03 38 < 1 0.1 +lotfi 154 308 1086 -2.526470606e+01 104 < 1 0.3 +maros 847 1443 10006 -5.806374370e+04 703 < 1 1.8 +maros-r7 3137 9408 151120 +1.497185166e+06 2340 5 16.7 +modszk1 688 1620 4158 +3.206197291e+02 705 < 1 1.4 +nesm 663 2923 13988 +1.407603649e+07 2240 1 2.4 +perold 626 1376 6026 -9.380755278e+03 1103 < 1 1.5 +pilot 1442 3652 43220 -5.574831533e+02 5726 11 7.8 +pilot-ja 941 1988 14706 -6.113136466e+03 1697 1 2.5 +pilot-we 723 2789 9218 -2.720107533e+06 1382 1 2.3 +pilot4 411 1000 5145 -2.581139259e+03 532 < 1 1.3 +pilot87 2031 4883 73804 +3.017103744e+02 7573 28 12.2 +pilotnov 976 2172 13129 -4.497276188e+03 988 1 2.5 +recipe 92 180 752 -2.666160000e+02 17 < 1 0.2 +sc105 106 103 281 -5.220206121e+01 51 < 1 0.2 +sc205 206 203 552 -5.220206121e+01 124 < 1 0.3 +sc50a 51 48 131 -6.457507706e+01 25 < 1 0.1 +sc50b 51 48 119 -7.000000000e+01 30 < 1 0.1 +scagr25 472 500 2029 -1.475343306e+07 352 < 1 0.7 +scagr7 130 140 553 -2.331389824e+06 94 < 1 0.2 +scfxm1 331 457 2612 +1.841675903e+04 281 < 1 0.6 +scfxm2 661 914 5229 +3.666026156e+04 587 < 1 1.1 +scfxm3 991 1371 7846 +5.490125455e+04 881 < 1 1.7 +scorpion 389 358 1708 +1.878124823e+03 146 < 1 0.4 +scrs8 491 1169 4029 +9.042969538e+02 545 < 1 1.1 +scsd1 78 760 3148 +8.666666674e+00 91 < 1 0.6 +scsd6 148 1350 5666 +5.050000008e+01 182 < 1 1.0 +scsd8 398 2750 11334 +9.049999999e+02 397 < 1 2.1 +sctap1 301 480 2052 +1.412250000e+03 196 < 1 0.5 +sctap2 1091 1880 8124 +1.724807143e+03 425 < 1 1.7 +sctap3 1481 2480 10734 +1.424000000e+03 729 < 1 2.4 +seba 516 1028 4874 +1.571160000e+04 883 < 1 1.0 +share1b 118 225 1182 -7.658931858e+04 167 < 1 0.3 +share2b 97 79 730 -4.157322407e+02 87 < 1 0.2 +shell 537 1775 4900 +1.208825346e+09 467 < 1 1.2 +ship04l 403 2118 8450 +1.793324538e+06 373 < 1 1.5 +ship04s 403 1458 5810 +1.798714700e+06 262 < 1 1.0 +ship08l 779 4283 17085 +1.909055211e+06 516 < 1 2.9 +ship08s 779 2387 9501 +1.920098211e+06 274 < 1 1.7 +ship12l 1152 5427 21597 +1.470187919e+06 686 < 1 3.7 +ship12s 1152 2763 10941 +1.489236134e+06 383 < 1 2.0 +sierra 1228 2036 9252 +1.539436218e+07 857 < 1 2.1 +stair 357 467 3857 -2.512669512e+02 399 < 1 1.0 +standata 360 1075 3038 +1.257699500e+03 140 < 1 0.7 +standgub 362 1184 3147 +1.257699500e+03 140 < 1 0.8 +standmps 468 1075 3686 +1.406017500e+03 299 < 1 0.9 +stocfor1 118 111 474 -4.113197622e+04 24 < 1 0.2 +stocfor2 2158 2031 9492 -3.902440854e+04 499 < 1 2.6 +stocfor3 16676 15695 74004 -3.997678394e+04 4456 11 19.7 +truss 1001 8806 36642 +4.588158472e+05 4744 4 6.5 +tuff 334 587 4523 +2.921477651e-01 61 < 1 0.8 +vtp-base 199 203 914 +1.298314625e+05 69 < 1 0.2 +wood1p 245 2594 70216 +1.442902412e+00 326 < 1 7.1 +woodw 1099 8405 37478 +1.304476333e+00 1093 < 1 6.0 diff --git a/resources/3rdparty/glpk-4.53/doc/notes/dfeas.pdf b/resources/3rdparty/glpk-4.53/doc/notes/dfeas.pdf new file mode 100644 index 0000000000000000000000000000000000000000..35f5d3aa5c71ec885b00186fc93c3c608bc6b9d0 GIT binary patch literal 63866 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
yqd`_rqNMRy$F%Bm7KA4@q-Z>o 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 literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/doc/notes/gomory.pdf b/resources/3rdparty/glpk-4.53/doc/notes/gomory.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b680627044bb8cb84e313d6299b50ded1ae1ade5 GIT binary patch literal 75445 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 Yc|v_X!FIT!LSkZ~xNL07+A6sJ3*O;Z_W%F@ literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/doc/notes/keller.pdf b/resources/3rdparty/glpk-4.53/doc/notes/keller.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3aa69388b23722a2de031d594cec1fca03cc68f7 GIT binary patch literal 85985 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�)t%lZ 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 literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/doc/notes/scaling.pdf b/resources/3rdparty/glpk-4.53/doc/notes/scaling.pdf new file mode 100644 index 0000000000000000000000000000000000000000..732f614db5924bfca19b6a9bc2b0c95f79f83c2d GIT binary patch literal 42382 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 literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/doc/notes/updating.pdf b/resources/3rdparty/glpk-4.53/doc/notes/updating.pdf new file mode 100644 index 0000000000000000000000000000000000000000..65b0966aaf08b0fd4f0bc298062d86b82527cda7 GIT binary patch literal 41817 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 literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/examples/INDEX b/resources/3rdparty/glpk-4.53/examples/INDEX new file mode 100644 index 000000000..9647c7bc8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/INDEX @@ -0,0 +1,52 @@ +assign.mod Assignment problem +bpp.mod Bin packing problem +cal.mod Print an ASCII calendar of the given year +cf12a.mod Curve fitting problem +cf12b.mod Curve fitting problem +cflsq.mod Curve fitting problem by least squares +color.mod Graph coloring problem +cpp.mod Critical path problem +crypto.mod A crypto-arithmetic puzzle +dea.mod Data envelopment analysis (DEA) +diet.mod Stigler's nutrition model +dist.mod A product distribution model +egypt.mod A static model for fertilizer production +fctp.mod Fixed-charge transportation problem +food.mod Food manufacture model +food2.mod Food manufacture model +gap.mod Generalized assignment problem +graph.mod Graph visualization +hashi.mod A solver for the Japanese number-puzzle Hashiwokakero +huge.mod Arithmetic mean of a large number of integers +jssp.mod Job-shop scheduling problem +magic.mod Magic square +maxcut.mod Maximum cut problem +maxflow.mod Maximum flow problem +mfasp.mod Minimum feedback arc set problem +mfvsp.mod Minimum feedback vertex set problem +min01ks.mod Finding minimal equivalent 0-1 knapsack inequality +misp.mod Maximum independent set problem +money.mod A crypto-arithmetic puzzle +mvcp.mod Minimum vertex cover problem +numbrix.mod Number placement puzzle +pbn/*.* Paint-by-numbers puzzle +plan.mod A simple LP problem +prod.mod A multiperiod production model +qfit.mod Quadratic curve fitting solution +queens.mod A classic combinatorial optimization problem +sat.mod Satisfiability problem +shiftcover.mod Workforce shift coverage assignment problem +shikaku.mod A solver for the logic puzzle Shikaku +sorting.mod How to sort arrays in MathProg +spp.mod Shortest path problem +stigler.mod Original Stigler's 1939 diet problem +sudoku.mod Number placement puzzle +tas.mod Tail assignment problem +todd.mod A class of hard instances of 0-1 knapsack problems +train.mod A model of railroad passenger car allocation +transp.mod A transportation problem +trick.mod A transportation design problem +tsp.mod Traveling salesman problem +xyacfs.mod Extended yet another curve fitting solution +yacfs.mod Yet another curve fitting solution +zebra.mod Who owns the zebra? diff --git a/resources/3rdparty/glpk-4.53/examples/Makefile.am b/resources/3rdparty/glpk-4.53/examples/Makefile.am new file mode 100644 index 000000000..04b6a47cf --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/Makefile.am @@ -0,0 +1,15 @@ +## Process this file with automake to produce Makefile.in ## + +AM_CPPFLAGS = -I$(srcdir)/../src + +LDADD = ../src/libglpk.la + +bin_PROGRAMS = glpsol + +glpsol_SOURCES = glpsol.c + +check: glpsol$(EXEEXT) + ./glpsol$(EXEEXT) --version + ./glpsol$(EXEEXT) --mps $(srcdir)/plan.mps + +## eof ## diff --git a/resources/3rdparty/glpk-4.53/examples/Makefile.in b/resources/3rdparty/glpk-4.53/examples/Makefile.in new file mode 100644 index 000000000..9a9c0dca2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/Makefile.in @@ -0,0 +1,558 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 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@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = glpsol$(EXEEXT) +subdir = examples +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_glpsol_OBJECTS = glpsol.$(OBJEXT) +glpsol_OBJECTS = $(am_glpsol_OBJECTS) +glpsol_LDADD = $(LDADD) +glpsol_DEPENDENCIES = ../src/libglpk.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(glpsol_SOURCES) +DIST_SOURCES = $(glpsol_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +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@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -I$(srcdir)/../src +LDADD = ../src/libglpk.la +glpsol_SOURCES = glpsol.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu examples/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: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +glpsol$(EXEEXT): $(glpsol_OBJECTS) $(glpsol_DEPENDENCIES) $(EXTRA_glpsol_DEPENDENCIES) + @rm -f glpsol$(EXEEXT) + $(LINK) $(glpsol_OBJECTS) $(glpsol_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glpsol.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +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)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +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 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am 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 + + +check: glpsol$(EXEEXT) + ./glpsol$(EXEEXT) --version + ./glpsol$(EXEEXT) --mps $(srcdir)/plan.mps + +# 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: diff --git a/resources/3rdparty/glpk-4.53/examples/assign.mod b/resources/3rdparty/glpk-4.53/examples/assign.mod new file mode 100644 index 000000000..6f700bb16 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/assign.mod @@ -0,0 +1,77 @@ +/* ASSIGN, Assignment Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The assignment problem is one of the fundamental combinatorial + optimization problems. + + In its most general form, the problem is as follows: + + There are a number of agents and a number of tasks. Any agent can be + assigned to perform any task, incurring some cost that may vary + depending on the agent-task assignment. It is required to perform all + tasks by assigning exactly one agent to each task in such a way that + the total cost of the assignment is minimized. + + (From Wikipedia, the free encyclopedia.) */ + +param m, integer, > 0; +/* number of agents */ + +param n, integer, > 0; +/* number of tasks */ + +set I := 1..m; +/* set of agents */ + +set J := 1..n; +/* set of tasks */ + +param c{i in I, j in J}, >= 0; +/* cost of allocating task j to agent i */ + +var x{i in I, j in J}, >= 0; +/* x[i,j] = 1 means task j is assigned to agent i + note that variables x[i,j] are binary, however, there is no need to + declare them so due to the totally unimodular constraint matrix */ + +s.t. phi{i in I}: sum{j in J} x[i,j] <= 1; +/* each agent can perform at most one task */ + +s.t. psi{j in J}: sum{i in I} x[i,j] = 1; +/* each task must be assigned exactly to one agent */ + +minimize obj: sum{i in I, j in J} c[i,j] * x[i,j]; +/* the objective is to find a cheapest assignment */ + +solve; + +printf "\n"; +printf "Agent Task Cost\n"; +printf{i in I} "%5d %5d %10g\n", i, sum{j in J} j * x[i,j], + sum{j in J} c[i,j] * x[i,j]; +printf "----------------------\n"; +printf " Total: %10g\n", sum{i in I, j in J} c[i,j] * x[i,j]; +printf "\n"; + +data; + +/* These data correspond to an example from [Christofides]. */ + +/* Optimal solution is 76 */ + +param m := 8; + +param n := 8; + +param c : 1 2 3 4 5 6 7 8 := + 1 13 21 20 12 8 26 22 11 + 2 12 36 25 41 40 11 4 8 + 3 35 32 13 36 26 21 13 37 + 4 34 54 7 8 12 22 11 40 + 5 21 6 45 18 24 34 12 48 + 6 42 19 39 15 14 16 28 46 + 7 16 34 38 3 34 40 22 24 + 8 26 20 5 17 45 31 37 43 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/bpp.mod b/resources/3rdparty/glpk-4.53/examples/bpp.mod new file mode 100644 index 000000000..8dd354ed8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/bpp.mod @@ -0,0 +1,83 @@ +/* BPP, Bin Packing Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* Given a set of items I = {1,...,m} with weight w[i] > 0, the Bin + Packing Problem (BPP) is to pack the items into bins of capacity c + in such a way that the number of bins used is minimal. */ + +param m, integer, > 0; +/* number of items */ + +set I := 1..m; +/* set of items */ + +param w{i in 1..m}, > 0; +/* w[i] is weight of item i */ + +param c, > 0; +/* bin capacity */ + +/* We need to estimate an upper bound of the number of bins sufficient + to contain all items. The number of items m can be used, however, it + is not a good idea. To obtain a more suitable estimation an easy + heuristic is used: we put items into a bin while it is possible, and + if the bin is full, we use another bin. The number of bins used in + this way gives us a more appropriate estimation. */ + +param z{i in I, j in 1..m} := +/* z[i,j] = 1 if item i is in bin j, otherwise z[i,j] = 0 */ + + if i = 1 and j = 1 then 1 + /* put item 1 into bin 1 */ + + else if exists{jj in 1..j-1} z[i,jj] then 0 + /* if item i is already in some bin, do not put it into bin j */ + + else if sum{ii in 1..i-1} w[ii] * z[ii,j] + w[i] > c then 0 + /* if item i does not fit into bin j, do not put it into bin j */ + + else 1; + /* otherwise put item i into bin j */ + +check{i in I}: sum{j in 1..m} z[i,j] = 1; +/* each item must be exactly in one bin */ + +check{j in 1..m}: sum{i in I} w[i] * z[i,j] <= c; +/* no bin must be overflowed */ + +param n := sum{j in 1..m} if exists{i in I} z[i,j] then 1; +/* determine the number of bins used by the heuristic; obviously it is + an upper bound of the optimal solution */ + +display n; + +set J := 1..n; +/* set of bins */ + +var x{i in I, j in J}, binary; +/* x[i,j] = 1 means item i is in bin j */ + +var used{j in J}, binary; +/* used[j] = 1 means bin j contains at least one item */ + +s.t. one{i in I}: sum{j in J} x[i,j] = 1; +/* each item must be exactly in one bin */ + +s.t. lim{j in J}: sum{i in I} w[i] * x[i,j] <= c * used[j]; +/* if bin j is used, it must not be overflowed */ + +minimize obj: sum{j in J} used[j]; +/* objective is to minimize the number of bins used */ + +data; + +/* The optimal solution is 3 bins */ + +param m := 6; + +param w := 1 50, 2 60, 3 30, 4 70, 5 50, 6 40; + +param c := 100; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/cal.mod b/resources/3rdparty/glpk-4.53/examples/cal.mod new file mode 100644 index 000000000..2555182e0 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/cal.mod @@ -0,0 +1,49 @@ +/* cal.mod - print an ASCII calendar of the given year */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +param year, integer, >= 0001, <= 3999, default 2010; + +param first_day{m in 1..12}, integer, >= 0, <= 6, := + time2str(str2time(year & "-" & m & "-01", "%Y-%m-%d"), "%w"); + +param days_in_month{m in 1..12}, integer, >= 28, <= 31, := + (str2time(year + (if m < 12 then 0 else 1) & "-" & + (if m < 12 then m+1 else 1) & "-01", "%Y-%m-%d") - + str2time(year & "-" & m & "-01", "%Y-%m-%d")) / 86400; + +param foo{m in 1..12, k in 0..5, d in 0..6}, integer, := + 7 * k + d + 1 - first_day[m]; + +param cal{m in 1..12, k in 0..5, d in 0..6}, integer, := + if 1 <= foo[m,k,d] and foo[m,k,d] <= days_in_month[m] then + foo[m,k,d]; + +printf "\n"; +printf "%33s%04d\n", "", year; +printf "\n"; +for {t in 1..12 by 3} +{ for {m in t..t+2} + { printf "%7s%-14s", "", time2str(str2time(m, "%m"), "%B"); + printf{0..0: m < t+2} " "; + } + printf "\n"; + for {m in t..t+2} + { printf " S M Tu W Th F S"; + printf{0..0: m < t+2} " "; + } + printf "\n"; + for {k in 0..5} + { for {m in t..t+2} + { for {d in 0..6} + { printf{0..0: cal[m,k,d] = 0} " "; + printf{0..0: cal[m,k,d] != 0} " %2d", cal[m,k,d]; + } + printf{0..0: m < t+2} " "; + } + printf "\n"; + } +} +printf "\n"; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/cf12a.mod b/resources/3rdparty/glpk-4.53/examples/cf12a.mod new file mode 100644 index 000000000..61a76c050 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/cf12a.mod @@ -0,0 +1,81 @@ +/* + + Curve fitting problem 12.11(a) H P Williams "Model Building in Mathematical Programming" + + Dr. H J Mackenzie + HARD software + hjm@hardsoftware.com + + 2006-01-05 + + */ + +# set of points + +set I; + +# independent variable + +param x {i in I}; + +# dependent variable + +param y {i in I}; + +# output input values + +printf {i in I} "x = %.1f; y = %.1f\n", x[i], y[i]; + +# define equation variables + +var a; + +var b; + +var u {i in I}, >= 0; + +var v {i in I}, >= 0; + +# define objective function + +minimize error: sum {i in I} u[i] + sum {i in I} v[i]; + +# define equation constraint + +s.t. equation {i in I} : b * x[i] + a + u[i] - v[i] = y[i]; + +solve; + +printf "y = %.4fx + %.4f\n", b, a; + +/* + * + * DATA section + * + */ + +data; + +param : I : x y := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/cf12b.mod b/resources/3rdparty/glpk-4.53/examples/cf12b.mod new file mode 100644 index 000000000..56f1ba106 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/cf12b.mod @@ -0,0 +1,88 @@ +/* + + Curve fitting problem 12.11(b) H P Williams "Model Building in Mathematical Programming" + + Dr. H J Mackenzie + HARD software + hjm@hardsoftware.com + + 2006-01-23 + + */ + +# set of points + +set I; + +# independent variable + +param x {i in I}; + +# dependent variable + +param y {i in I}; + +# output input values + +printf {i in I} "x = %.1f; y = %.1f\n", x[i], y[i]; + +# define equation variables + +var a; + +var b; + +var u {i in I}, >= 0; + +var v {i in I}, >= 0; + +var z; + +# define objective function + +minimize deviation: z; + +# define equation constraint + +s.t. equation {i in I} : b * x[i] + a + u[i] - v[i] = y[i]; + +# define deviation constrains + +s.t. u_deviation {i in I} : z - u[i] >= 0; +s.t. v_deviation {i in I} : z - v[i] >= 0; + +solve; + +printf "y = %.4fx + %.4f Max deviation = %.4f\n", b, a, z; + +/* + * + * DATA section + * + */ + +data; + +param : I : x y := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/cflsq.mod b/resources/3rdparty/glpk-4.53/examples/cflsq.mod new file mode 100644 index 000000000..4af4d029b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/cflsq.mod @@ -0,0 +1,51 @@ +/*Curve fitting problem by Least Squares + Nigel_Galloway@operamail.com + October 1st., 2007 +*/ +set Sample; +param Sx {z in Sample}; +param Sy {z in Sample}; + +var X; +var Y; +var Ex{z in Sample}; +var Ey{z in Sample}; + +/* sum of variances is zero for Sx*/ +variencesX{z in Sample}: X + Ex[z] = Sx[z]; +zumVariancesX: sum{z in Sample} Ex[z] = 0; +/* sum of variances is zero for Sy*/ +variencesY{z in Sample}: Y + Ey[z] = Sy[z]; +zumVariancesY: sum{z in Sample} Ey[z] = 0; + +solve; + +param b1 := (sum{z in Sample} Ex[z]*Ey[z])/(sum{z in Sample} Ex[z]*Ex[z]); +printf "\nbest linear fit is:\n\ty = %f %s %fx\n\n", Y-b1*X, if b1 < 0 then "-" else "+", abs(b1); + +data; + +param: +Sample: Sx Sy := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/color.mod b/resources/3rdparty/glpk-4.53/examples/color.mod new file mode 100644 index 000000000..9a279c387 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/color.mod @@ -0,0 +1,113 @@ +/* COLOR, Graph Coloring Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* Given an undirected loopless graph G = (V, E), where V is a set of + nodes, E <= V x V is a set of arcs, the Graph Coloring Problem is to + find a mapping (coloring) F: V -> C, where C = {1, 2, ... } is a set + of colors whose cardinality is as small as possible, such that + F(i) != F(j) for every arc (i,j) in E, that is adjacent nodes must + be assigned different colors. */ + +param n, integer, >= 2; +/* number of nodes */ + +set V := {1..n}; +/* set of nodes */ + +set E, within V cross V; +/* set of arcs */ + +check{(i,j) in E}: i != j; +/* there must be no loops */ + +/* We need to estimate an upper bound of the number of colors |C|. + The number of nodes |V| can be used, however, for sparse graphs such + bound is not very good. To obtain a more suitable estimation we use + an easy "greedy" heuristic. Let nodes 1, ..., i-1 are already + assigned some colors. To assign a color to node i we see if there is + an existing color not used for coloring nodes adjacent to node i. If + so, we use this color, otherwise we introduce a new color. */ + +set EE := setof{(i,j) in E} (i,j) union setof{(i,j) in E} (j,i); +/* symmetrisized set of arcs */ + +param z{i in V, case in 0..1} := +/* z[i,0] = color index assigned to node i + z[i,1] = maximal color index used for nodes 1, 2, ..., i-1 which are + adjacent to node i */ +( if case = 0 then + ( /* compute z[i,0] */ + min{c in 1..z[i,1]} + ( if not exists{j in V: j < i and (i,j) in EE} z[j,0] = c then + c + else + z[i,1] + 1 + ) + ) + else + ( /* compute z[i,1] */ + if not exists{j in V: j < i} (i,j) in EE then + 1 + else + max{j in V: j < i and (i,j) in EE} z[j,0] + ) +); + +check{(i,j) in E}: z[i,0] != z[j,0]; +/* check that all adjacent nodes are assigned distinct colors */ + +param nc := max{i in V} z[i,0]; +/* number of colors used by the heuristic; obviously, it is an upper + bound of the optimal solution */ + +display nc; + +var x{i in V, c in 1..nc}, binary; +/* x[i,c] = 1 means that node i is assigned color c */ + +var u{c in 1..nc}, binary; +/* u[c] = 1 means that color c is used, i.e. assigned to some node */ + +s.t. map{i in V}: sum{c in 1..nc} x[i,c] = 1; +/* each node must be assigned exactly one color */ + +s.t. arc{(i,j) in E, c in 1..nc}: x[i,c] + x[j,c] <= u[c]; +/* adjacent nodes cannot be assigned the same color */ + +minimize obj: sum{c in 1..nc} u[c]; +/* objective is to minimize the number of colors used */ + +data; + +/* These data correspond to the instance myciel3.col from: + http://mat.gsia.cmu.edu/COLOR/instances.html */ + +/* The optimal solution is 4 */ + +param n := 11; + +set E := + 1 2 + 1 4 + 1 7 + 1 9 + 2 3 + 2 6 + 2 8 + 3 5 + 3 7 + 3 10 + 4 5 + 4 6 + 4 10 + 5 8 + 5 9 + 6 11 + 7 11 + 8 11 + 9 11 + 10 11 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/cplex/README b/resources/3rdparty/glpk-4.53/examples/cplex/README new file mode 100644 index 000000000..38bb8b4d3 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/cplex/README @@ -0,0 +1,44 @@ +The program module in this subdirectory is a crude implementation of +CPLEX-like interface to GLPK API. It consists of two files: cplex.c and +cplex.h. + +NOTE that this module is NOT a clean room implementation of the CPLEX +callable library. It only implements a CPLEX-like interface to the GLPK +API routines, and its main purpose is to provide possibility to build +and run applications which normally use the CPLEX callable library. + +This module approximately corresponds to CPLEX 9.0. + +Currently this module can be used as a linear programming solver for +Concorde, the state-of-the-art computer code for solving the symmetric +traveling salesman problem (TSP) developed by David Applegate, Robert +Bixby, Vasek Chvatal, and William Cook. For details about Concorde see +its web page at http://www.tsp.gatech.edu/concorde.html. + +To build Concorde along with GLPK you need to do the following: + +1. Configure, build, and install GLPK. + +2. Download the Concorde tarball co031219.tgz (version Dec 19, 2003), + unpack and unarchive it. + +3. Copy files cplex.h and cplex.c to subdirectory concorde/LP/. + +4. Create file named lpglpk.c in subdirectory concorde/LP/. This file + must contain the following two lines: + + #include "cplex.c" + #include "lpcplex8.c" + +5. Configure Concorde in usual way (./configure) and then build it with + the following command: + + make CPPFLAGS=-I. LPSOLVER_INTERFACE=lpglpk.c LPSOLVER_LIB=-lglpk + + The Concorde executable can be found in subdirectory concorde/TSP/. + +Please note that currently this GLPK interface module does not support +some important features (namely, CPXgetijdiv, CPXmdleave, CPXpivotin, +CPXpivotout, and CPXstrongbranch), so large (more than 1000 nodes) TSP +instances cannot be solved in a reasonable time, and some instances may +cause abnormal termination of Concorde (if CPXgetijdiv is called). diff --git a/resources/3rdparty/glpk-4.53/examples/cplex/concorde.txt b/resources/3rdparty/glpk-4.53/examples/cplex/concorde.txt new file mode 100644 index 000000000..c6f7aec9b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/cplex/concorde.txt @@ -0,0 +1,121 @@ +Solver: Concorde-03.12.19 (options used: -s 99) + http://www.tsp.gatech.edu/concorde.html +LP Solver: GLPK 4.34 (CPLEX-like interface module examples/cplex) +Computer: Intel Pentium 4 CPU 3GHz, 2GB of RAM +Platform: Cygwin 1.5.24 (Windows XP 5.1 Build 2600 Service Pack 4) +Compiler: GCC 3.4.4 (options used: -O2) +Test set: http://www.iwr.uni-heidelberg.de/groups/comopt/software/ + TSPLIB95/ + +Problem Solution B&B Time, s +--------- -------- --- ------- +a280 2579 1 3.09 +ali535 202339 1 21.88 +att48 10628 1 0.20 +att532 27686 7 74.31 +bayg29 1610 1 0.08 +bays29 2020 1 0.08 +berlin52 7542 1 0.11 +bier127 118282 1 0.62 +brazil58 25395 1 0.23 +brd14051 +brg180 1950 1 0.34 +burma14 3323 1 0.06 +ch130 6110 1 0.92 +ch150 6528 1 1.69 +d1291 +d15112 +d1655 +d18512 +d198 15780 3 4.92 +d2103 +d493 35002 5 123.89 +d657 48913 11 148.17 +dantzig42 699 1 0.08 +dsj1000 18660188 13 251.00 +eil101 (failed due to CPXgetijdiv) +eil51 426 1 0.17 +eil76 538 1 0.11 +fl1400 +fl1577 +fl3795 +fl417 11861 1 47.20 +fnl4461 +fri26 937 1 0.05 +gil262 2378 3 10.39 +gr120 6942 1 0.66 +gr137 69853 1 2.09 +gr17 2085 1 0.03 +gr202 40160 1 3.97 +gr21 2707 1 0.03 +gr229 134602 7 19.45 +gr24 1272 1 0.03 +gr431 171414 9 40.67 +gr48 5046 1 0.22 +gr666 294358 3 40.23 +gr96 55209 1 1.22 +hk48 11461 1 0.08 +kroA100 21282 1 0.41 +kroA150 26524 1 2.09 +kroA200 29368 1 2.44 +kroB100 22141 1 1.20 +kroB150 26130 1 1.66 +kroB200 29437 1 1.41 +kroC100 20749 1 0.42 +kroD100 21294 1 0.50 +kroE100 22068 1 0.94 +lin105 14379 1 0.23 +lin318 42029 1 4.28 +nrw1379 +p654 34643 1 17.08 +pa561 2763 15 370.70 +pcb1173 56892 11 370.30 +pcb3038 +pcb442 59778 13 35.86 +pla33810 +pla7397 +pla85900 +pr1002 259045 1 23.08 +pr107 44303 1 0.38 +pr124 59030 1 1.23 +pr136 96772 1 2.19 +pr144 58537 1 0.89 +pr152 73682 1 2.73 +pr226 80369 1 2.72 +pr2392 +pr264 49135 1 1.61 +pr299 48191 3 14.52 +pr439 107217 15 117.75 +pr76 108159 1 0.95 +rat195 2323 5 12.91 +rat575 6773 19 202.52 +rat783 8806 1 37.92 +rat99 1211 1 0.50 +rd100 7910 1 0.28 +rd400 15281 11 74.41 +rl11849 +rl1304 +rl1323 +rl1889 +rl5915 +rl5934 +si1032 92650 1 82.09 +si175 21407 3 8.97 +si535 48450 1 71.28 +st70 675 1 0.20 +swiss42 1273 1 0.06 +ts225 126643 1 21.25 +tsp225 3916 1 10.14 +u1060 224094 13 507.44 +u1432 +u159 42080 1 0.41 +u1817 +u2152 +u2319 +u574 36905 1 32.84 +u724 41910 19 238.42 +ulysses16 6859 1 0.19 +ulysses22 7013 1 0.47 +usa13509 +vm1084 239297 9 543.38 +vm1748 diff --git a/resources/3rdparty/glpk-4.53/examples/cplex/cplex.c b/resources/3rdparty/glpk-4.53/examples/cplex/cplex.c new file mode 100644 index 000000000..ef9e2dffe --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/cplex/cplex.c @@ -0,0 +1,2130 @@ +/* cplex.c (CPLEX-like interface to GLPK API) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include <ctype.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <glpk.h> +#include "cplex.h" + +struct CPXENV +{ /* environment block */ + CPXLP *list; + /* linked list of problem objects */ + int *intparam; /* int intparam[]; */ + /* integer control parameters */ + double *dblparam; /* double dblparam[]; */ + /* floating-point control parameters */ +}; + +struct CPXLP +{ /* problem object */ + CPXENV *env; + /* pointer to environment block */ + glp_prob *prob; + /* pointer to underlying GLPK problem object */ + int rflen; + /* length of the array rflag */ + char *rflag; /* char rflag[rflen]; */ + /* rflag[i], i = 0,...,nrows-1, is a flag of i-th row: */ +#define RF_NOT_RANGED 0 /* not ranged */ +#define RF_RANGED_POS 1 /* ranged, RHS = lower bound */ +#define RF_RANGED_NEG 2 /* ranged, RHS = upper bound */ + int stat; + /* solution status reported by CPXgetstat; zero means no solution + exists */ + int meth; + /* method indicator reported by CPXgetmethod */ + int iwlen; + /* length of the working array */ + int *iwork; /* int iwork[iwlen] */ + /* working array initialized by binary zeros */ + CPXLP *link; + /* pointer to another problem object */ +}; + +struct intparam +{ int which; + int defv; + int minv; + int maxv; +}; + +struct dblparam +{ int which; + double defv; + double minv; + double maxv; +}; + +struct errstring +{ int code; + const char *string; +}; + +#define BIGINT 2100000000 +#define BIGDBL 1e75 + +static const struct intparam intparam[] = +{ {CPX_PARAM_ADVIND, 0, 0, 2}, + {CPX_PARAM_AGGIND, -1, -1, BIGINT}, + {CPX_PARAM_DATACHECK, CPX_OFF, CPX_OFF, CPX_ON}, + {CPX_PARAM_DPRIIND, CPX_DPRIIND_AUTO, CPX_DPRIIND_AUTO, + CPX_DPRIIND_DEVEX}, + {CPX_PARAM_FASTMIP, CPX_OFF, CPX_OFF, CPX_ON}, /* ??? */ + {CPX_PARAM_ITLIM, BIGINT, 0, BIGINT}, + {CPX_PARAM_PERIND, CPX_OFF, CPX_OFF, CPX_ON}, + {CPX_PARAM_PPRIIND, CPX_PPRIIND_AUTO, CPX_PPRIIND_PARTIAL, + CPX_PPRIIND_FULL}, + {CPX_PARAM_PREIND, CPX_ON, CPX_OFF, CPX_ON}, + {CPX_PARAM_REINV, 0, 0, 10000}, + {CPX_PARAM_SCRIND, CPX_OFF, CPX_OFF, CPX_ON}, + {CPX_PARAM_SIMDISPLAY, 1, 0, 2}, +}; + +static const struct dblparam dblparam[] = +{ {CPX_PARAM_EPOPT, 1e-6, 1e-9, 1e-1}, + {CPX_PARAM_EPPER, 1e-6, 1e-8, BIGDBL}, + {CPX_PARAM_EPRHS, 1e-6, 1e-9, 1e-1}, + {CPX_PARAM_OBJLLIM, -BIGDBL, -BIGDBL, +BIGDBL}, + {CPX_PARAM_OBJULIM, +BIGDBL, -BIGDBL, +BIGDBL}, +}; + +static const struct errstring errstring[] = +{ {CPXERR_ARRAY_NOT_ASCENDING, "Array entry %d not ascending"}, + {CPXERR_BAD_ARGUMENT, "Invalid argument"}, + {CPXERR_BAD_CTYPE, "Invalid ctype entry %d"}, + {CPXERR_BAD_FILETYPE, "Invalid filetype"}, + {CPXERR_BAD_LUB, "Invalid bound change indicator entry %d"}, + {CPXERR_BAD_PARAM_NUM, "Invalid parameter number"}, + {CPXERR_BAD_SENSE, "Invalid sense entry %d"}, + {CPXERR_BAD_STATUS, "Invalid status entry %d for basis specificat" + "ion"}, + {CPXERR_COL_INDEX_RANGE, "Column index %d out of range"}, + {CPXERR_COUNT_RANGE, "Count entry %d negative or larger than allo" + "wed"}, + {CPXERR_DUP_ENTRY, "Duplicate entry"}, + {CPXERR_FAIL_OPEN_WRITE, "Could not open file '%s' for writing"}, + {CPXERR_INDEX_RANGE, "Index is outside range of valid values"}, + {CPXERR_NEGATIVE_SURPLUS, "Insufficient array length"}, + {CPXERR_NO_BASIC_SOLN, "No basic solution exists"}, + {CPXERR_NO_ENVIRONMENT, "No environment exists"}, + {CPXERR_NO_FILENAME, "File name not specified"}, + {CPXERR_NO_MEMORY, "Out of memory"}, + {CPXERR_NO_PROBLEM, "No problem exists"}, + {CPXERR_NO_SOLN, "No solution exists"}, + {CPXERR_NOT_FIXED, "Only fixed variables are pivoted out"}, + {CPXERR_NULL_NAME, "Null pointer %d in name array"}, + {CPXERR_NULL_POINTER, "Null pointer for required data"}, + {CPXERR_PARAM_TOO_BIG, "Parameter value too big"}, + {CPXERR_PARAM_TOO_SMALL, "Parameter value too small"}, + {CPXERR_ROW_INDEX_RANGE, "Row index %d out of range"}, +}; + +/**********************************************************************/ + +#define xassert glp_assert +#define xprintf glp_printf +#define xmalloc glp_malloc +#define xcalloc glp_calloc +#define xfree glp_free + +/**********************************************************************/ + +static int findintparam(int whichparam) +{ int k, card; + card = sizeof(intparam) / sizeof(struct intparam); + for (k = 0; k < card; k++) + if (intparam[k].which == whichparam) return k; + return -1; +} + +static int getintparam(CPXENV *env, int whichparam) +{ int k; + xassert(env != NULL); + k = findintparam(whichparam); + xassert(k >= 0); + return env->intparam[k]; +} + +static int finddblparam(int whichparam) +{ int k, card; + card = sizeof(dblparam) / sizeof(struct dblparam); + for (k = 0; k < card; k++) + if (dblparam[k].which == whichparam) return k; + return -1; +} + +static double getdblparam(CPXENV *env, int whichparam) +{ int k; + xassert(env != NULL); + k = finddblparam(whichparam); + xassert(k >= 0); + return env->dblparam[k]; +} + +static const char *finderrstring(int errcode) +{ int k, card; + card = sizeof(errstring) / sizeof(struct errstring); + for (k = 0; k < card; k++) + { if (errstring[k].code == errcode) + return errstring[k].string; + } + return NULL; +} + +static int error(CPXENV *env, int errcode, ...) +{ va_list arg; + char buffer[510]; + xassert(env != NULL); + if (getintparam(env, CPX_PARAM_SCRIND) == CPX_ON) + { xassert(CPXgeterrorstring(env, errcode, buffer) == buffer); + va_start(arg, errcode); + vprintf(buffer, arg); + va_end(arg); + } + return errcode; +} + +static int checkenv(CPXENV *env) +{ int errcode; + if (env == NULL) + errcode = CPXERR_NO_ENVIRONMENT; + else + errcode = 0; + return errcode; +} + +static checklp(CPXENV *env, CPXLP *lp) +{ int errcode; + errcode = checkenv(env); + if (errcode) goto done; + if (lp == NULL) + errcode = error(env, CPXERR_NO_PROBLEM); +done: return errcode; +} + +static void invalidate(CPXLP *lp) +{ lp->stat = 0; + lp->meth = CPX_ALG_NONE; + return; +} + +static void enlargerflag(CPXLP *lp) +{ int m; + xassert(lp != NULL); + m = glp_get_num_rows(lp->prob); + if (lp->rflen < m) + { int rflen = lp->rflen; + char *rflag = lp->rflag; + while (lp->rflen < m) + { lp->rflen += lp->rflen; + xassert(lp->rflen > 0); + } + lp->rflag = xcalloc(lp->rflen, sizeof(char)); + memcpy(lp->rflag, rflag, rflen); + xfree(rflag); + } + return; +} + +static void enlargeiwork(CPXLP *lp, int len) +{ xassert(len >= 0); + if (lp->iwlen < len) + { xfree(lp->iwork); + while (lp->iwlen < len) + { lp->iwlen += lp->iwlen; + xassert(lp->iwlen > 0); + } + lp->iwork = xcalloc(lp->iwlen, sizeof(int)); + memset(lp->iwork, 0, lp->iwlen * sizeof(int)); + } + return; +} + +/**********************************************************************/ + +int CPXaddcols(CPXENV *env, CPXLP *lp, int ccnt, int nzcnt, + const double obj[], const int cmatbeg[], const int cmatind[], + const double cmatval[], const double lb[], const double ub[], + char *colname[]) +{ int j, k, m, n, beg, end, type, errcode; + double lbnd, ubnd; + errcode = checklp(env, lp); + if (errcode) goto done; + if (ccnt < 0 || nzcnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (ccnt > 0) + { if (cmatbeg == NULL || cmatind == NULL || cmatval == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + } + m = glp_get_num_rows(lp->prob); + n = glp_get_num_cols(lp->prob); + enlargeiwork(lp, m); + for (j = 0; j < ccnt; j++) + { beg = cmatbeg[j]; + if (j > 0 && !(cmatbeg[j-1] <= beg)) + { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j); + goto done; + } + if (!(0 <= beg && beg <= nzcnt)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt); + for (k = beg; k < end; k++) + { if (!(0 <= cmatind[k] && cmatind[k] < m)) + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k); + goto done; + } + } + errcode = 0; + for (k = beg; k < end; k++) + { if (lp->iwork[cmatind[k]]) + { errcode = error(env, CPXERR_DUP_ENTRY); + break; + } + lp->iwork[cmatind[k]] = 1; + } + for (k = beg; k < end; k++) + lp->iwork[cmatind[k]] = 0; + if (errcode) goto done; + if (colname != NULL) + { if (colname[j] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, j); + goto done; + } + } + } + errcode = 0; + invalidate(lp); + if (ccnt > 0) + glp_add_cols(lp->prob, ccnt); + for (j = 0; j < ccnt; j++) + { if (colname != NULL) + glp_set_col_name(lp->prob, n+j+1, colname[j]); + lbnd = (lb == NULL ? 0.0 : lb[j]); + ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]); + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) + type = GLP_FR; + else if (ubnd >= +CPX_INFBOUND) + type = GLP_LO; + else if (lbnd <= -CPX_INFBOUND) + type = GLP_UP; + else if (lbnd != ubnd) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd); + if (obj != NULL) + glp_set_obj_coef(lp->prob, n+j+1, obj[j]); + beg = cmatbeg[j]; + end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt); + for (k = beg; k < end; k++) + lp->iwork[k-beg] = cmatind[k]+1; + glp_set_mat_col(lp->prob, n+j+1, end-beg, lp->iwork-1, + cmatval+beg-1); + for (k = beg; k < end; k++) + lp->iwork[k-beg] = 0; + } +done: return errcode; +} + +int CPXaddrows(CPXENV *env, CPXLP *lp, int ccnt, int rcnt, int nzcnt, + const double rhs[], const char sense[], const int rmatbeg[], + const int rmatind[], const double rmatval[], char *colname[], + char *rowname[]) +{ int i, j, k, m, n, beg, end, type, errcode; + double temp; + errcode = checklp(env, lp); + if (errcode) goto done; + if (ccnt < 0 || rcnt < 0 || nzcnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (rcnt > 0) + { if (rmatbeg == NULL || rmatind == NULL || rmatval == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + } + m = glp_get_num_rows(lp->prob); + n = glp_get_num_cols(lp->prob); + enlargeiwork(lp, n+ccnt); + for (i = 0; i < rcnt; i++) + { if (sense != NULL) + { if (!(sense[i] == 'L' || sense[i] == 'E' || + sense[i] == 'G' || sense[i] == 'R')) + { errcode = error(env, CPXERR_BAD_SENSE, i); + goto done; + } + } + beg = rmatbeg[i]; + if (i > 0 && !(rmatbeg[i-1] <= beg)) + { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, i); + goto done; + } + if (!(0 <= beg && beg <= nzcnt)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt); + for (k = beg; k < end; k++) + { if (!(0 <= rmatind[k] && rmatind[k] < n+ccnt)) + { errcode = error(env, CPXERR_COL_INDEX_RANGE, k); + goto done; + } + } + errcode = 0; + for (k = beg; k < end; k++) + { if (lp->iwork[rmatind[k]]) + { errcode = error(env, CPXERR_DUP_ENTRY); + break; + } + lp->iwork[rmatind[k]] = 1; + } + for (k = beg; k < end; k++) + lp->iwork[rmatind[k]] = 0; + if (errcode) goto done; + if (rowname != NULL) + { if (rowname[i] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, i); + goto done; + } + } + } + for (j = 0; j < ccnt; j++) + { if (colname != NULL) + { if (colname[j] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, j); + goto done; + } + } + } + errcode = 0; + invalidate(lp); + if (rcnt > 0) + glp_add_rows(lp->prob, rcnt); + if (ccnt > 0) + glp_add_cols(lp->prob, ccnt); + enlargerflag(lp); + for (i = 0; i < rcnt; i++) + { if (rowname != NULL) + glp_set_row_name(lp->prob, m+i+1, rowname[i]); + temp = (rhs == NULL ? 0.0 : rhs[i]); + if (sense == NULL || sense[i] == 'E') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_FX; + } + else if (sense[i] == 'L') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_UP; + } + else if (sense[i] == 'G') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_LO; + } + else if (sense[i] == 'R') + { lp->rflag[m+i] = RF_RANGED_POS; + type = GLP_FX; + } + else + xassert(sense != sense); + glp_set_row_bnds(lp->prob, m+i+1, type, temp, temp); + beg = rmatbeg[i]; + end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt); + for (k = beg; k < end; k++) + lp->iwork[k-beg] = rmatind[k]+1; + glp_set_mat_row(lp->prob, m+i+1, end-beg, lp->iwork-1, + rmatval+beg-1); + for (k = beg; k < end; k++) + lp->iwork[k-beg] = 0; + } + for (j = 0; j < ccnt; j++) + { if (colname != NULL) + glp_set_col_name(lp->prob, n+j+1, colname[j]); + glp_set_col_bnds(lp->prob, n+j+1, GLP_LO, 0.0, 0.0); + } +done: return errcode; +} + +int CPXbaropt(CPXENV *env, CPXLP *lp) +{ xassert(env == env); + xassert(lp == lp); + xprintf("CPXbaropt: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXbinvrow(CPXENV *env, CPXLP *lp, int i, double y[]) +{ xassert(env == env); + xassert(lp == lp); + xassert(i == i); + xassert(y == y); + xprintf("CPXbinvrow: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXchgbds(CPXENV *env, CPXLP *lp, int cnt, const int indices[], + const char lu[], const double bd[]) +{ int j, n, type, errcode; + double lbnd, ubnd; + errcode = checklp(env, lp); + if (errcode) goto done; + if (cnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (cnt > 0) + { if (indices == NULL || lu == NULL || bd == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + } + n = glp_get_num_cols(lp->prob); + for (j = 0; j < cnt; j++) + { if (!(0 <= indices[j] && indices[j] < n)) + { errcode = error(env, CPXERR_COL_INDEX_RANGE, j); + goto done; + } + if (!(lu[j] == 'L' || lu[j] == 'U' || lu[j] == 'B')) + { errcode = error(env, CPXERR_BAD_LUB, j); + goto done; + } + } + errcode = 0; + invalidate(lp); + for (j = 0; j < cnt; j++) + { type = glp_get_col_type(lp->prob, indices[j]+1); + lbnd = glp_get_col_lb(lp->prob, indices[j]+1); + ubnd = glp_get_col_ub(lp->prob, indices[j]+1); + if (type == GLP_FR || type == GLP_UP) + lbnd = -CPX_INFBOUND; + if (type == GLP_FR || type == GLP_LO) + ubnd = +CPX_INFBOUND; + if (lu[j] == 'L') + lbnd = bd[j]; + else if (lu[j] == 'U') + ubnd = bd[j]; + else if (lu[j] == 'B') + lbnd = ubnd = bd[j]; + else + xassert(lu != lu); + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) + type = GLP_FR; + else if (ubnd >= +CPX_INFBOUND) + type = GLP_LO; + else if (lbnd <= -CPX_INFBOUND) + type = GLP_UP; + else if (lbnd != ubnd) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp->prob, indices[j]+1, type, lbnd, ubnd); + } +done: return errcode; +} + +int CPXchgcoeflist(CPXENV *env, CPXLP *lp, int numcoefs, + const int rowlist[], const int collist[], const double vallist[]) +{ int i, j, k, m, n, rcnt, ccnt, len, ptr, errcode; + int *head, *next, *ind; + double *val; + errcode = checklp(env, lp); + if (errcode) goto done; + if (numcoefs < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (numcoefs == 0) + { errcode = 0; + goto done; + } + if (rowlist == NULL || collist == NULL || vallist == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + /* check triplets and determine the number of rows and columns + to be changed */ + m = glp_get_num_rows(lp->prob); + n = glp_get_num_cols(lp->prob); + enlargeiwork(lp, m); + enlargeiwork(lp, n); + rcnt = ccnt = 0; + for (k = 0; k < numcoefs; k++) + { i = rowlist[k]; + if (!(0 <= i && i < m)) + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i); + goto done; + } + if (!(lp->iwork[i] & 0x01)) + rcnt++, lp->iwork[i] |= 0x01; + j = collist[k]; + if (!(0 <= j && j < n)) + { errcode = error(env, CPXERR_COL_INDEX_RANGE, j); + goto done; + } + if (!(lp->iwork[j] & 0x02)) + ccnt++, lp->iwork[j] |= 0x02; + } + memset(lp->iwork, 0, m * sizeof(int)); + memset(lp->iwork, 0, n * sizeof(int)); + errcode = 0; + invalidate(lp); + if (rcnt <= ccnt) + { /* change the matrix by rows */ + /* build the linked list of triplets: + head[i] is a pointer to first triplet for row i + next[k] is a pointer to next triplet for the same row */ + head = xcalloc(m, sizeof(int)); + for (i = 0; i < m; i++) + head[i] = -1; + next = xcalloc(numcoefs, sizeof(int)); + for (k = 0; k < numcoefs; k++) + { i = rowlist[k]; + next[k] = head[i]; + head[i] = k; + } + /* check duplicate columns */ + for (i = 0; i < m; i++) + { for (k = head[i]; k >= 0; k = next[k]) + { j = collist[k]; + if (lp->iwork[j]) + { xfree(head); + xfree(next); + errcode = error(env, CPXERR_DUP_ENTRY); + goto done; + } + lp->iwork[j] = 1; + } + for (k = head[i]; k >= 0; k = next[k]) + lp->iwork[collist[k]] = 0; + } + /* perform operation */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + for (i = 0; i < m; i++) + { if (head[i] < 0) continue; + len = glp_get_mat_row(lp->prob, i+1, ind, val); + for (ptr = 1; ptr <= len; ptr++) + { j = ind[ptr]-1; + xassert(lp->iwork[j] == 0); + lp->iwork[j] = ptr; + } + for (k = head[i]; k >= 0; k = next[k]) + { j = collist[k]; + if (lp->iwork[j] == 0) + lp->iwork[j] = ++len; + ptr = lp->iwork[j]; + ind[ptr] = j+1, val[ptr] = vallist[k]; + } + glp_set_mat_row(lp->prob, i+1, len, ind, val); + for (ptr = 1; ptr <= len; ptr++) + lp->iwork[ind[ptr]-1] = 0; + } + } + else + { /* change the matrix by columns */ + /* build the linked lists of triplets: + head[j] is a pointer to first triplet for column j + next[k] is a pointer to next triplet for the same column */ + head = xcalloc(n, sizeof(int)); + for (j = 0; j < n; j++) + head[j] = -1; + next = xcalloc(numcoefs, sizeof(int)); + for (k = 0; k < numcoefs; k++) + { j = collist[k]; + next[k] = head[j]; + head[j] = k; + } + /* check duplicate rows */ + for (j = 0; j < n; j++) + { for (k = head[j]; k >= 0; k = next[k]) + { i = rowlist[k]; + if (lp->iwork[i]) + { xfree(head); + xfree(next); + errcode = error(env, CPXERR_DUP_ENTRY); + goto done; + } + lp->iwork[i] = 1; + } + for (k = head[j]; k >= 0; k = next[k]) + lp->iwork[rowlist[k]] = 0; + } + /* perform operation */ + ind = xcalloc(1+m, sizeof(int)); + val = xcalloc(1+m, sizeof(double)); + for (j = 0; j < n; j++) + { if (head[j] < 0) continue; + len = glp_get_mat_col(lp->prob, j+1, ind, val); + for (ptr = 1; ptr <= len; ptr++) + { i = ind[ptr]-1; + xassert(lp->iwork[i] == 0); + lp->iwork[i] = ptr; + } + for (k = head[j]; k >= 0; k = next[k]) + { i = rowlist[k]; + if (lp->iwork[i] == 0) + lp->iwork[i] = ++len; + ptr = lp->iwork[i]; + ind[ptr] = i+1, val[ptr] = vallist[k]; + } + glp_set_mat_col(lp->prob, j+1, len, ind, val); + for (ptr = 1; ptr <= len; ptr++) + lp->iwork[ind[ptr]-1] = 0; + } + } + xfree(head); + xfree(next); + xfree(ind); + xfree(val); +done: return errcode; +} + +void CPXchgobjsen(CPXENV *env, CPXLP *lp, int maxormin) +{ int errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (!(maxormin == CPX_MIN || maxormin == CPX_MAX)) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + errcode = 0; + invalidate(lp); + if (maxormin == CPX_MIN) + glp_set_obj_dir(lp->prob, GLP_MIN); + else + glp_set_obj_dir(lp->prob, GLP_MAX); +done: xassert(errcode == errcode); + return; +} + +int CPXchgsense(CPXENV *env, CPXLP *lp, int cnt, const int indices[], + const char sense[]) +{ int i, m, type, errcode; + double rhs; + errcode = checklp(env, lp); + if (errcode) goto done; + if (cnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (cnt > 0 && (indices == NULL || sense == NULL)) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + m = glp_get_num_rows(lp->prob); + for (i = 0; i < cnt; i++) + { if (!(0 <= indices[i] && indices[i] < m)) + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i); + goto done; + } + if (!(sense[i] == 'L' || sense[i] == 'E' || sense[i] == 'G' || + sense[i] == 'R')) + { errcode = error(env, CPXERR_BAD_SENSE, i); + goto done; + } + } + errcode = 0; + invalidate(lp); + for (i = 0; i < cnt; i++) + { type = glp_get_row_type(lp->prob, indices[i]+1); + if (lp->rflag[indices[i]] == RF_NOT_RANGED) + { if (type == GLP_LO || type == GLP_FX) + rhs = glp_get_row_lb(lp->prob, indices[i]+1); + else if (type == GLP_UP) + rhs = glp_get_row_ub(lp->prob, indices[i]+1); + else + xassert(type != type); + } + else if (lp->rflag[indices[i]] == RF_RANGED_POS) + { xassert(type == GLP_DB || type == GLP_FX); + rhs = glp_get_row_lb(lp->prob, indices[i]+1); + } + else if (lp->rflag[indices[i]] == RF_RANGED_NEG) + { xassert(type == GLP_DB); + rhs = glp_get_row_ub(lp->prob, indices[i]+1); + } + else + xassert(lp != lp); + if (sense[i] == 'L') + { lp->rflag[indices[i]] = RF_NOT_RANGED; + type = GLP_UP; + } + else if (sense[i] == 'E') + { lp->rflag[indices[i]] = RF_NOT_RANGED; + type = GLP_FX; + } + else if (sense[i] == 'G') + { lp->rflag[indices[i]] = RF_NOT_RANGED; + type = GLP_LO; + } + else if (sense[i] == 'R') + { lp->rflag[indices[i]] = RF_RANGED_POS; + type = GLP_FX; + } + else + xassert(sense != sense); + glp_set_row_bnds(lp->prob, indices[i]+1, type, rhs, rhs); + } +done: return errcode; +} + +int CPXcloseCPLEX(CPXENV **_env) +{ CPXENV *env; + CPXLP *lp; + int errcode; + if (_env == NULL) + { errcode = CPXERR_NULL_POINTER; + goto done; + } + env = *_env; + errcode = checkenv(env); + if (errcode) goto done; + while (env->list != NULL) + { lp = env->list; + errcode = CPXfreeprob(env, &lp); + xassert(!errcode); + } + xfree(env->intparam); + xfree(env->dblparam); + xfree(env); + *_env = NULL; + errcode = 0; +done: return errcode; +} + +int CPXcopybase(CPXENV *env, CPXLP *lp, const int cstat[], + const int rstat[]) +{ int i, j, m, n, stat, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + m = glp_get_num_rows(lp->prob); + n = glp_get_num_cols(lp->prob); + if (m > 0 && rstat == NULL || n > 0 && cstat == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + for (i = 0; i < m; i++) + { if (!(rstat[i] == CPX_AT_LOWER || rstat[i] == CPX_BASIC || + rstat[i] == CPX_AT_UPPER)) + { errcode = error(env, CPXERR_BAD_STATUS, i); + goto done; + } + } + for (j = 0; j < n; j++) + { if (!(cstat[j] == CPX_AT_LOWER || cstat[j] == CPX_BASIC || + cstat[j] == CPX_AT_UPPER || cstat[j] == CPX_FREE_SUPER)) + { errcode = error(env, CPXERR_BAD_STATUS, j); + goto done; + } + } + errcode = 0; + invalidate(lp); + for (i = 0; i < m; i++) + { if (rstat[i] == CPX_AT_LOWER) + stat = GLP_NL; + else if (rstat[i] == CPX_BASIC) + stat = GLP_BS; + else if (rstat[i] == CPX_AT_UPPER) + stat = GLP_NU; + else + xassert(rstat != rstat); + glp_set_row_stat(lp->prob, i+1, stat); + } + for (j = 0; j < n; j++) + { if (cstat[j] == CPX_AT_LOWER) + stat = GLP_NL; + else if (cstat[j] == CPX_BASIC) + stat = GLP_BS; + else if (cstat[j] == CPX_AT_UPPER) + stat = GLP_NU; + else if (cstat[j] == CPX_FREE_SUPER) + stat = GLP_NF; + else + xassert(cstat != cstat); + glp_set_col_stat(lp->prob, j+1, stat); + } +done: return errcode; +} + +int CPXcopybasednorms(CPXENV *env, CPXLP *lp, const int cstat[], + const int rstat[], const double dnorm[]) +{ int errcode; + errcode = CPXcopybase(env, lp, cstat, rstat); + xassert(dnorm == dnorm); + return errcode; +} + +int CPXcopylp(CPXENV *env, CPXLP *lp, int numcols, int numrows, + int objsen, const double obj[], const double rhs[], + const char sense[], const int matbeg[], const int matcnt[], + const int matind[], const double matval[], const double lb[], + const double ub[], const double rngval[]) +{ int errcode; + errcode = CPXcopylpwnames(env, lp, numcols, numrows, objsen, obj, + rhs, sense, matbeg, matcnt, matind, matval, lb, ub, rngval, + NULL, NULL); + return errcode; +} + +int CPXcopylpwnames(CPXENV *env, CPXLP *lp, int numcols, int numrows, + int objsen, const double obj[], const double rhs[], + const char sense[], const int matbeg[], const int matcnt[], + const int matind[], const double matval[], const double lb[], + const double ub[], const double rngval[], char *colname[], + char *rowname[]) +{ int i, j, k, beg, end, type, errcode; + double lbnd, ubnd; + char name[255+1]; + errcode = checklp(env, lp); + if (errcode) goto done; + if (numcols < 0 || numrows < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (!(objsen == CPX_MIN || objsen == CPX_MAX)) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (numcols > 0) + { if (matbeg == NULL || matcnt == NULL || matind == NULL || + matval == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + } + for (i = 0; i < numrows; i++) + { if (sense != NULL) + { if (!(sense[i] == 'L' || sense[i] == 'E' || + sense[i] == 'G' || sense[i] == 'R')) + { errcode = error(env, CPXERR_BAD_SENSE, i); + goto done; + } + } + if (rowname != NULL) + { if (rowname[i] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, i); + goto done; + } + } + } + enlargeiwork(lp, numrows); + for (j = 0; j < numcols; j++) + { beg = matbeg[j]; + if (j > 0 && !(matbeg[j-1] <= beg)) + { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j); + goto done; + } + if (beg < 0) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + end = beg + matcnt[j]; + if (!(beg <= end) || j < numcols-1 && !(end <= matbeg[j+1])) + { errcode = error(env, CPXERR_COUNT_RANGE, j); + goto done; + } + for (k = beg; k < end; k++) + { if (!(0 <= matind[k] && matind[k] < numrows)) + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k); + goto done; + } + } + errcode = 0; + for (k = beg; k < end; k++) + { if (lp->iwork[matind[k]]) + { errcode = error(env, CPXERR_DUP_ENTRY); + break; + } + lp->iwork[matind[k]] = 1; + } + for (k = beg; k < end; k++) + lp->iwork[matind[k]] = 0; + if (errcode) goto done; + if (colname != NULL) + { if (colname[j] != NULL) + { errcode = error(env, CPXERR_NULL_NAME, j); + goto done; + } + } + } + errcode = 0; + invalidate(lp); + if (glp_get_prob_name(lp->prob) == NULL) + name[0] = '\0'; + else + strcpy(name, glp_get_prob_name(lp->prob)); + glp_erase_prob(lp->prob); + glp_set_prob_name(lp->prob, name); + if (objsen == CPX_MIN) + glp_set_obj_dir(lp->prob, GLP_MIN); + else if (objsen == CPX_MAX) + glp_set_obj_dir(lp->prob, GLP_MAX); + else + xassert(objsen != objsen); + if (numrows > 0) + glp_add_rows(lp->prob, numrows); + enlargerflag(lp); + for (i = 0; i < numrows; i++) + { if (rowname != NULL) + glp_set_row_name(lp->prob, i+1, rowname[i]); + lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]); + if (sense == NULL || sense[i] == 'E') + { lp->rflag[i] = RF_NOT_RANGED; + type = GLP_FX; + } + else if (sense[i] == 'L') + { lp->rflag[i] = RF_NOT_RANGED; + type = GLP_UP; + } + else if (sense[i] == 'G') + { lp->rflag[i] = RF_NOT_RANGED; + type = GLP_LO; + } + else if (sense[i] == 'R') + { if (rngval == NULL || rngval[i] == 0.0) + { lp->rflag[i] = RF_RANGED_POS; + type = GLP_FX; + } + else if (rngval[i] > 0.0) + { lp->rflag[i] = RF_RANGED_POS; + type = GLP_DB; + ubnd += rngval[i]; + } + else /* rngval[i] < 0.0 */ + { lp->rflag[i] = RF_RANGED_NEG; + type = GLP_DB; + lbnd += rngval[i]; + } + } + else + xassert(sense != sense); + glp_set_row_bnds(lp->prob, i+1, type, lbnd, ubnd); + } + if (numcols > 0) + glp_add_cols(lp->prob, numcols); + for (j = 0; j < numcols; j++) + { if (colname != NULL) + glp_set_col_name(lp->prob, j+1, colname[j]); + lbnd = (lb == NULL ? 0.0 : lb[j]); + ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]); + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) + type = GLP_FR; + else if (ubnd >= +CPX_INFBOUND) + type = GLP_LO; + else if (lbnd <= -CPX_INFBOUND) + type = GLP_UP; + else if (lbnd != ubnd) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp->prob, j+1, type, lbnd, ubnd); + if (obj != NULL) + glp_set_obj_coef(lp->prob, j+1, obj[j]); + beg = matbeg[j]; + end = beg + matcnt[j]; + for (k = beg; k < end; k++) + lp->iwork[k-beg] = matind[k]+1; + glp_set_mat_col(lp->prob, j+1, end-beg, lp->iwork-1, + matval+beg-1); + for (k = beg; k < end; k++) + lp->iwork[k-beg] = 0; + } +done: return errcode; +} + +CPXLP *CPXcreateprob(CPXENV *env, int *status, const char *probname) +{ CPXLP *lp = NULL; + int errcode; + errcode = checkenv(env); + if (errcode) goto done; + lp = xmalloc(sizeof(struct CPXLP)); + lp->env = env; + lp->prob = glp_create_prob(); + glp_set_prob_name(lp->prob, probname); + lp->rflen = 100; + lp->rflag = xcalloc(lp->rflen, sizeof(char)); + lp->iwlen = 100; + lp->iwork = xcalloc(lp->iwlen, sizeof(int)); + memset(lp->iwork, 0, lp->iwlen * sizeof(int)); + lp->link = env->list; + env->list = lp; + invalidate(lp); +done: if (status != NULL) *status = errcode; + return lp; +} + +int CPXdelcols(CPXENV *env, CPXLP *lp, int begin, int end) +{ int j, n, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + n = glp_get_num_cols(lp->prob); + if (!(0 <= begin && begin <= end && end < n)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + errcode = 0; + invalidate(lp); + enlargeiwork(lp, end-begin+1); + for (j = begin; j <= end; j++) + lp->iwork[j-begin] = j+1; + glp_del_cols(lp->prob, end-begin+1, lp->iwork-1); + for (j = begin; j <= end; j++) + lp->iwork[j-begin] = 0; +done: return errcode; +} + +int CPXdelrows(CPXENV *env, CPXLP *lp, int begin, int end) +{ int i, m, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + m = glp_get_num_rows(lp->prob); + if (!(0 <= begin && begin <= end && end < m)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + errcode = 0; + invalidate(lp); + enlargeiwork(lp, end-begin+1); + for (i = begin; i <= end; i++) + lp->iwork[i-begin] = i+1; + glp_del_rows(lp->prob, end-begin+1, lp->iwork-1); + for (i = begin; i <= end; i++) + lp->iwork[i-begin] = 0; + for (i = end+1; i < m; i++) + lp->rflag[i-(end-begin+1)] = lp->rflag[i]; +done: return errcode; +} + +int CPXdelsetcols(CPXENV *env, CPXLP *lp, int delstat[]) +{ xassert(env == env); + xassert(lp == lp); + xassert(delstat == delstat); + xprintf("CPXdelsetcols: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXdelsetrows(CPXENV *env, CPXLP *lp, int delstat[]) +{ int i, m, cnt, ind, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + m = glp_get_num_rows(lp->prob); + if (m > 0 && delstat == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + errcode = 0; + invalidate(lp); + enlargeiwork(lp, m); + cnt = ind = 0; + for (i = 0; i < m; i++) + { if (delstat[i] == 1) + { delstat[i] = -1; + lp->iwork[cnt++] = i+1; + } + else + { delstat[i] = ind; + lp->rflag[ind++] = lp->rflag[i]; + } + } + if (cnt > 0) + glp_del_rows(lp->prob, cnt, lp->iwork-1); + for (i = 0; i < cnt; i++) + lp->iwork[i] = 0; +done: return errcode; +} + +int CPXdualopt(CPXENV *env, CPXLP *lp); + +int CPXfreeprob(CPXENV *env, CPXLP **_lp) +{ CPXLP *lp; + int errcode; + errcode = checkenv(env); + if (errcode) goto done; + if (_lp == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + lp = *_lp; + errcode = checklp(env, lp); + if (errcode) goto done; + errcode = 0; + env = lp->env; + if (env->list == lp) + env->list = lp->link; + else + { CPXLP *pp; + for (pp = env->list; pp != NULL; pp = pp->link) + if (pp->link == lp) break; + xassert(pp != NULL); + pp->link = lp->link; + } + glp_delete_prob(lp->prob); + xfree(lp->rflag); + xfree(lp->iwork); + xfree(lp); + *_lp = NULL; +done: return errcode; +} + +int CPXgetbase(CPXENV *env, CPXLP *lp, int cstat[], int rstat[]) +{ int i, j, m, n, stat, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + ; + else + { errcode = error(env, CPXERR_NO_BASIC_SOLN); + goto done; + } + errcode = 0; + if (rstat != NULL) + { m = glp_get_num_rows(lp->prob); + for (i = 0; i < m; i++) + { stat = glp_get_row_stat(lp->prob, i+1); + if (stat == GLP_BS) + rstat[i] = CPX_BASIC; + else if (lp->rflag[i] == RF_NOT_RANGED || stat != GLP_NU) + rstat[i] = CPX_AT_LOWER; + else + rstat[i] = CPX_AT_UPPER; + } + } + if (cstat != NULL) + { n = glp_get_num_cols(lp->prob); + for (j = 0; j < n; j++) + { stat = glp_get_col_stat(lp->prob, j+1); + if (stat == GLP_BS) + cstat[j] = CPX_BASIC; + else if (stat == GLP_NU) + cstat[j] = CPX_AT_UPPER; + else if (stat == GLP_NF) + cstat[j] = CPX_FREE_SUPER; + else + cstat[j] = CPX_AT_LOWER; + } + } +done: return errcode; +} + +int CPXgetbasednorms(CPXENV *env, CPXLP *lp, int cstat[], int rstat[], + double dnorm[]) +{ int i, m, errcode; + errcode = CPXgetbase(env, lp, cstat, rstat); + if (errcode) goto done; + if (dnorm != NULL) + { m = glp_get_num_rows(lp->prob); + for (i = 0; i < m; i++) dnorm[i] = 1.0; + } +done: return errcode; +} + +int CPXgetbhead(CPXENV *env, CPXLP *lp, int head[], double x[]) +{ xassert(env == env); + xassert(lp == lp); + xassert(head == head); + xassert(x == x); + xprintf("CPXgetbhead: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetdblparam(CPXENV *env, int whichparam, double *value) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = finddblparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + errcode = 0; + if (value != NULL) + *value = env->dblparam[k]; +done: return errcode; +} + +int CPXgetdj(CPXENV *env, CPXLP *lp, double dj[], int begin, int end) +{ int j, n, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + n = glp_get_num_cols(lp->prob); + if (!(0 <= begin && begin <= end && end < n)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (dj != NULL) + { for (j = begin; j <= end; j++) + dj[j-begin] = glp_get_col_dual(lp->prob, j+1); + } + } + else + xassert(lp != lp); +done: return errcode; +} + +char *CPXgeterrorstring(CPXENV *env, int errcode, char *buffer) +{ const char *string; + xassert(env == env); + string = finderrstring(errcode); + if (string == NULL) + buffer = NULL; + else + sprintf(buffer, "CPLEX Error %5d: %s.\n", errcode, string); + return buffer; +} + +int CPXgetijdiv(CPXENV *env, CPXLP *lp, int *idiv, int *jdiv) +{ xassert(env == env); + xassert(lp == lp); + xassert(idiv == idiv); + xassert(jdiv == jdiv); + xprintf("CPXgetijdiv: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetintparam(CPXENV *env, int whichparam, int *value) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = findintparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + errcode = 0; + if (value != NULL) + *value = env->intparam[k]; +done: return errcode; +} + +int CPXgetlb(CPXENV *env, CPXLP *lp, double lb[], int begin, int end) +{ xassert(env == env); + xassert(lp == lp); + xassert(lb == lb); + xassert(begin == begin); + xassert(end == end); + xprintf("CPXgetlb: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetmethod(CPXENV *env, CPXLP *lp) +{ int method; + if (checklp(env, lp)) + method = CPX_ALG_NONE; + else + method = lp->meth; + return method; +} + +int CPXgetnumcols(CPXENV *env, CPXLP *lp) +{ int numcols; + if (checklp(env, lp)) + numcols = 0; + else + numcols = glp_get_num_cols(lp->prob); + return numcols; +} + +int CPXgetnumnz(CPXENV *env, CPXLP *lp) +{ int numnz; + if (checklp(env, lp)) + numnz = 0; + else + numnz = glp_get_num_nz(lp->prob); + return numnz; +} + +int CPXgetnumrows(CPXENV *env, CPXLP *lp) +{ int numrows; + if (checklp(env, lp)) + numrows = 0; + else + numrows = glp_get_num_rows(lp->prob); + return numrows; +} + +int CPXgetobjval(CPXENV *env, CPXLP *lp, double *objval) +{ int errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (objval != NULL) + *objval = glp_get_obj_val(lp->prob); + } + else + xassert(lp != lp); +done: return errcode; +} + +int CPXgetpi(CPXENV *env, CPXLP *lp, double pi[], int begin, int end) +{ int i, m, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + m = glp_get_num_rows(lp->prob); + if (!(0 <= begin && begin <= end && end < m)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (pi != NULL) + { for (i = begin; i <= end; i++) + pi[i-begin] = glp_get_row_dual(lp->prob, i+1); + } + } + else + xassert(lp != lp); +done: return errcode; +} + +int CPXgetsense(CPXENV *env, CPXLP *lp, char sense[], int begin, + int end) +{ xassert(env == env); + xassert(lp == lp); + xassert(sense == sense); + xassert(begin == begin); + xassert(end == end); + xprintf("CPXgetsense: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetslack(CPXENV *env, CPXLP *lp, double slack[], int begin, + int end) +{ int i, m, type, errcode; + double temp; + errcode = checklp(env, lp); + if (errcode) goto done; + m = glp_get_num_rows(lp->prob); + if (!(0 <= begin && begin <= end && end < m)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (slack != NULL) + { for (i = begin; i <= end; i++) + { type = glp_get_row_type(lp->prob, i+1); + temp = glp_get_row_prim(lp->prob, i+1); + if (lp->rflag[i] == RF_NOT_RANGED) + { if (type == GLP_LO || type == GLP_FX) + slack[i-begin] = + glp_get_row_lb(lp->prob, i+1) - temp; + else if (type == GLP_UP) + slack[i-begin] = + glp_get_row_ub(lp->prob, i+1) - temp; + else + xassert(type != type); + } + else if (lp->rflag[i] == RF_RANGED_POS) + { xassert(type == GLP_DB || type == GLP_FX); + slack[i-begin] = + temp - glp_get_row_lb(lp->prob, i+1); + } + else if (lp->rflag[i] == RF_RANGED_NEG) + { xassert(type == GLP_DB); + slack[i-begin] = + temp - glp_get_row_ub(lp->prob, i+1); + } + else + xassert(lp != lp); + } + } + } + else + xassert(lp != lp); +done: return errcode; +} + +int CPXgetstat(CPXENV *env, CPXLP *lp) +{ int stat; + if (checklp(env, lp)) + stat = 0; + else + stat = lp->stat; + return stat; +} + +int CPXgetub(CPXENV *env, CPXLP *lp, double ub[], int begin, int end) +{ xassert(env == env); + xassert(lp == lp); + xassert(ub == ub); + xassert(begin == begin); + xassert(end == end); + xprintf("CPXgetub: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetweight(CPXENV *env, CPXLP *lp, int rcnt, const int rmatbeg[], + const int rmatind[], const double rmatval[], double weight[], + int dpriind) +{ xassert(env == env); + xassert(lp == lp); + xassert(rcnt == rcnt); + xassert(rmatbeg == rmatbeg); + xassert(rmatind == rmatind); + xassert(rmatval == rmatval); + xassert(weight == weight); + xassert(dpriind == dpriind); + xprintf("CPXgetweight: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetx(CPXENV *env, CPXLP *lp, double x[], int begin, int end) +{ int j, n, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + n = glp_get_num_cols(lp->prob); + if (!(0 <= begin && begin <= end && end < n)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (x != NULL) + { for (j = begin; j <= end; j++) + x[j-begin] = glp_get_col_prim(lp->prob, j+1); + } + } + else + xassert(lp != lp); +done: return errcode; +} + +int CPXinfodblparam(CPXENV *env, int whichparam, double *defvalue, + double *minvalue, double *maxvalue) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = finddblparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + errcode = 0; + if (defvalue != NULL) + *defvalue = dblparam[k].defv; + if (minvalue != NULL) + *minvalue = dblparam[k].minv; + if (maxvalue != NULL) + *maxvalue = dblparam[k].maxv; +done: return errcode; +} + +int CPXinfointparam(CPXENV *env, int whichparam, int *defvalue, + int *minvalue, int *maxvalue) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = findintparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + errcode = 0; + if (defvalue != NULL) + *defvalue = intparam[k].defv; + if (minvalue != NULL) + *minvalue = intparam[k].minv; + if (maxvalue != NULL) + *maxvalue = intparam[k].maxv; +done: return errcode; +} + +int CPXmdleave(const CPXENV *env, CPXLP *lp, const int goodlist[], + int goodlen, double downratio[], double upratio[]) +{ int k; + xassert(env == env); + xassert(lp == lp); + xassert(goodlist == goodlist); + xassert(goodlen >= 0); + xassert(downratio != NULL); + xassert(upratio != NULL); + /* not implemented yet */ + for (k = 0; k < goodlen; k++) + downratio[k] = upratio[k] = 0.0; + return 0; +} + +int CPXnewcols(CPXENV *env, CPXLP *lp, int ccnt, const double obj[], + const double lb[], const double ub[], const char ctype[], + char *colname[]) +{ int j, n, kind, type, errcode; + double lbnd, ubnd; + errcode = checklp(env, lp); + if (errcode) goto done; + if (ccnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + for (j = 0; j < ccnt; j++) + { if (ctype != NULL) + { if (!(ctype[j] == 'C' || ctype[j] == 'B' || + ctype[j] == 'I')) + { errcode = error(env, CPXERR_BAD_CTYPE, j); + goto done; + } + } + if (colname != NULL) + { if (colname[j] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, j); + goto done; + } + } + } + errcode = 0; + invalidate(lp); + n = glp_get_num_cols(lp->prob); + if (ccnt > 0) + glp_add_cols(lp->prob, ccnt); + for (j = 0; j < ccnt; j++) + { if (colname != NULL) + glp_set_col_name(lp->prob, n+j+1, colname[j]); + if (obj != NULL) + glp_set_obj_coef(lp->prob, n+j+1, obj[j]); + lbnd = (lb == NULL ? 0.0 : lb[j]); + ubnd = (ub == NULL ? 0.0 : ub[j]); + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) + type = GLP_FR; + else if (ubnd >= +CPX_INFBOUND) + type = GLP_LO; + else if (lbnd <= -CPX_INFBOUND) + type = GLP_UP; + else if (lbnd != ubnd) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd); + if (ctype != NULL) + { if (ctype[j] == 'C') + kind = GLP_CV; + else if (ctype[j] == 'B') + kind = GLP_BV; + else if (ctype[j] == 'I') + kind = GLP_IV; + else + xassert(ctype != ctype); + glp_set_col_kind(lp->prob, n+j+1, kind); + } + } +done: return errcode; +} + +int CPXnewrows(CPXENV *env, CPXLP *lp, int rcnt, const double rhs[], + const char sense[], const double rngval[], char *rowname[]) +{ int i, m, type, errcode; + double lbnd, ubnd; + errcode = checklp(env, lp); + if (errcode) goto done; + if (rcnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + for (i = 0; i < rcnt; i++) + { if (sense != NULL) + { if (!(sense[i] == 'L' || sense[i] == 'E' || + sense[i] == 'G' || sense[i] == 'R')) + { errcode = error(env, CPXERR_BAD_SENSE, i); + goto done; + } + } + if (rowname != NULL) + { if (rowname[i] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, i); + goto done; + } + } + } + errcode = 0; + invalidate(lp); + m = glp_get_num_rows(lp->prob); + if (rcnt > 0) + glp_add_rows(lp->prob, rcnt); + enlargerflag(lp); + for (i = 0; i < rcnt; i++) + { if (rowname != NULL) + glp_set_row_name(lp->prob, m+i+1, rowname[i]); + lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]); + if (sense == NULL || sense[i] == 'E') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_FX; + } + else if (sense[i] == 'L') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_UP; + } + else if (sense[i] == 'G') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_LO; + } + else if (sense[i] == 'R') + { if (rngval == NULL || rngval[i] == 0.0) + { lp->rflag[m+i] = RF_RANGED_POS; + type = GLP_FX; + } + else if (rngval[i] > 0.0) + { lp->rflag[m+i] = RF_RANGED_POS; + type = GLP_DB; + ubnd += rngval[i]; + } + else /* rngval[i] < 0.0 */ + { lp->rflag[m+i] = RF_RANGED_NEG; + type = GLP_DB; + lbnd += rngval[i]; + } + } + else + xassert(sense != sense); + glp_set_row_bnds(lp->prob, m+i+1, type, lbnd, ubnd); + } +done: return errcode; +} + +CPXENV *CPXopenCPLEX(int *status) +{ CPXENV *env; + int k, card; + env = xmalloc(sizeof(CPXENV)); + env->list = NULL; + card = sizeof(intparam) / sizeof(struct intparam); + env->intparam = xcalloc(card, sizeof(int)); + for (k = 0; k < card; k++) + env->intparam[k] = intparam[k].defv; + card = sizeof(dblparam) / sizeof(struct dblparam); + env->dblparam = xcalloc(card, sizeof(double)); + for (k = 0; k < card; k++) + env->dblparam[k] = dblparam[k].defv; + if (status != NULL) *status = 0; + return env; +} + +int CPXpivotin(CPXENV *env, CPXLP *lp, const int rlist[], int rlen) +{ int i, m, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (rlen < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (rlen > 0 && rlist == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + m = glp_get_num_rows(lp->prob); + for (i = 0; i < rlen; i++) + { if (!(0 <= rlist[i] && rlist[i] < m)) + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i); + goto done; + } + } + errcode = 0; + for (i = 0; i < rlen; i++) + { if (glp_get_row_type(lp->prob, rlist[i]+1) != GLP_FX) + { if (glp_get_row_stat(lp->prob, rlist[i]+1) != GLP_BS) + { /* not implemented yet */ + break; + } + } + } +done: return errcode; +} + +int CPXpivotout(CPXENV *env, CPXLP *lp, const int clist[], int clen) +{ int j, n, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (clen < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (clen > 0 && clist == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + n = glp_get_num_cols(lp->prob); + for (j = 0; j < clen; j++) + { if (!(0 <= clist[j] && clist[j] < n)) + { errcode = error(env, CPXERR_COL_INDEX_RANGE, j); + goto done; + } + if (glp_get_col_type(lp->prob, clist[j]+1) != GLP_FX) + { errcode = error(env, CPXERR_NOT_FIXED); + goto done; + } + } + errcode = 0; + for (j = 0; j < clen; j++) + { if (glp_get_col_stat(lp->prob, clist[j]+1) == GLP_BS) + { /* not implemented yet */ + break; + } + } +done: return errcode; +} + +int CPXprimopt(CPXENV *env, CPXLP *lp); + +int CPXsavwrite(CPXENV *env, CPXLP *lp, const char *filename) +{ xassert(env == env); + xassert(lp == lp); + xassert(filename == filename); + xprintf("CPXsavwrite: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXsetdblparam(CPXENV *env, int whichparam, double newvalue) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = finddblparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + if (newvalue < dblparam[k].minv) + { errcode = error(env, CPXERR_PARAM_TOO_SMALL); + goto done; + } + if (newvalue > dblparam[k].maxv) + { errcode = error(env, CPXERR_PARAM_TOO_BIG); + goto done; + } + errcode = 0; + env->dblparam[k] = newvalue; +done: return errcode; +} + +int CPXsetintparam(CPXENV *env, int whichparam, int newvalue) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = findintparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + if (newvalue < intparam[k].minv) + { errcode = error(env, CPXERR_PARAM_TOO_SMALL); + goto done; + } + if (newvalue > intparam[k].maxv) + { errcode = error(env, CPXERR_PARAM_TOO_BIG); + goto done; + } + errcode = 0; + env->intparam[k] = newvalue; +done: return errcode; +} + +int CPXsolninfo(CPXENV *env, CPXLP *lp, int *solnmethod, int *solntype, + int *pfeasind, int *dfeasind) +{ int type, pfeas, dfeas, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + errcode = 0; + if (!lp->stat) + type = CPX_NO_SOLN, pfeas = dfeas = 0; + else if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { type = CPX_BASIC_SOLN; + pfeas = (glp_get_prim_stat(lp->prob) == GLP_FEAS); + dfeas = (glp_get_dual_stat(lp->prob) == GLP_FEAS); + } + else + xassert(lp != lp); + if (solnmethod != NULL) + *solnmethod = lp->meth; + if (solntype != NULL) + *solntype = type; + if (pfeasind != NULL) + *pfeasind = pfeas; + if (dfeasind != NULL) + *dfeasind = dfeas; +done: return errcode; +} + +int CPXsolution(CPXENV *env, CPXLP *lp, int *lpstat, double *objval, + double x[], double pi[], double slack[], double dj[]) +{ int m, n, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + m = glp_get_num_rows(lp->prob); + n = glp_get_num_cols(lp->prob); + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (lpstat != NULL) + *lpstat = CPXgetstat(env, lp); + if (objval != NULL) + xassert(CPXgetobjval(env, lp, objval) == 0); + if (x != NULL) + xassert(CPXgetx(env, lp, x, 0, n-1) == 0); + if (pi != NULL) + xassert(CPXgetpi(env, lp, pi, 0, m-1) == 0); + if (slack != NULL) + xassert(CPXgetslack(env, lp, slack, 0, m-1) == 0); + if (dj != NULL) + xassert(CPXgetdj(env, lp, dj, 0, n-1) == 0); + } + else + xassert(lp != lp); +done: return errcode; +} + +int CPXstrongbranch(CPXENV *env, CPXLP *lp, const int goodlist[], + int goodlen, double downpen[], double uppen[], int itlim) +{ int k; + xassert(env == env); + xassert(lp == lp); + xassert(goodlist == goodlist); + xassert(goodlen >= 0); + xassert(downpen != NULL); + xassert(uppen != NULL); + xassert(itlim == itlim); + /* not implemented yet */ + for (k = 0; k < goodlen; k++) + downpen[k] = uppen[k] = 0.0; + return 0; +} + +static int xstrcasecmp(const char *s1, const char *s2) +{ int c1, c2; + for (;;) + { c1 = toupper((unsigned char)*s1++); + c2 = toupper((unsigned char)*s2++); + if (c1 == '\0' || c1 != c2) break; + } + return c1 - c2; +} + +static void getfiletype(const char *filename, char type[3+1]) +{ /* determine filetype from filename */ + int beg, end; + beg = end = strlen(filename); + while (beg > 0 && filename[beg-1] != '.' && end - beg < 3) + beg--; + if (beg > 0 && filename[beg-1] == '.' && + xstrcasecmp(&filename[beg], "gz") == 0) + { end = --beg; + while (beg > 0 && filename[beg-1] != '.' && end - beg < 3) + beg--; + } + if (beg > 0 && filename[beg-1] == '.') + { memcpy(type, &filename[beg], end - beg); + type[end - beg] = '\0'; + } + else + type[0] = '\0'; + return; +} + +int CPXwriteprob(CPXENV *env, CPXLP *lp, const char *filename, + const char *filetype) +{ glp_prob *copy; + int errcode; + char type[3+1]; + errcode = checklp(env, lp); + if (errcode) goto done; + if (filename == NULL) + { errcode = error(env, CPXERR_NO_FILENAME); + goto done; + } + if (filetype == NULL) + getfiletype(filename, type), filetype = type; + if (xstrcasecmp(filetype, "MPS") == 0) + { glp_term_out(GLP_OFF); + errcode = glp_write_mps(lp->prob, GLP_MPS_FILE, NULL, filename) + ; + glp_term_out(GLP_ON); + } + else if (xstrcasecmp(filetype, "LP") == 0) + { glp_term_out(GLP_OFF); + errcode = glp_write_lp(lp->prob, NULL, filename); + glp_term_out(GLP_ON); + } + else if (xstrcasecmp(filetype, "RMP") == 0 || + xstrcasecmp(filetype, "REW") == 0) + { copy = glp_create_prob(); + glp_copy_prob(copy, lp->prob, GLP_OFF); + glp_term_out(GLP_OFF); + errcode = glp_write_mps(copy, GLP_MPS_DECK, NULL, filename); + glp_term_out(GLP_ON); + glp_delete_prob(copy); + } + else if (xstrcasecmp(filetype, "RLP") == 0) + { copy = glp_create_prob(); + glp_copy_prob(copy, lp->prob, GLP_OFF); + glp_term_out(GLP_OFF); + errcode = glp_write_lp(copy, NULL, filename); + glp_term_out(GLP_ON); + glp_delete_prob(copy); + } + else + { errcode = error(env, CPXERR_BAD_FILETYPE); + goto done; + } + if (errcode) + errcode = error(env, CPXERR_FAIL_OPEN_WRITE, filename); +done: return errcode; +} + +/**********************************************************************/ + +static int solvelp(CPXENV *env, CPXLP *lp, int meth) +{ glp_smcp parm; + int errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + errcode = 0; + invalidate(lp); + glp_init_smcp(&parm); + switch (meth) + { case CPX_ALG_PRIMAL: + parm.meth = GLP_PRIMAL; + break; + case CPX_ALG_DUAL: + parm.meth = GLP_DUAL; + break; + default: + xassert(meth != meth); + } + switch (getintparam(env, CPX_PARAM_SIMDISPLAY)) + { case 0: + parm.msg_lev = GLP_MSG_OFF; + break; + case 1: + parm.msg_lev = GLP_MSG_ALL; + break; + case 2: + parm.msg_lev = GLP_MSG_ALL; + parm.out_frq = 1; + break; + default: + xassert(env != env); + } + xassert(getdblparam == getdblparam); + switch (getintparam(env, CPX_PARAM_ADVIND)) + { case 0: + glp_term_out(GLP_OFF); + glp_adv_basis(lp->prob, 0); + glp_term_out(GLP_ON); + break; + case 1: + case 2: + break; + default: + xassert(env != env); + } + if (!glp_bf_exists(lp->prob)) + { if (glp_factorize(lp->prob) != 0) + { glp_term_out(GLP_OFF); + glp_adv_basis(lp->prob, 0); + glp_term_out(GLP_ON); + if (glp_factorize(lp->prob) != 0) + glp_std_basis(lp->prob); + } + } + xassert(glp_simplex(lp->prob, &parm) == 0); + switch (glp_get_status(lp->prob)) + { case GLP_OPT: + lp->stat = CPX_STAT_OPTIMAL; + lp->meth = meth; + break; + case GLP_NOFEAS: + lp->stat = CPX_STAT_INFEASIBLE; + lp->meth = meth; + break; + case GLP_UNBND: + lp->stat = CPX_STAT_UNBOUNDED; + lp->meth = meth; + break; + default: + xassert(lp != lp); + } +done: return errcode; +} + +int CPXprimopt(CPXENV *env, CPXLP *lp) +{ int errcode; + errcode = solvelp(env, lp, CPX_ALG_PRIMAL); + return errcode; +} + +int CPXdualopt(CPXENV *env, CPXLP *lp) +{ int errcode; + errcode = solvelp(env, lp, CPX_ALG_DUAL); + return errcode; +} + +int CPXlpopt(CPXENV *env, CPXLP *lp) +{ int errcode; + errcode = solvelp(env, lp, CPX_ALG_PRIMAL); + return errcode; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/cplex/cplex.h b/resources/3rdparty/glpk-4.53/examples/cplex/cplex.h new file mode 100644 index 000000000..94c3b204c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/cplex/cplex.h @@ -0,0 +1,301 @@ +/* cplex.h (CPLEX-like interface to GLPK API) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef _CPLEX_H +#define _CPLEX_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CPXENV CPXENV, *CPXENVptr; +typedef struct CPXLP CPXLP, *CPXLPptr; + +#define CPX_VERSION 900 + +#define CPX_OFF 0 +#define CPX_ON 1 + +#define CPX_INFBOUND 1e20 + +/* error codes: */ +#define CPXERR_NO_MEMORY 1001 +#define CPXERR_NO_ENVIRONMENT 1002 +#define CPXERR_BAD_ARGUMENT 1003 +#define CPXERR_NULL_POINTER 1004 +#define CPXERR_NO_PROBLEM 1009 +#define CPXERR_BAD_PARAM_NUM 1013 +#define CPXERR_PARAM_TOO_SMALL 1014 +#define CPXERR_PARAM_TOO_BIG 1015 +#define CPXERR_INDEX_RANGE 1200 +#define CPXERR_COL_INDEX_RANGE 1201 +#define CPXERR_ROW_INDEX_RANGE 1203 +#define CPXERR_NEGATIVE_SURPLUS 1207 +#define CPXERR_BAD_SENSE 1215 +#define CPXERR_NO_SOLN 1217 +#define CPXERR_NOT_FIXED 1221 +#define CPXERR_DUP_ENTRY 1222 +#define CPXERR_NULL_NAME 1224 +#define CPXERR_ARRAY_NOT_ASCENDING 1226 +#define CPXERR_COUNT_RANGE 1227 +#define CPXERR_BAD_LUB 1229 +#define CPXERR_BAD_STATUS 1253 +#define CPXERR_NO_BASIC_SOLN 1261 +#define CPXERR_NO_FILENAME 1421 +#define CPXERR_FAIL_OPEN_WRITE 1422 +#define CPXERR_BAD_FILETYPE 1424 +#define CPXERR_BAD_CTYPE 3021 + +/* control parameters: */ +#define CPX_PARAM_ADVIND 1001 +#define CPX_PARAM_AGGIND 1003 +#define CPX_PARAM_DPRIIND 1009 +#define CPX_PARAM_EPOPT 1014 +#define CPX_PARAM_EPPER 1015 +#define CPX_PARAM_EPRHS 1016 +#define CPX_PARAM_FASTMIP 1017 /* ??? */ +#define CPX_PARAM_SIMDISPLAY 1019 +#define CPX_PARAM_ITLIM 1020 +#define CPX_PARAM_OBJLLIM 1025 +#define CPX_PARAM_OBJULIM 1026 +#define CPX_PARAM_PERIND 1027 +#define CPX_PARAM_PPRIIND 1029 +#define CPX_PARAM_PREIND 1030 +#define CPX_PARAM_REINV 1031 +#define CPX_PARAM_SCRIND 1035 +#define CPX_PARAM_DATACHECK 1056 + +/* CPX_PARAM_DPRIIND: */ +#define CPX_DPRIIND_AUTO 0 +#define CPX_DPRIIND_FULL 1 +#define CPX_DPRIIND_STEEP 2 +#define CPX_DPRIIND_FULL_STEEP 3 +#define CPX_DPRIIND_STEEPQSTART 4 +#define CPX_DPRIIND_DEVEX 5 + +/* CPX_PARAM_PPRIIND: */ +#define CPX_PPRIIND_PARTIAL (-1) +#define CPX_PPRIIND_AUTO 0 +#define CPX_PPRIIND_DEVEX 1 +#define CPX_PPRIIND_STEEP 2 +#define CPX_PPRIIND_STEEPQSTART 3 +#define CPX_PPRIIND_FULL 4 + +/* CPXgetprobtype: */ +#define CPXPROB_LP 0 +#define CPXPROB_MIP 1 +#define CPXPROB_RELAXED 2 +#define CPXPROB_FIXED 3 +#define CPXPROB_QP 5 +#define CPXPROB_ZEROEDQP 6 + +/* CPXgetobjsen: */ +#define CPX_MIN 1 +#define CPX_MAX (-1) + +/* CPXgetbase: */ +#define CPX_AT_LOWER 0 +#define CPX_BASIC 1 +#define CPX_AT_UPPER 2 +#define CPX_FREE_SUPER 3 + +/* CPXgetstat: */ +#define CPX_STAT_OPTIMAL 1 +#define CPX_STAT_UNBOUNDED 2 +#define CPX_STAT_INFEASIBLE 3 +#define CPX_STAT_INForUNBD 4 +#define CPX_STAT_OPTIMAL_INFEAS 5 +#define CPX_STAT_ABORT_IT_LIM 10 +#define CPX_STAT_ABORT_OBJ_LIM 12 + +/* CPXgetmethod: */ +#define CPX_ALG_NONE 0 +#define CPX_ALG_PRIMAL 1 +#define CPX_ALG_DUAL 2 +#define CPX_ALG_BARRIER 4 + +/* CPXsolninfo: */ +#define CPX_NO_SOLN 0 +#define CPX_BASIC_SOLN 1 +#define CPX_NONBASIC_SOLN 2 +#define CPX_PRIMAL_SOLN 3 + +int CPXaddcols(CPXENV *env, CPXLP *lp, int ccnt, int nzcnt, + const double obj[], const int cmatbeg[], const int cmatind[], + const double cmatval[], const double lb[], const double ub[], + char *colname[]); + +int CPXaddrows(CPXENV *env, CPXLP *lp, int ccnt, int rcnt, int nzcnt, + const double rhs[], const char sense[], const int rmatbeg[], + const int rmatind[], const double rmatval[], char *colname[], + char *rowname[]); + +int CPXbaropt(CPXENV *env, CPXLP *lp); + +int CPXbinvrow(CPXENV *env, CPXLP *lp, int i, double y[]); + +int CPXchgbds(CPXENV *env, CPXLP *lp, int cnt, const int indices[], + const char lu[], const double bd[]); + +int CPXchgcoeflist(CPXENV *env, CPXLP *lp, int numcoefs, + const int rowlist[], const int collist[], const double vallist[]); + +void CPXchgobjsen(CPXENV *env, CPXLP *lp, int maxormin); + +int CPXchgsense(CPXENV *env, CPXLP *lp, int cnt, const int indices[], + const char sense[]); + +int CPXcloseCPLEX(CPXENV **env); + +int CPXcopybase(CPXENV *env, CPXLP *lp, const int cstat[], + const int rstat[]); + +int CPXcopybasednorms(CPXENV *env, CPXLP *lp, const int cstat[], + const int rstat[], const double dnorm[]); + +int CPXcopylp(CPXENV *env, CPXLP *lp, int numcols, int numrows, + int objsen, const double obj[], const double rhs[], + const char sense[], const int matbeg[], const int matcnt[], + const int matind[], const double matval[], const double lb[], + const double ub[], const double rngval[]); + +int CPXcopylpwnames(CPXENV *env, CPXLP *lp, int numcols, int numrows, + int objsen, const double obj[], const double rhs[], + const char sense[], const int matbeg[], const int matcnt[], + const int matind[], const double matval[], const double lb[], + const double ub[], const double rngval[], char *colname[], + char *rowname[]); + +CPXLP *CPXcreateprob(CPXENV *env, int *status, const char *probname); + +int CPXdelcols(CPXENV *env, CPXLP *lp, int begin, int end); + +int CPXdelrows(CPXENV *env, CPXLP *lp, int begin, int end); + +int CPXdelsetcols(CPXENV *env, CPXLP *lp, int delstat[]); + +int CPXdelsetrows(CPXENV *env, CPXLP *lp, int delstat[]); + +int CPXdualopt(CPXENV *env, CPXLP *lp); + +int CPXfreeprob(CPXENV *env, CPXLP **lp); + +int CPXgetbase(CPXENV *env, CPXLP *lp, int cstat[], int rstat[]); + +int CPXgetbasednorms(CPXENV *env, CPXLP *lp, int cstat[], int rstat[], + double dnorm[]); + +int CPXgetbhead(CPXENV *env, CPXLP *lp, int head[], double x[]); + +int CPXgetdblparam(CPXENV *env, int whichparam, double *value); + +int CPXgetdj(CPXENV *env, CPXLP *lp, double dj[], int begin, int end); + +char *CPXgeterrorstring(CPXENV *env, int errcode, char *buffer); + +int CPXgetijdiv(CPXENV *env, CPXLP *lp, int *idiv, int *jdiv); + +int CPXgetintparam(CPXENV *env, int whichparam, int *value); + +int CPXgetlb(CPXENV *env, CPXLP *lp, double lb[], int begin, int end); + +int CPXgetmethod(CPXENV *env, CPXLP *lp); + +int CPXgetnumcols(CPXENV *env, CPXLP *lp); + +int CPXgetnumnz(CPXENV *env, CPXLP *lp); + +int CPXgetnumrows(CPXENV *env, CPXLP *lp); + +int CPXgetobjval(CPXENV *env, CPXLP *lp, double *objval); + +int CPXgetpi(CPXENV *env, CPXLP *lp, double pi[], int begin, int end); + +int CPXgetsense(CPXENV *env, CPXLP *lp, char sense[], int begin, + int end); + +int CPXgetslack(CPXENV *env, CPXLP *lp, double slack[], int begin, + int end); + +int CPXgetstat(CPXENV *env, CPXLP *lp); + +int CPXgetub(CPXENV *env, CPXLP *lp, double ub[], int begin, int end); + +int CPXgetweight(CPXENV *env, CPXLP *lp, int rcnt, const int rmatbeg[], + const int rmatind[], const double rmatval[], double weight[], + int dpriind); + +int CPXgetx(CPXENV *env, CPXLP *lp, double x[], int begin, int end); + +int CPXinfodblparam(CPXENV *env, int whichparam, double *defvalue, + double *minvalue, double *maxvalue); + +int CPXinfointparam(CPXENV *env, int whichparam, int *defvalue, + int *minvalue, int *maxvalue); + +int CPXlpopt(CPXENV *env, CPXLP *lp); + +int CPXmdleave(const CPXENV *env, CPXLP *lp, const int goodlist[], + int goodlen, double downratio[], double upratio[]); + +int CPXnewcols(CPXENV *env, CPXLP *lp, int ccnt, const double obj[], + const double lb[], const double ub[], const char ctype[], + char *colname[]); + +int CPXnewrows(CPXENV *env, CPXLP *lp, int rcnt, const double rhs[], + const char sense[], const double rngval[], char *rowname[]); + +CPXENV *CPXopenCPLEX(int *status); + +int CPXpivotin(CPXENV *env, CPXLP *lp, const int rlist[], int rlen); + +int CPXpivotout(CPXENV *env, CPXLP *lp, const int clist[], int clen); + +int CPXprimopt(CPXENV *env, CPXLP *lp); + +int CPXsavwrite(CPXENV *env, CPXLP *lp, const char *filename); + +int CPXsetdblparam(CPXENV *env, int whichparam, double newvalue); + +int CPXsetintparam(CPXENV *env, int whichparam, int newvalue); + +int CPXsolninfo(CPXENV *env, CPXLP *lp, int *solnmethod, int *solntype, + int *pfeasind, int *dfeasind); + +int CPXsolution(CPXENV *env, CPXLP *lp, int *lpstat, double *objval, + double x[], double pi[], double slack[], double dj[]); + +int CPXstrongbranch(CPXENV *env, CPXLP *lp, const int goodlist[], + int goodlen, double downpen[], double uppen[], int itlim); + +int CPXwriteprob(CPXENV *env, CPXLP *lp, const char *filename, + const char *filetype); + +#ifdef __cplusplus +} +#endif + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/cpp.mod b/resources/3rdparty/glpk-4.53/examples/cpp.mod new file mode 100644 index 000000000..af3f1208b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/cpp.mod @@ -0,0 +1,67 @@ +/* CPP, Critical Path Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* Note: Reduced costs of auxiliary variables phi[j,k] (see below) + can be only zero or one. The critical path is defined by the + constraints, whose reduced cost is one. */ + +set J; +/* set of jobs (activities) */ + +set P{j in J}, in J, default {}; +/* P[j] is a subset of jobs that immediately precede job j */ + +param t{j in J}, >= 0; +/* duration required to perform job j */ + +var x{j in J}, >= 0; +/* starting time of job j */ + +s.t. phi{j in J, k in P[j]}: x[j] >= x[k] + t[k]; +/* job j can start only after all immediately preceding jobs have been + completely performed */ + +var z; +/* project makespan */ + +s.t. fin{j in J}: z >= x[j] + t[j]; +/* which is the maximum of the completion times of all the jobs */ + +minimize obj: z; +/* the objective is make z as small as possible */ + +data; + +/* The optimal solution is 46 */ + +param : J : t := + A 3 /* Excavate */ + B 4 /* Lay foundation */ + C 3 /* Rough plumbing */ + D 10 /* Frame */ + E 8 /* Finish exterior */ + F 4 /* Install HVAC */ + G 6 /* Rough electric */ + H 8 /* Sheet rock */ + I 5 /* Install cabinets */ + J 5 /* Paint */ + K 4 /* Final plumbing */ + L 2 /* Final electric */ + M 4 /* Install flooring */ +; + +set P[B] := A; +set P[C] := B; +set P[D] := B; +set P[E] := D; +set P[F] := D; +set P[G] := D; +set P[H] := C E F G; +set P[I] := H; +set P[J] := H; +set P[K] := I; +set P[L] := J; +set P[M] := K L; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/crypto.mod b/resources/3rdparty/glpk-4.53/examples/crypto.mod new file mode 100644 index 000000000..bad50325f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/crypto.mod @@ -0,0 +1,84 @@ +/* CRYPTO, a crypto-arithmetic puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* This problem comes from the newsgroup rec.puzzle. + The numbers from 1 to 26 are assigned to the letters of the alphabet. + The numbers beside each word are the total of the values assigned to + the letters in the word (e.g. for LYRE: L, Y, R, E might be to equal + 5, 9, 20 and 13, or any other combination that add up to 47). + Find the value of each letter under the equations: + + BALLET 45 GLEE 66 POLKA 59 SONG 61 + CELLO 43 JAZZ 58 QUARTET 50 SOPRANO 82 + CONCERT 74 LYRE 47 SAXOPHONE 134 THEME 72 + FLUTE 30 OBOE 53 SCALE 51 VIOLIN 100 + FUGUE 50 OPERA 65 SOLO 37 WALTZ 34 + + Solution: + A, B,C, D, E,F, G, H, I, J, K,L,M, N, O, P,Q, R, S,T,U, V,W, X, Y, Z + 5,13,9,16,20,4,24,21,25,17,23,2,8,12,10,19,7,11,15,3,1,26,6,22,14,18 + + Reference: + Koalog Constraint Solver <http://www.koalog.com/php/jcs.php>, + Simple problems, the crypto-arithmetic puzzle ALPHACIPHER. */ + +set LETTERS := +{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' +}; +/* set of letters */ + +set VALUES := 1..card(LETTERS); +/* set of values assigned to the letters */ + +set WORDS; +/* set of words */ + +param total{word in WORDS}; +/* total[word] is the total of the values assigned to the letters in + the word */ + +var x{i in LETTERS, j in VALUES}, binary; +/* x[i,j] = 1 means that letter i is assigned value j */ + +s.t. phi{i in LETTERS}: sum{j in VALUES} x[i,j] = 1; + +s.t. psi{j in VALUES}: sum{i in LETTERS} x[i,j] = 1; + +s.t. eqn{word in WORDS}: sum{k in 1..length(word), j in VALUES} + j * x[substr(word,k,1), j] = total[word]; + +solve; + +printf{i in LETTERS} " %s", i; +printf "\n"; + +printf{i in LETTERS} " %2d", sum{j in VALUES} j * x[i,j]; +printf "\n"; + +data; + +param : WORDS : total := + BALLET 45 + CELLO 43 + CONCERT 74 + FLUTE 30 + FUGUE 50 + GLEE 66 + JAZZ 58 + LYRE 47 + OBOE 53 + OPERA 65 + POLKA 59 + QUARTET 50 + SAXOPHONE 134 + SCALE 51 + SOLO 37 + SONG 61 + SOPRANO 82 + THEME 72 + VIOLIN 100 + WALTZ 34 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/csv/distances.csv b/resources/3rdparty/glpk-4.53/examples/csv/distances.csv new file mode 100644 index 000000000..8c7b419de --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/csv/distances.csv @@ -0,0 +1,7 @@ +plant,market,distance +"Seattle","New York",2.5 +"Seattle","Chicago",1.7 +"Seattle","Topeka",1.8 +"San Diego","New York",2.5 +"San Diego","Chicago",1.8 +"San Diego","Topeka",1.4 diff --git a/resources/3rdparty/glpk-4.53/examples/csv/markets.csv b/resources/3rdparty/glpk-4.53/examples/csv/markets.csv new file mode 100644 index 000000000..d04dec82c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/csv/markets.csv @@ -0,0 +1,4 @@ +market,demand +"New York",325. +"Chicago",300. +"Topeka",275. diff --git a/resources/3rdparty/glpk-4.53/examples/csv/parameters.csv b/resources/3rdparty/glpk-4.53/examples/csv/parameters.csv new file mode 100644 index 000000000..c7c37e9af --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/csv/parameters.csv @@ -0,0 +1,2 @@ +parameter,value +"transport cost",90. diff --git a/resources/3rdparty/glpk-4.53/examples/csv/plants.csv b/resources/3rdparty/glpk-4.53/examples/csv/plants.csv new file mode 100644 index 000000000..292f45f12 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/csv/plants.csv @@ -0,0 +1,3 @@ +plant,capacity +"Seattle",350. +"San Diego",600. diff --git a/resources/3rdparty/glpk-4.53/examples/csv/transp_csv.mod b/resources/3rdparty/glpk-4.53/examples/csv/transp_csv.mod new file mode 100644 index 000000000..d970bf61b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/csv/transp_csv.mod @@ -0,0 +1,70 @@ +# A TRANSPORTATION PROBLEM +# +# This problem finds a least cost shipping schedule that meets +# requirements at markets and supplies at factories. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* canning plants */ + +set J; +/* markets */ + +set K dimen 2; +/* transportation lane */ + +set L; +/* parameters */ + +param a{i in I}; +/* capacity of plant i in cases */ + +param b{j in J}; +/* demand at market j in cases */ + +param d{i in I, j in J}; +/* distance in thousands of miles */ + +param e{l in L}; +/* parameters */ + +param f; +/* freight in dollars per case per thousand miles */ + +table tab_plant IN "CSV" "plants.csv" : + I <- [plant], a ~ capacity; + +table tab_market IN "CSV" "markets.csv" : + J <- [market], b ~ demand; + +table tab_distance IN "CSV" "distances.csv" : + K <- [plant, market], d ~ distance; + +table tab_parameter IN "CSV" "parameters.csv" : + L <- [parameter], e ~ value ; + +param c{i in I, j in J} := e['transport cost'] * d[i,j] / 1000; +/* transport cost in thousands of dollars per case */ + +var x{(i,j) in K} >= 0; +/* shipment quantities in cases */ + +minimize cost: sum{(i,j) in K} c[i,j] * x[i,j]; +/* total transportation costs in thousands of dollars */ + +s.t. supply{i in I}: sum{(i,j) in K} x[i,j] <= a[i]; +/* observe supply limit at plant i */ + +s.t. demand{j in J}: sum{(i,j) in K} x[i,j] >= b[j]; +/* satisfy demand at market j */ + +solve; + +table tab_result{(i,j) in K} OUT "CSV" "result.csv" : + i ~ plant, j ~ market, x[i,j] ~ shipment; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod b/resources/3rdparty/glpk-4.53/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod new file mode 100644 index 000000000..204846763 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod @@ -0,0 +1,226 @@ +# Model I Forest Estate Modelling using GLPK/MathProg +# Reading and writing dbf files + +# by Noli Sicad --- nsicad@gmail.com +# 18 December 2009 + +# Forest Management 4th Edition +# by Lawrence Davis, K. Norman Johnson, Pete Bettinger, Theodore Howard +# Chapter 11 - Daniel Pickett +# http://warnell.forestry.uga.edu/Warnell/Bettinger/mgtbook/index.htm + +# Model I Formulation + +/* Note: This is not the full LP model mentioned in the book. +Some of the constraints are deliberately omitted in this model for the purpose of clarity. + +The features of MathProg in this example are: +* reading and writing dbf from regular dbf files, +* reading dbf file (database of shapefile (stands.shp)) (e.g. area parameter), +* using the area data in the constraints and +* writing dbf file from result of LP model. + +Model I - Harvest Scheduling formulation for Sustainable Forest Management (SFM) + +Features are: +* Net Present Value for the objective function (Revenue - Cost) +* Harvest Constraints by period - Sustainable Yield per Period +* Even-Flow Constraint / Volume - Harvest Flow Constraint - Alpha (1-Apha) +* Even-Flow Constraint / Volume - Harvest Flow Constraint - Beta (1 +Beta) +* Forest / Land Constraint -- Total Area of the forest +* Forest Stand Constraint -- Individual stands + +What is next? -- Forest Mgt Carbon Accounting for Climate Change + +Note: The model file that the data containing in +the dbf files is public domain material (so it is compatible with the +GNU GPL) and data can be found in +http://warnell.forestry.uga.edu/Warnell/Bettinger/mgtbook/index.htm + +# Noli Sicad --- nsicad@gmail.com + +*/ + +set G_STAND_TYPE; # A, B, C + +set I_CULTURAL_PRES; +set J_MGT_YEAR; + +param K_PERIOD; +param Forest_Cost{G_STAND_TYPE,I_CULTURAL_PRES, J_MGT_YEAR}; # cost + +param Yield_Table_Vol{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD} >= 0; + + +param Alpha >= 0; +param Beta >= 0; + +param TCost_Table{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD} >= 0; + +param NetRev_Table{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD}; + + +var XForestLand{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} >= 0; + + +#reading dbf tables +table tab IN "xBASE" "standtype.dbf": G_STAND_TYPE <- [STAND]; +display G_STAND_TYPE; + + +table tab2 IN "xBASE" "cultural_pres.dbf": I_CULTURAL_PRES <- [CUL_PRES]; +display I_CULTURAL_PRES; + +table tab3 IN "xBASE" "mgt_year.dbf": J_MGT_YEAR <- [MGT_YEAR]; +display J_MGT_YEAR; + +/* +param Forest_Cost{G_STAND_TYPE,I_CULTURAL_PRES, J_MGT_YEAR} default 0; # cost +*/ + +set S1, dimen 3; +table tab4 IN "xBASE" "Forest_Cost.dbf": S1 <- [STAND, CUL_PRES, MGT_YEAR],Forest_Cost ~FCOST; +display Forest_Cost; + +set S2, dimen 4; +table tab5 IN "xBASE" "Yield_Table_Vol.dbf": S2 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],Yield_Table_Vol ~YIELD; +display Yield_Table_Vol; + +set S3, dimen 4; +table tab5 IN "xBASE" "TCost_Table.dbf": S3 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],TCost_Table ~TCOST; +display TCost_Table; + + +set S4, dimen 4; +table tab5 IN "xBASE" "NetRev_Table.dbf": S4 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],NetRev_Table ~NETREV; +display NetRev_Table; + + +param MGT; + +param Area_Stand_Indi{g in G_STAND_TYPE, m in 1..MGT} default 0; + +set ST, dimen 2; +table tab5 IN "xBASE" "stands.dbf": ST <- [VEG_TYPE, MGT], Area_Stand_Indi ~ACRES; +display Area_Stand_Indi; + +param Area_Stand_Type{g in G_STAND_TYPE}:= sum {m in 1..MGT } Area_Stand_Indi[g,m]; +display Area_Stand_Type; + + +param Total_Area := sum {g in G_STAND_TYPE, m in 1..MGT } Area_Stand_Indi[g,m]; +display Total_Area; + +param Harvest_Min_Vol_Period; + + +var NetPresentValue; + +# Objective function +maximize Net_Present_Value: NetPresentValue; + +subject to NPV: + NetPresentValue = sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Forest_Cost[g,i,j] * XForestLand[g,i,j]; + +# Harvest Constraint by Period +subject to Harvest_Period_H {k in 1..K_PERIOD}: + sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] >= Harvest_Min_Vol_Period; + + +#Even-Flow Constraint / Volume - Harvest Flow Constraint - Alpha +subject to Even_Flow_Constaints_Alpha {k in 6..K_PERIOD-1}: + (1 - Alpha) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] - + sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j] <= 0; + +# Even-Flow Constraint / Volume - Harvest Flow Constraint - Beta +subject to Even_Flow_Constaints_Beta {k in 6..K_PERIOD-1}: + (1 + Beta) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] - + sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j] >= 0; + +# Forest / Land Constraints +subject to Total_Area_Constraint: + sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} XForestLand[g,i,j] <= Total_Area; +display Total_Area; + +# Forest / Land Constraints for A B C +subject to Area {g in G_STAND_TYPE}: + sum {i in I_CULTURAL_PRES,j in J_MGT_YEAR} XForestLand[g,i,j] = Area_Stand_Type[g]; + + + +solve; +#RESULT SECTION +printf '#################################\n'; +printf 'Forest Management Model I - Noli Sicad\n'; +printf '\n'; +printf 'Net Present Value = %.2f\n', NetPresentValue; +printf '\n'; + +printf '\n'; +printf 'Variables\n'; +printf 'Stand_Type Age_Class Mgt_Presc Sign Value \n'; +printf{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR}:'%5s %10s %11s = %10.2f\n', g,i,j, XForestLand[g,i,j]; +printf '\n'; + +printf 'Constraints\n'; +printf 'Period Harvest Sign \n'; +for {k in 1..K_PERIOD} { + printf '%5s %10.2f >= %.3f\n', k, sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j], Harvest_Min_Vol_Period; + } + +# xbase (dbf) output +table Harvest{k in 1..K_PERIOD} OUT "xBASE" "HarvestArea1.dbf" "N(5)N(15,2)" : k ~ Period, (sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j]) ~ H_Area; + +# xbase (dbf) read +set S, dimen 2; +table tab2 IN "xBASE" "HarvestArea1.dbf": S <- [Period, H_Area]; +display S; + + + + +printf '\n'; +printf 'Constraint\n'; +printf 'Harvest Period\n'; +printf 'Type AgeClass PrescMgt Period Value\n'; +printf{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR, k in 1..K_PERIOD}:'%5s %11s %11s %5s %10.2f\n', g,i,j, k, (Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j]); + + +printf 'Even_Flow_Constaint_Alpha (1-Alpha)\n'; +printf 'Period Sign \n'; +for {k in 6..K_PERIOD-1} { + printf "%s %10.2f <= %s\n", k, ((1 - Alpha) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] - sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j]),0; + } +printf '\n'; + + +# Forest / Land Constraints +printf '\n'; +printf 'Total Area Constraint\n'; +printf 'Type AgeClass PrescMgt Value Sign Total_Area \n'; +printf '%5s <= %.3f\n',sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} XForestLand[g,i,j], Total_Area; + +printf 'Area\n'; +printf 'Area Value Sign Areas_Stand\n'; +for {g in G_STAND_TYPE} { + printf '%5s %10.2f <= %.3f\n', g, sum {i in I_CULTURAL_PRES,j in J_MGT_YEAR} XForestLand[g,i,j], Area_Stand_Type[g]; + } + + +#DATA SECTION + +data; + +# Most of the data has been moved to dbf format + +param MGT:=31; + +param K_PERIOD:= 7; + +param Alpha:= 0.20; +param Beta:= 0.20; + +param Harvest_Min_Vol_Period:= 12000; + +end; + diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/Forest_Cost.dbf b/resources/3rdparty/glpk-4.53/examples/dbf/Forest_Cost.dbf new file mode 100644 index 0000000000000000000000000000000000000000..acb8dcb19300f8c5d1b4a5e7a63db53daadf93d1 GIT binary patch literal 1458 zcmaKrF;9gs6oq*j7Zc;|#Neud(o#AizUQJ(^T5H0(aFTYKjc3ZS|FUmwH+XoueV?C zf%C&|cbg>1Z!%uDqwVVBW0-En+XW%b`*Z(x+PA~>QF{OK)b$_x`ZT=r>n~~jp?Ph) zFz44_pCNFS*6B3zug{<UJD(rNyVEYe&oXAznkh|I2~4qOv@uFx^qML1G6O~lK1FT? zhJ3UW81k{wUf`o#X`qhV`lNRj`x6-O8P14%1qOWnVZdi*9_FSAd8L)sqcbt+qpj~D zG3cWzpD8iuGv&1~LS7r^z@X36AF6{sGJ`(Mh<Rx|dnB*LCz2O2qE8dc%PRkE5QF`( x#(#&zV1LTW|6jzQk5O1BlGjovk{2=PGi5;x`Y;p8YpD~-i<r1is3ZB@`~gT(_%i?i literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/NetRev_Table.dbf b/resources/3rdparty/glpk-4.53/examples/dbf/NetRev_Table.dbf new file mode 100644 index 0000000000000000000000000000000000000000..6e6f2bd3a98b3b9aa7c7be9f66286b64f9dac08f GIT binary patch literal 11786 zcmb7}!EW0|5Qd!uy%Y#~?};xEL$syXK02;i1W4S#aRc<^V^0No=nM9}dWgvN&OiTh zcK@*s5=Q%RIP-D2B&9dMzIyfl+1c5DXXmH)?d$8~?foz1>$~OShX%R(<I~fZhvV1N z*Z0x*=ieTm{yg43oW|Dee{8n@a(wvsd)dLdeLH@Ce0(^5TQ^$Ae|pUc-cGmE^K1V5 zuYaHZnQORyT6A-BwL9PK#`J}4`|eWHmoK9CmEP|zbnZi?r%Wa9UqoM3x>E@(ET9?e zRKj$P=G`ImUB^oa${^EbFja{e-0!X<-<(?+WZDdNDnVZvgG^&j@sVe`M)MrcsybeL zD}zj%!Bm%KursSTw=#%IGX|Mf2AM`(v2UhpG|&5Re%JBhTNz~940e1oZ3Z{KFJ80` zMs(j`ME4Cwv~`iHyKgYc-8UG~${;L^=U~arbd9#_U_>i}HJdt%quge2vkpeIGRT#f z!Oe^<xzSg~Ak)}WdtOGl>$cl<FrsY^rs_6>DcTHn=69{M97|;om1Ybwtqd}ax?<l< z*J!&A7T<Nebg2w7Z3a8OnKpwP-#4RmaFaWt`vxPrZ!n_KMe94F`vxPrZ!n_GV8;n8 z@En{bzOO2|nf8&UVK9>$1~W7aW@s49&@dR&zAt}AouQRM&h4Yfw;!J-WsqrQkZEO* zX=Tt?stq!&3^MKOiVQOCBTXxVKHD@YgG_G>ekg12$<}ZkJd~%SAq|7?%CqZ`hQSPN zUCh^s+%TBQ4TBll40bAk1zrc^+)N`n91hFx5RE~MFS(ULrp@4#sl*J<b9m%Aw=&4I z8SGSozA^@x#-8FXnMQQjMZPh<RH6(rZ3a_an!%25&aDih(u_f-l|iOaSL~Z<L>XEc zM7E_%GuZLXbl+gPGsW*&Z1DM7Z0BV}!(fJn!3^!YSg$0*N?<UP8wN8p492v#5L}C! zx|#M-)TJNy>tLo5Wsq|#gG?)fOe=$aW@v*<`#nVlnf8&Ul|i3vnv_ANl|iPJL0_ph z$h0!Zw67~N$h40%tql5XejSX@2B!N4qh~;@itYLx(J+{yVK76Ziwq5e85(miL&IQ9 z!@~GVl6o$-RWqVtus!k-4TBjP1~W7aW@s3UY2VlAEG}I#?d|iK7SVoNO)G;w+h`q( zDp3YGw=(D})drbX2ATGCMFyGnk*3ug^w~!1VDZiL#^Bv@wl1&nbMe0X13aW*@Ogz8 z(lD5z(M5(fgY_w6SPAA}Cbt>v<c5XS>gslRi*qw=(dmzp^*ODn+s4<d${^FqAk)eq z(=a%dUoD1po53lj(bv-E=33n3W*T+HzL~b@;_4>yZR4wN7|hgd22)+aV5V*ujA>VC z!XVSiAk#3Esl>LOuisytA9ho7ENy)C4TG87${^?N8;qWGF$bTo+*Wr)!(fJn!3^!Y zSg$0*N?<UP8wN8p492v#;LqX=?YE7(^y9&EapQz(WsqrQkZEO*X=TvQ3~i8Uzo*C` z(>~I)GU&4f_k+#RVOkkvS{d|}YJ*HGgG~FnB7;o(NYiQ#`fS1dVB?$VzQJ<$=vO{( zuw9WO8U`~o3}$F_k)dHQLt_qRXc&xXSXeG<-X|aVVvuPcX&MIGH8#o(gBcnIGc*il zXc&xX-<LMXv@*!Fk0RfG-2YFKsaqN3+{z%+%Ah~i+91=)Ak)6C$RN``(zG(@vyIll LayBsC8vOY?BOBCW literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/README b/resources/3rdparty/glpk-4.53/examples/dbf/README new file mode 100644 index 000000000..bbe9c3e71 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/dbf/README @@ -0,0 +1,2 @@ +This subdirectory contains an example MathProg model that demonstrates +using data tables in DBF format. diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/TCost_Table.dbf b/resources/3rdparty/glpk-4.53/examples/dbf/TCost_Table.dbf new file mode 100644 index 0000000000000000000000000000000000000000..9a462c37aee15b20e48e56f761751805fa1f0fff GIT binary patch literal 11786 zcmb7|v2GPH5JeLZ4HBZK+AlyaFE1o1LkI{70!l(bm68gHf*<6+D0s2i*?Ya$zLON7 ziO<f?ob`I`Jbiz7`1j!8;LpM9{lDv<+q;YFclFno5C1)DkjrnM?!Vq#-R^&Vt;Rop zxV!&;b#b#FE7w17uK#*<^YKf)LAkyizq|Z$dsnY1<1e3Zf)~@p^#AAR=a1j_zmDdx z{2$S7bG&)I*^KG!a&3Y>eiXf%>Fw^!S8_7b)0C*>&7<hkneJ2q7WQNq>{P;ZM7yo5 zJH|^5&LGoaFjYwyOm*oDawTD~Qwj8yFvv9ANg8B2qTR8aRWV+CJA+Jz!Bm%Fu;ZI^ zJA+VZ!XVSmAk$En^v!fcyORX%3`Vx{bi!cAH`8Ho<$L?6bx_fLgNj}Zwkw;Wp^L_# zqQhXS%P^Rt!{DUr1`ESESnFmwqSZR6=*3{W+ADf7n5jDqu4a|W9R^eMVo=u&eI*Ps z9R@p<Fdflq9jsl(czM$ngPFP)gW5Oeb_SUagPj=*l_m@_?F=#vb;<XV>4;YAVD%m2 z#rI-R`(}DEsC_dX23Pase6$Xx=)OUfyKhj@&_&~0(S3u8UJSOr73~ay1)hTw?_+Cj zrZMs~7);~_g9#c8CTK92puwP|u`k+DCunDob7Q1@<M=c=gG@VvOgn>2JA+uMH^{Uz z$TZfa3^I+8r=3B}HcieT(<_5-%hLPs#*Ws(<4rv`3~4a9EnN<2FqojDi=(py4F(f5 z7);P%uu}<G;B`>uW;&wn`R?T5?+}f_7%vaa8Du&PPE(?iFqrDn8RSaBV5bu3D`Ajn zxRdOX>4>(c=gN1C7vIhx(_t{xWf<)E=G@L8RGKizv@^&w)Fpj09ntpWRILy(UVJ-) zOozdaZ>GcG%6HwF!r!ylVEq=yd#PwJn4rO6g2pb`psEB6CUS$p1RVzVepDrBL41oF zgG^)Ob322WP3&fdl{kZ(+Zklq8N|N4L8kFe${^DidD_iE%r;HVAk)qu)6O7P>J2jO z3^I*%DT7R7<Y{LRvx)s+GryVc8&qdNSQVSqUeRDML4&~r4P7K?FqoiW4kl<YC~2@T z{F0>3#qlf^4F;PPS<zrHL4&~r4F(f57?d>jHF}F{mrSF5e$y0<*LvC+#B8H=P*vg# za&Bi3EA<AMb_SWox|BhtG4iyVgP3i!4p!exuMA$6E$G7=J31F1ZR$RDNQ1$;LJVmz zn4qJJc^^B>4F(grVGbtfFxaUCEbuxgb2A;$d@gRfjPdf&oI$3;;CyZv<_?3YE}cQH zBn);cfxZ$3nT9(_-%Lj|pNktOF<yK-gG`6PRF`3}<C}9kgHUP0Ak)qu(@>Z6&2&Wb zxw!Ei<Hff#$aEO&_+~l`u6(QWCF}?5mpkfKG#E_KU@$>r7v)PbtON`ua)ZGH9R~N$ zN>zdu#J9Mqn`w-EZf6j)iF5I=5@(QeJA+I+gV>ih$TZ$b8DttGPrEsY*~EUZ@y)a| z$h0$vm3o6rJA+JPUCJQS7<t;wLChxhgN<*d`v&Xo5m!Dk*sS)727?J23?^vkB0+<} z1PyaAL4!d_g9ZK;H>+kf$TUVgPZSLX6S=`)f(C;L8Vn|AFeqv4i{@a0b_O{&M#?vi vkG>@J=`igKGVKg9?F{0x_6C`D2ARgXltHF3^0YIE*+%PNeL76H24DRHrn}G@ literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/Yield_Table_Vol.dbf b/resources/3rdparty/glpk-4.53/examples/dbf/Yield_Table_Vol.dbf new file mode 100644 index 0000000000000000000000000000000000000000..b0d051ba77e25f794cf00870bc2205d85e781817 GIT binary patch literal 11786 zcmb7}v2N8s5Jdxs1_{wqy)TI3gd|Xg5D*ds6ri9=Nrgng5At6WI9?#<uJ6uuUXf_B z$K#pf@nSz7yuNqu_uk&#uf6^G=lb*M^V#LA_UH4PUk^Lv{L8!Rk5?C;=09J$_4jW+ zUw^$gyPDUQ;~#a$f4sPQ`=Om+Ilf>2`u5`8-}5i)Pws1i$GfxL-_P{@+t2GC)4y=} zjp*oj|KOme4{_{4q>t`IKf9$5Ph#%lTY8r(Ik^*kdQ00%XkoX5L0gH^h>lK8msp>x zNCuUL!3~wb;D#=fL9GM^Z6)k08&sNSa#vnyL`To}k5}`J_1Skas5A_2=n@94Z_S+y zveIl&>10r8*5!OFjp$jXlR;#guMP}a-%7(^=lk$Z`=F!81|3a<y0bZ&U8q4v!{CN4 z#|B+)7~HwKX`!0ImRo5=-9G4O8gx#Ot-FhJ-7wfqm8%2>t#7S_23_6kD;rdrXUe&8 zY_|`#F0tMj%(-dM`PSSpXniXUgVs0imTXYzWKe0=<(w#usM`mdZ>-P0X)x!eLFZd@ z!(iw8MZFJhpvMMX?y*5fvkP_N=&?aZ(_qe>4AMe1gRK&!8M#WhUOf-G+{vKkP6m}u z29-_*IT_iY(mazhs5GNYCxgsZ-No(dD4h%{oeZ+lY*6WBP-)iX3@Xhi(`g2ot$H48 zzLj1Xd^vBt%O|`SPtR}O(@J_}u%uT8OB!8Fhq02C!7}%121^<SZ6&l|X0XexG@|MB z<~^;XlR;#guP_X@f78m`Fu0-1WKb)CL0bv?$_AC@nU*`P>r!b%(~0qo^$iA<hQSS8 z!l3o7xsyR&>ugZzWKe0=<$NoRXj;B!>#h#gXWz-7(lBU!D-DC4@AhQM@3Sg{jvgCy z^w^-I*@gOc^w^-I#|9k@gPre2(?T|=G$Yp~*Uj_b|EY47B!ike8B{tMR5}^tWMqR% z^Gwd5(u^{l3^H4F7q_dUbTX)PGRR7^L8X&HrCFCVs5GNYrx|26^E}wy4N8v<wx`Ff z`=F!81|2;%=xBDK1|2;%=;-kbIyxDog=z*{ZlxKyF1cRqgD!V6sJW9trISIWlR-{K zHmEeu<P0j!DAUOxvsL?GyE;lIgGwiZtTY=`IvG@&bvc7dGs<+DL1wG=!RA}(mBI7n zrFi}k-izD+36%88U`ekGmNdF(&#@)FGFZ~987yfSw3X0;nZYi%(uk(%=Iy_vlR;#2 zZ*^sE7~IfhGN_fnV0)tODq&yQpwc|ka;KHKacp}}D{0K&hPq*J0}X@LH!7X4WirT0 zvq7bkL8V!j^Q|<Z_PtN%8|!nI$)M6OXniXUgPm{p4#=lN?b6X>gN_~>bTqrjm5dF# z++%}|hQZEvqiLa<K}Yjg*Cp4@^Wgufa=DX1&7BM?oeV0S401BEL8W;nXHaQInN9|o zt-6cb)loVbR5}@CrP-j;$)M7#%NbOfQKr)jGMjlG?Cu7o#|GQeBX_>aprgkI9X&Sa zXm+6n9X&Sa=<y6XIvJ#eY*1-Nu1l_0`(UeE>10spWKij3Q0ZillaUQ7%`-WJN;ArI tGRSPzKG?2~(#fFG$sjAu29-_*m1bSepwf&ooo0~Ps(rBeR=PL%^be03!(;#e literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/cultural_pres.dbf b/resources/3rdparty/glpk-4.53/examples/dbf/cultural_pres.dbf new file mode 100644 index 0000000000000000000000000000000000000000..76c8dfab5a64567d2c045041e7e8c94922c090a4 GIT binary patch literal 96 xcmZS1<q>3NU|?`$-~y7Ez&X?>J|M_77%1ZhlI28G!m9uShA@VL5u9Zy1pqn72h#um literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/mgt_year.dbf b/resources/3rdparty/glpk-4.53/examples/dbf/mgt_year.dbf new file mode 100644 index 0000000000000000000000000000000000000000..043ba5a0d7cf4c384ad401cdf102bd7509eaeb15 GIT binary patch literal 106 zcmZS1<q>3IU|?`$-~y7Ez}Gz_KGM}O2q@zWlI28G!mE&*UJ_qmr~m|DmJys~3}=}D GSyBKKG!E_n literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/stands.dbf b/resources/3rdparty/glpk-4.53/examples/dbf/stands.dbf new file mode 100644 index 0000000000000000000000000000000000000000..5ecfd2429cbfd621346f6d951d07ce3c443ab339 GIT binary patch literal 4323 zcmb_fOK&4Z5YB4hwg|+L3-b#~T~+-&I>AIMZB|hdkoM#wr<FKxNBncX>W6JQ_QaBD z*)u)UkFV?XRn7aaAAbD#=H}*~cYovhx^14eoBsB*-9Nnl@0`c&)5nMH%l7H!=H&S1 z?rHnnmYf{_eS5!q`SQ5MlslXDeVe<#-u?Dz_t>_m>*w)@`<LC9?FR6t*WYfQH=lM@ zin{)X{m!kkxi{$A>i9R~sox)Ne;se?__y!IW4k}UY(D?ex+nL?`No2i`+v7AOH5gP zB4x$HqLMO|;H<wa94RE-w1?AI{`$vXyFdB#pd@UR!s3PI8QHeSFNC7OQE(NqIG2f| zwCyxdD(M3FK7T%h2sRC25$rRKMLc7b1k5RUz$f;RlGq?xNR&&t0KRIjtvSAm$plpj z(|kbF23ARS>Lu;rl|6CpXN{gTTmtWpK@WW~E5@*>e+6$V@Rt%&0Zg3<LkW(87j27} zsJO5yy{y_^4Ia`L>N}33vB3u@zzb^%<ht#1@dRVEX>h~fFM*#`+fk$d9{(VO&T(T~ zfg=Sq-y6zj&N)&}rA}oLL_xej`nPRAdA^u{FmZt4Jp!*u&u|uKLYwp~p28cR-;{sO z_QUf%HG%dDs9_G2kR<!S-Sya~gsHJf!)ou>UGI$A8;<zB>&?oy<KQ1vJ;z~tW_3bQ zI=m0$d7XC3s_Vh+7Elk2JH@>~Uu<Vfkpq{Z{K!s8rO5<JB9V3Y$)<bl){YoLqn+-| z`*8@!wzl}>d?w%QtubcGUHL{A$;<72&52GU-7~IN1zd0hH<PY8MfLuY74bo-@w|t* zD1^QpJRh8Y0sI-)Yw!qfN0ao7m*#%#IdMvZc6>p4$lNWZfY-1Ne?lXNSEl?X{Y*Ph zyipHB?8te*M=j=Vwh9fJ;9RbSuhLHuV$N+Eut3jnvCeuaGb7`5RU!SrFRp;ECN?wE zWF7_rLnGk$R9N@Ydq9fsX9ZbG@&60_WP3r(n~5ca?A##TC2K_7Tew;a8Oiq=_=D{y z>BVf1BdLS69jcm^a#D<uSo`EyD5Z3T^cB9^e&Pp#<O~fc7tbg+TEb<A@`6h4@X09X z8rM76es(=P+n`3r5PwLYwHzrwqo3DZ&$#=1JHXGxgmu*bj#2L@u|P)%H7<#w>(UFP zkLB+C_R!$kU?bgA#g<vcsGXfS515RC6fJnzK3Rck4ez~#b@;WE!{)<^jgeE@j^k?8 zWR3ldLia$ru|VOuX#%<ceBuk>C(8~Hu0jGH_2YQg?uzG{^>RsYenP=z11PlN?WOiB zeDH55ze+z_wqvmsTRtGdX_{e0pb3e})<fFidWbVeVi9RA;q#!x3#6Z-x~+y~EsvS< z!5`yYzZ>Pi0E#J2-5}i@5d~swYz^=@-a34ndHTv$?KJo)LMr3o2wp@oa(u7#I3vwO zqeN>Z5;EWw@aDrf0!SU5<7SGtax<a4@<_5B-YZHBHcmq0s1(Z;@K$6uc9~tzYJ3y2 zD0t3l`%1d_zQI?H>lqJ5pb+1%{jp4QAKAP~kAi&~L#)94*d>Q@ZzNn4oem#Xz19<y anuvl`<+oDvT;Nq+g$BZ_ubk?3Km7~OdwFUA literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/standtype.dbf b/resources/3rdparty/glpk-4.53/examples/dbf/standtype.dbf new file mode 100644 index 0000000000000000000000000000000000000000..0306d50456403e3b6c32adea01b1a63249497778 GIT binary patch literal 96 vcmZS1<q>3NU|?`$-~y7EAUMR)&jljv45B#El<+DzD!_mfjG^ERV@Ux30vrbK literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/examples/dea.mod b/resources/3rdparty/glpk-4.53/examples/dea.mod new file mode 100644 index 000000000..ba610735a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/dea.mod @@ -0,0 +1,222 @@ +/* Data Envelopment Analysis (DEA) + * + * DEA quantifies the relative efficiency of decision making units (DMUs) by + * finding the efficient frontier in multiple input multiple output data. The + * inputs are resources (eg. number of employees, available machines, ...), + * the outputs are productive outputs (eg. contracts made, total sales, ...). + * The method is non-parametric. More details are available in the paper + * below. + * + * Models according to: Seiford, Threall, "Recent developments in DEA", 1990. + * + * Implementation: Sebastian Nowozin <nowozin@gmail.com> + */ + +### SETS ### + +set dmus; # Decision Making Units (DMU) +set inputs; # Input parameters +set outputs; # Output parameters + + +### PARAMETERS ### + +param input_data{dmus,inputs} >= 0; +param output_data{dmus,outputs} >= 0; + + +### PROGRAM ### + +var theta{dmus} >= 0; +var lambda{dmus,dmus} >= 0; + +minimize inefficiency: sum{td in dmus} theta[td]; + +s.t. output_lower_limit{o in outputs, td in dmus}: + sum{d in dmus} lambda[d,td]*output_data[d,o] >= output_data[td,o]; +s.t. input_upper_limit{i in inputs, td in dmus}: + sum{d in dmus} lambda[d,td]*input_data[d,i] <= theta[td]*input_data[td,i]; + + s.t. PI1{td in dmus}: + sum{d in dmus} lambda[d,td] = 1; +/* +possibilities: + i) (no constraint) + ii) s.t. PI1{td in dmus}: + sum{d in dmus} lambda[d,td] <= 1; + iii) s.t. PI1{td in dmus}: + sum{d in dmus} lambda[d,td] >= 1; +*/ + + +### SOLVE AND PRINT SOLUTION ### + +solve; + +printf "DMU\tEfficiency\n"; +for {td in dmus} { + printf "%s\t%1.4f\n", td, theta[td]; +} + +### DATA ### + +data; + +set dmus := 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 ; +set inputs := AvgInventory LaborCost OperatingCost Population ; +set outputs := PrescrVol kDollarValue ; + +param input_data default 0.0 : + + AvgInventory LaborCost OperatingCost Population := + +1 8000 17030 1280 1410 +2 9000 25890 2779 1523 +3 13694 29076 2372 1354 +4 4250 17506 1385 822 +5 6500 23208 639 746 +6 7000 12946 802 1281 +7 4500 18001 1130 1016 +8 5000 14473 1097 1070 +9 27000 31760 5559 1694 +10 21560 50972 15010 1910 +11 15000 39523 4799 1745 +12 8500 13076 3489 1353 +13 35000 35427 1704 500 +14 18000 27554 2882 1016 +15 59750 53848 14208 2500 +16 19200 38253 1480 2293 +17 40000 109404 83016 2718 +18 8466 18198 1278 2877 +19 16000 40891 7599 4150 +20 10000 45444 5556 4421 +21 25000 35623 2121 3883 +22 14000 20192 5515 3519 +23 12500 34973 10475 32366 +24 17260 32284 14498 3393 +25 7000 17920 7585 4489 +26 14000 42094 3742 2217 +27 16400 35422 14236 4641 +28 13000 19100 3529 5968 +29 30000 72167 8656 8715 +30 12530 19970 1714 5968 +31 31500 39183 4919 5607 +32 10000 32048 3483 7324 +33 22000 68877 12279 8685 +34 10000 29812 3332 8685 +35 16000 47686 2507 5420 +36 10000 33415 4738 7703 +37 9000 12359 4603 4665 +38 16439 23614 2989 6317 +39 14500 36069 1793 31839 +40 39000 76307 9539 15619 +41 24927 40706 12661 30213 +42 13858 39267 4609 34719 +43 33375 29509 11323 31839 +44 29044 44482 5542 34719 +45 32257 61365 20550 32366 +46 8800 49671 3306 43561 +47 47000 40425 10396 31263 +48 12000 33034 4915 31263 +49 28000 69163 4688 15173 +50 13300 28931 16735 73064 +51 13500 29758 4260 62309 +52 24000 40927 8285 23166 +53 16000 40403 2131 99836 +54 17000 38730 2539 60348 +55 25000 35978 2502 99836 +56 16000 37509 6278 99836 +57 20000 46950 10715 85925 +58 14000 35966 3144 85925 +59 22000 68318 8015 108987 +60 21879 69537 7778 108987 +61 15000 25425 2812 201404 +62 10000 19508 2454 201404 +63 20000 28191 3367 201404 +64 18000 37073 8624 108987 +65 19051 23763 3496 201404 +66 15000 28642 3366 201404 +67 10000 35919 3868 201404 +68 24000 54653 26494 108987 +69 1800 6276 3413 60348 + ; + +param output_data default 0.0 : + + PrescrVol kDollarValue := + +1 12293 61.00 +2 18400 92.00 +3 16789 92.65 +4 10700 45.00 +5 9800 50.00 +6 6500 29.00 +7 8200 56.00 +8 8680 45.00 +9 33800 183.00 +10 23710 156.00 +11 24000 120.00 +12 17500 75.00 +13 25000 130.00 +14 26000 122.00 +15 26830 178.513 +16 16600 106.00 +17 90000 450.00 +18 11140 73.624 +19 25868 136.00 +20 32700 191.295 +21 29117 152.864 +22 18000 100.00 +23 11100 60.00 +24 23030 137.778 +25 10656 58.00 +26 24682 152.095 +27 26908 120.00 +28 16464 80.00 +29 57000 321.00 +30 17532 94.747 +31 30035 168.00 +32 16000 100.00 +33 63700 277.00 +34 18000 90.00 +35 27339 139.134 +36 19500 116.00 +37 13000 80.00 +38 15370 102.00 +39 18446 90.00 +40 56000 260.00 +41 73845 364.951 +42 28600 145.00 +43 27000 243.00 +44 52423 279.816 +45 73759 363.388 +46 20500 80.00 +47 27100 115.00 +48 15000 110.00 +49 50895 277.852 +50 19707 128.00 +51 17994 78.80 +52 36135 167.222 +53 30000 153.00 +54 26195 125.00 +55 28000 216.00 +56 24658 152.551 +57 36850 190.00 +58 29250 183.69 +59 50000 250.00 +60 40078 265.443 +61 20200 110.00 +62 12500 75.00 +63 30890 195.00 +64 31000 175.00 +65 31277 192.992 +66 11500 75.00 +67 30000 175.668 +68 38383 190.00 +69 2075 8.650 + ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/diet.mod b/resources/3rdparty/glpk-4.53/examples/diet.mod new file mode 100644 index 000000000..6d36391af --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/diet.mod @@ -0,0 +1,99 @@ +# STIGLER'S NUTRITION MODEL +# +# This model determines a least cost diet which meets the daily +# allowances of nutrients for a moderately active man weighing 154 lbs. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 27-1. + +set N; +/* nutrients */ + +set F; +/* foods */ + +param b{N}; +/* required daily allowances of nutrients */ + +param a{F,N}; +/* nutritive value of foods (per dollar spent) */ + +var x{f in F} >= 0; +/* dollars of food f to be purchased daily */ + +s.t. nb{n in N}: sum{f in F} a[f,n] * x[f] = b[n]; +/* nutrient balance (units) */ + +minimize cost: sum{f in F} x[f]; +/* total food bill (dollars) */ + +data; + +param : N : b := + Calorie 3 /* thousands */ + Protein 70 /* grams */ + Calcium 0.8 /* grams */ + Iron 12 /* milligrams */ + Vitamin-A 5 /* thousands IUs */ + Vitamin-B1 1.8 /* milligrams */ + Vitamin-B2 2.7 /* milligrams */ + Niacin 18 /* milligrams */ + Vitamin-C 75 /* milligrams */ ; + +set F := Wheat Cornmeal Cannedmilk Margarine Cheese Peanut-B Lard + Liver Porkroast Salmon Greenbeans Cabbage Onions Potatoes + Spinach Sweet-Pot Peaches Prunes Limabeans Navybeans; + +param a default 0 + +: Calorie Protein Calcium Iron Vitamin-A Vitamin-B1 := +# (1000) (g) (g) (mg) (1000IU) (mg) + +Wheat 44.7 1411 2.0 365 . 55.4 +Cornmeal 36 897 1.7 99 30.9 17.4 +Cannedmilk 8.4 422 15.1 9 26 3 +Margarine 20.6 17 .6 6 55.8 .2 +Cheese 7.4 448 16.4 19 28.1 .8 +Peanut-B 15.7 661 1 48 . 9.6 +Lard 41.7 . . . .2 . +Liver 2.2 333 .2 139 169.2 6.4 +Porkroast 4.4 249 .3 37 . 18.2 +Salmon 5.8 705 6.8 45 3.5 1 +Greenbeans 2.4 138 3.7 80 69 4.3 +Cabbage 2.6 125 4 36 7.2 9 +Onions 5.8 166 3.8 59 16.6 4.7 +Potatoes 14.3 336 1.8 118 6.7 29.4 +Spinach 1.1 106 . 138 918.4 5.7 +Sweet-Pot 9.6 138 2.7 54 290.7 8.4 +Peaches 8.5 87 1.7 173 86.8 1.2 +Prunes 12.8 99 2.5 154 85.7 3.9 +Limabeans 17.4 1055 3.7 459 5.1 26.9 +Navybeans 26.9 1691 11.4 792 . 38.4 + +: Vitamin-B2 Niacin Vitamin-C := +# (mg) (mg) (mg) + +Wheat 33.3 441 . +Cornmeal 7.9 106 . +Cannedmilk 23.5 11 60 +Margarine . . . +Cheese 10.3 4 . +Peanut-B 8.1 471 . +Lard .5 5 . +Liver 50.8 316 525 +Porkroast 3.6 79 . +Salmon 4.9 209 . +Greenbeans 5.8 37 862 +Cabbage 4.5 26 5369 +Onions 5.9 21 1184 +Potatoes 7.1 198 2522 +Spinach 13.8 33 2755 +Sweet-Pot 5.4 83 1912 +Peaches 4.3 55 57 +Prunes 4.3 65 257 +Limabeans 38.2 93 . +Navybeans 24.6 217 . ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/dist.mod b/resources/3rdparty/glpk-4.53/examples/dist.mod new file mode 100644 index 000000000..f3d66b513 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/dist.mod @@ -0,0 +1,565 @@ +# DIST, a product distribution model +# +# References: +# Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language +# for Mathematical Programming." Management Science 36 (1990) 519-554. + +### SHIPPING SETS AND PARAMETERS ### + +set whse 'warehouses'; # Locations from which demand is satisfied + +set dctr 'distribution centers' within whse; + + # Locations from which product may be shipped + +param sc 'shipping cost' {dctr,whse} >= 0; + + # Shipping costs, to whse from dctr, in $ / 100 lb + +param huge 'largest shipping cost' > 0; + + # Largest cost allowed for a usable shipping route + +param msr 'minimum size restriction' {dctr,whse} logical; + + # True indicates a minimum-size restriction on + # direct shipments using this dctr --> whse route + +param dsr 'direct shipment requirement' {dctr} >= 0; + + # Minimum total demand, in pallets, needed to + # allow shipment on routes subject to the + # minimum size restriction + +### PLANT SETS AND PARAMETERS ### + +set fact 'factories' within dctr; + + # Locations where product is manufactured + +param rtmin 'regular-time total minimum' >= 0; + + # Lower limit on (average) total regular-time + # crews employed at all factories + +param rtmax 'regular-time total maximum' >= rtmin; + + # Upper limit on (average) total regular-time + # crews employed at all factories + +param otmin 'overtime total minimum' >= 0; + + # Lower limit on total overtime hours at all factories + +param otmax 'overtime total maximum' >= otmin; + + # Upper limit on total overtime hours at all factories + +param rmin 'regular-time minimums' {fact} >= 0; + + # Lower limits on (average) regular-time crews + +param rmax 'regular-time maximums' {f in fact} >= rmin[f]; + + # Upper limits on (average) regular-time crews + +param omin 'overtime minimums' {fact} >= 0; + + # Lower limits on overtime hours + +param omax 'overtime maximums' {f in fact} >= omin[f]; + + # Upper limits on overtime hours + +param hd 'hours per day' {fact} >= 0; + + # Regular-time hours per working day + +param dp 'days in period' {fact} > 0; + + # Working days in the current planning period + +### PRODUCT SETS AND PARAMETERS ### + +set prd 'products'; # Elements of the product group + +param wt 'weight' {prd} > 0; + + # Weight in 100 lb / 1000 cases + +param cpp 'cases per pallet' {prd} > 0; + + # Cases of product per shipping pallet + +param tc 'transshipment cost' {prd} >= 0; + + # Transshipment cost in $ / 1000 cases + +param pt 'production time' {prd,fact} >= 0; + + # Crew-hours to produce 1000 cases + +param rpc 'regular-time production cost' {prd,fact} >= 0; + + # Cost of production on regular time, + # in $ / 1000 cases + +param opc 'overtime production cost' {prd,fact} >= 0; + + # Cost of production on overtime, in $ / 1000 cases + +### DEMAND SETS AND PARAMETERS ### + +param dt 'total demand' {prd} >= 0; + + # Total demands for products, in 1000s + +param ds 'demand shares' {prd,whse} >= 0.0, <= 1.0; + + # Historical demand data, from which each + # warehouse's share of total demand is deduced + +param dstot {p in prd} := sum {w in whse} ds[p,w]; + + # Total of demand shares; should be 1, but often isn't + +param dem 'demand' {p in prd, w in whse} := dt[p] * ds[p,w] / dstot[p]; + + # Projected demands to be satisfied, in 1000s + +set rt 'shipping routes available' := + + {d in dctr, w in whse: + d <> w and sc[d,w] < huge and + (w in dctr or sum {p in prd} dem[p,w] > 0) and + not (msr[d,w] and sum {p in prd} 1000*dem[p,w]/cpp[p] < dsr[d]) }; + + # List of ordered pairs that represent routes + # on which shipments are allowed + +### VARIABLES ### + +var Rprd 'regular-time production' {prd,fact} >= 0; + + # Regular-time production of each product + # at each factory, in 1000s of cases + +var Oprd 'overtime production' {prd,fact} >= 0; + + # Overtime production of each product + # at each factory, in 1000s of cases + +var Ship 'shipments' {prd,rt} >= 0; + + # Shipments of each product on each allowed route, + # in 1000s of cases + +var Trans 'transshipments' {prd,dctr} >= 0; + + # Transshipments of each product at each + # distribution center, in 1000s of cases + +### OBJECTIVE ### + +minimize cost: sum {p in prd, f in fact} rpc[p,f] * Rprd[p,f] + + sum {p in prd, f in fact} opc[p,f] * Oprd[p,f] + + sum {p in prd, (d,w) in rt} sc[d,w] * wt[p] * Ship[p,d,w] + + sum {p in prd, d in dctr} tc[p] * Trans[p,d]; + + # Total cost: regular production, overtime + # production, shipping, and transshipment + +### CONSTRAINTS ### + +rtlim 'regular-time total limits': + + rtmin <= sum {p in prd, f in fact} + (pt[p,f] * Rprd[p,f]) / (dp[f] * hd[f]) <= rtmax; + + # Total crews must lie between limits + +otlim 'overtime total limits': + + otmin <= sum {p in prd, f in fact} pt[p,f] * Oprd[p,f] <= otmax; + + # Total overtime must lie between limits + +rlim 'regular-time limits' {f in fact}: + + rmin[f] <= sum {p in prd} + (pt[p,f] * Rprd[p,f]) / (dp[f] * hd[f]) <= rmax[f]; + + # Crews at each factory must lie between limits + +olim 'overtime limits' {f in fact}: + + omin[f] <= sum {p in prd} pt[p,f] * Oprd[p,f] <= omax[f]; + + # Overtime at each factory must lie between limits + +noRprd 'no regular production' {p in prd, f in fact: rpc[p,f] = 0}: + + Rprd[p,f] = 0; + +noOprd 'no overtime production' {p in prd, f in fact: opc[p,f] = 0}: + + Oprd[p,f] = 0; # Do not produce where specified cost is zero + +bal 'material balance' {p in prd, w in whse}: + + sum {(v,w) in rt} + Ship [p,v,w] + (if w in fact then Rprd[p,w] + Oprd[p,w]) = + + dem[p,w] + (if w in dctr then sum {(w,v) in rt} Ship[p,w,v]); + + # Demand is satisfied by shipment into warehouse + # plus production (if it is a factory) + # minus shipment out (if it is a distn. center) + +trdef 'transshipment definition' {p in prd, d in dctr}: + + Trans[p,d] >= sum {(d,w) in rt} Ship [p,d,w] - + (if d in fact then Rprd[p,d] + Oprd[p,d]); + + # Transshipment at a distribution center is + # shipments out less production (if any) + +### DATA -- 3 PRODUCTS ### + +data; + +set prd := 18REG 24REG 24PRO ; + +set whse := w01 w02 w03 w04 w05 w06 w08 w09 w12 w14 w15 w17 + w18 w19 w20 w21 w24 w25 w26 w27 w28 w29 w30 w31 + w32 w33 w34 w35 w36 w37 w38 w39 w40 w41 w42 w43 + w44 w45 w46 w47 w48 w49 w50 w51 w53 w54 w55 w56 + w57 w59 w60 w61 w62 w63 w64 w65 w66 w68 w69 w71 + w72 w73 w74 w75 w76 w77 w78 w79 w80 w81 w82 w83 + w84 w85 w86 w87 w89 w90 w91 w92 w93 w94 w95 w96 + w98 x22 x23 ; + +set dctr := w01 w02 w03 w04 w05 w62 w76 w96 ; + +set fact := w01 w05 w96 ; + +param huge := 99. ; + +param rtmin := 0.0 ; +param rtmax := 8.0 ; + +param otmin := 0.0 ; +param otmax := 96.0 ; + +param rmin := w01 0.00 w05 0.00 w96 0.00 ; +param rmax := w01 3.00 w05 2.00 w96 3.00 ; + +param omin := w01 0.0 w05 0.0 w96 0.0 ; +param omax := w01 48.0 w05 0.0 w96 48.0 ; + +param hd := w01 8.0 w05 8.0 w96 8.0 ; + +param dp := w01 19.0 w05 19.0 w96 19.0 ; + +param wt := 18REG 47.3 24REG 63.0 24PRO 63.0 ; + +param tc := 18REG 40.00 24REG 45.00 24PRO 45.00 ; + +param dt := 18REG 376.0 24REG 172.4 24PRO 316.3 ; + +param cpp := 18REG 102. 24REG 91. 24PRO 91. ; + +param dsr := w01 96. w02 96. w03 96. w04 96. w05 96. + w62 96. w76 96. w96 96. ; + +param pt (tr) : + + 18REG 24REG 24PRO := + +w01 1.194 1.429 1.429 +w05 1.194 1.509 1.509 +w96 0.000 1.600 1.600 ; + +param rpc (tr) : + + 18REG 24REG 24PRO := + +w01 2119. 2653. 2617. +w05 2489. 3182. 3176. +w96 0. 2925. 2918. ; + +param opc (tr) : + + 18REG 24REG 24PRO := + +w01 2903. 3585. 3579. +w05 0. 0. 0. +w96 0. 3629. 3622. ; + +param sc default 99.99 (tr) : + + w01 w02 w03 w04 w05 w62 w76 w96 := + +w01 . 2.97 1.14 2.08 2.37 1.26 2.42 1.43 +w02 4.74 . 4.17 6.12 7.41 3.78 7.04 5.21 +w03 2.45 4.74 . 3.67 2.84 0.90 2.41 2.55 +w04 1.74 5.03 2.43 . 3.19 2.45 2.69 0.58 +w05 2.70 5.16 2.84 2.85 . 3.26 3.34 2.71 +w06 1.99 4.17 2.13 2.19 2.52 2.06 2.00 1.51 +w08 0.21 2.92 1.24 2.07 2.29 1.25 2.32 1.55 +w09 0.66 3.76 1.41 2.47 1.82 1.66 . 1.87 +w12 1.38 3.83 1.68 2.53 2.39 . 1.96 1.94 +w14 2.47 1.58 2.40 3.59 3.85 2.25 . 3.05 +w15 1.06 4.95 2.48 1.39 3.41 1.96 . 1.02 +w17 0.88 3.39 1.46 2.00 2.67 1.45 . 1.46 +w18 7.90 6.57 7.79 9.59 10.81 . . 6.70 +w19 1.42 4.12 1.96 1.99 3.52 1.88 . 1.26 +w20 3.03 1.59 2.34 4.76 3.98 1.88 . 3.73 +w24 1.58 2.80 2.27 2.87 3.19 1.31 . 2.05 +w25 1.51 5.05 2.74 0.57 2.98 . 2.95 0.27 +w26 1.75 3.61 2.70 1.54 4.07 3.52 . 1.03 +w27 2.48 6.87 3.17 1.59 2.08 3.45 . 0.99 +w28 2.05 6.83 2.97 1.13 2.91 . . 1.26 +w29 4.03 3.68 4.46 3.20 5.50 . . 3.20 +w30 2.48 5.78 2.99 2.24 1.79 3.10 . 1.39 +w31 2.34 5.41 2.87 1.67 1.66 . . 1.39 +w32 14.36 . . . . . . . +w33 3.87 4.27 5.11 3.48 5.66 4.03 . 3.05 +w34 3.26 4.80 3.21 2.70 4.14 . . 1.77 +w35 2.34 2.84 2.89 3.35 3.78 2.68 . 2.52 +w36 2.43 5.69 2.96 2.95 1.02 2.61 1.07 2.54 +w37 2.23 4.64 2.41 1.99 4.30 2.61 . 1.44 +w38 4.66 4.36 5.23 3.04 4.46 . . 3.82 +w39 1.11 3.51 1.10 2.53 3.07 1.12 . 2.23 +w40 2.99 4.78 4.23 1.57 3.92 . . 1.80 +w41 4.93 4.00 5.43 4.45 6.31 . . 3.81 +w42 3.86 6.55 5.03 2.11 4.41 . . 2.63 +w43 4.61 4.45 3.77 1.22 4.31 . . 2.35 +w44 2.05 4.48 1.06 3.70 3.46 1.10 . 3.21 +w45 0.92 3.42 1.58 3.04 1.82 1.94 . 2.52 +w46 1.36 2.44 0.95 3.08 2.78 0.39 2.16 2.37 +w47 1.30 3.39 1.60 2.49 4.29 2.04 . 1.68 +w48 1.65 3.78 1.03 2.97 2.21 1.31 . 2.74 +w49 1.96 3.00 1.50 3.24 3.68 1.00 . 2.99 +w50 0.90 4.14 1.60 1.95 3.61 1.61 . 1.52 +w51 1.59 3.95 0.25 2.96 2.58 1.00 2.41 2.71 +w53 1.59 3.79 1.28 3.12 3.10 0.89 . 2.98 +w54 1.72 4.36 1.61 2.92 2.34 1.91 1.97 3.05 +w55 2.45 2.73 2.21 4.47 4.30 2.57 . 4.48 +w56 1.10 3.73 1.59 2.74 2.33 1.45 . 2.44 +w57 0.95 3.39 1.37 2.30 2.47 1.15 . 1.95 +w59 3.29 5.35 3.32 3.81 1.52 3.38 1.34 4.08 +w60 2.41 6.12 2.46 3.65 2.35 . 1.37 4.06 +w61 3.32 5.50 3.41 3.38 1.23 . 0.99 4.28 +w62 1.12 3.00 0.82 3.22 2.95 . 3.33 2.53 +w63 3.59 6.36 3.25 4.12 1.84 3.59 1.46 4.03 +w64 1.85 4.45 2.17 3.43 2.13 2.03 . 4.02 +w65 2.78 4.79 2.81 2.94 1.54 2.90 1.07 2.94 +w66 3.90 5.79 3.05 3.65 1.36 3.39 1.22 3.57 +w68 2.61 5.20 2.90 2.34 1.68 3.19 1.48 2.31 +w69 2.94 5.21 2.78 3.43 0.21 3.26 0.68 2.54 +w71 2.06 4.98 2.38 2.44 1.59 2.97 1.05 2.55 +w72 2.61 5.50 2.83 3.12 1.35 3.23 0.88 2.99 +w73 8.52 6.16 8.03 8.83 10.44 7.38 10.26 . +w74 6.11 5.46 9.07 9.38 10.80 . . 8.25 +w75 2.66 4.94 2.87 3.69 1.52 3.15 1.24 4.00 +w76 1.99 5.26 2.23 3.36 0.58 3.17 . 2.50 +w77 4.32 3.07 5.05 3.88 6.04 . . 4.15 +w78 5.60 2.59 5.78 5.56 7.10 . . 5.60 +w79 4.25 2.32 4.93 4.57 6.04 . . 4.58 +w80 5.94 4.00 5.60 7.02 9.46 . . 7.51 +w81 5.39 2.21 5.10 6.22 6.46 . . 6.58 +w82 8.80 5.69 9.29 9.88 11.69 8.63 11.52 . +w83 4.40 . 5.24 5.21 5.81 3.91 7.04 5.33 +w84 5.87 5.43 6.17 5.70 7.63 . . 5.70 +w85 3.90 3.65 3.38 4.57 5.64 3.05 . 5.04 +w86 5.48 2.10 5.70 6.37 7.33 . . 6.19 +w87 8.88 5.54 9.50 9.71 11.64 8.85 11.68 . +w89 4.62 4.01 4.03 6.30 6.30 3.81 . 7.77 +w90 4.35 2.72 4.61 4.01 5.60 . . 3.20 +w91 7.61 4.42 7.83 6.85 8.79 . . 7.66 +w92 7.15 2.69 6.91 7.20 . . . 7.06 +w93 3.17 3.95 4.37 3.74 5.05 . . 2.40 +w94 1.21 3.07 0.90 2.74 3.17 . 2.63 2.39 +w95 5.82 3.29 6.55 7.06 11.47 . . 7.83 +w96 1.77 5.20 2.72 0.59 3.47 2.48 . . +w98 3.04 1.92 3.64 3.70 4.90 3.05 . 3.88 +x22 4.08 6.25 4.15 4.30 1.77 . 1.77 . +x23 3.39 5.74 3.55 4.08 1.69 . 1.47 . ; + +param msr (tr) : + + w01 w02 w03 w04 w05 w62 w76 w96 := + +w01 0 0 0 0 0 0 1 0 +w02 0 0 0 0 0 0 1 0 +w03 0 0 0 0 0 0 1 0 +w04 0 0 0 0 0 0 1 0 +w05 0 0 0 0 0 0 0 0 +w06 0 1 1 1 1 1 1 1 +w08 0 1 1 1 1 1 1 1 +w09 0 1 1 1 1 1 0 1 +w12 0 1 1 1 1 0 1 1 +w14 1 1 1 1 1 0 0 1 +w15 0 1 1 1 1 1 0 1 +w17 0 1 1 1 1 1 0 1 +w18 0 1 1 1 1 0 0 1 +w19 0 1 1 1 1 0 0 1 +w20 1 1 1 1 1 0 0 1 +w24 0 1 1 1 1 0 0 1 +w25 0 1 1 1 1 0 1 0 +w26 1 1 1 0 1 1 0 1 +w27 1 1 1 0 1 1 0 1 +w28 1 1 1 0 1 0 0 1 +w29 0 1 1 1 1 0 0 1 +w30 1 1 1 0 1 1 0 1 +w31 1 1 1 0 1 0 0 1 +w32 0 0 0 0 0 0 0 0 +w33 1 0 1 1 1 1 0 1 +w34 1 1 1 0 1 0 0 1 +w35 1 1 1 1 1 0 0 1 +w36 0 1 1 1 0 1 1 1 +w37 1 1 1 0 1 1 0 1 +w38 1 1 1 0 1 0 0 1 +w39 0 1 1 1 1 1 0 1 +w40 1 1 1 0 1 0 0 1 +w41 1 0 1 1 1 0 0 1 +w42 1 1 1 0 1 0 0 1 +w43 1 1 1 0 1 0 0 1 +w44 1 1 1 1 1 0 0 1 +w45 0 1 1 1 1 1 0 1 +w46 0 1 1 1 1 0 1 1 +w47 0 1 1 1 1 1 0 1 +w48 0 1 1 1 1 0 0 1 +w49 1 1 1 1 1 0 0 1 +w50 0 1 1 1 1 1 0 1 +w51 0 1 1 1 1 0 1 1 +w53 1 1 1 1 1 0 0 1 +w54 0 1 1 1 1 1 1 1 +w55 0 1 1 1 1 0 0 1 +w56 0 1 1 1 1 1 0 1 +w57 0 1 1 1 1 1 0 1 +w59 0 1 1 1 0 1 1 1 +w60 0 1 1 1 1 0 1 1 +w61 0 1 1 1 0 0 1 1 +w62 0 0 0 0 0 0 1 0 +w63 0 1 1 1 0 1 1 1 +w64 0 1 1 1 1 1 0 1 +w65 0 1 1 1 0 1 1 1 +w66 0 1 1 1 0 1 1 1 +w68 0 1 1 1 0 1 1 1 +w69 0 1 1 1 0 1 1 1 +w71 0 1 1 1 0 1 1 1 +w72 0 1 1 1 0 1 1 1 +w73 0 1 1 1 0 1 1 0 +w74 0 1 1 1 0 0 0 1 +w75 0 1 1 1 0 1 1 1 +w76 0 0 0 0 0 0 0 0 +w77 1 0 1 1 1 0 0 1 +w78 1 0 1 1 1 0 0 1 +w79 1 0 1 1 1 0 0 1 +w80 1 0 1 1 1 0 0 1 +w81 1 0 1 1 1 0 0 1 +w82 1 0 1 1 1 1 1 0 +w83 1 0 1 1 1 0 1 1 +w84 1 0 1 1 1 0 0 1 +w85 1 1 1 1 1 0 0 1 +w86 1 0 1 1 1 0 0 1 +w87 1 0 1 1 1 1 1 0 +w89 1 0 1 1 1 1 0 1 +w90 0 1 1 1 1 0 0 1 +w91 1 0 1 1 1 0 0 1 +w92 1 0 1 1 1 0 0 1 +w93 1 1 1 0 1 0 0 1 +w94 0 0 1 1 1 0 1 1 +w95 1 0 1 1 1 0 0 1 +w96 0 0 0 0 0 0 0 0 +w98 1 0 1 1 1 1 0 1 +x22 1 1 1 1 0 0 1 0 +x23 1 1 1 1 0 0 1 0 ; + +param ds default 0.000 (tr) : + + 18REG 24REG 24PRO := + +w01 0.000 0.000 0.008 +w02 0.004 0.000 0.000 +w03 0.000 0.000 0.000 +w04 0.010 0.002 0.000 +w05 0.000 0.000 0.000 +w06 0.010 0.008 0.008 +w08 0.030 0.024 0.024 +w09 0.014 0.018 0.020 +w12 0.014 0.012 0.010 +w14 0.007 0.007 0.012 +w15 0.010 0.019 0.018 +w17 0.013 0.010 0.011 +w19 0.015 0.012 0.009 +w20 0.012 0.021 0.022 +w21 0.000 0.000 0.000 +w24 0.012 0.022 0.018 +w25 0.019 0.025 0.020 +w26 0.006 0.015 0.021 +w27 0.008 0.010 0.015 +w28 0.011 0.016 0.019 +w29 0.008 0.020 0.013 +w30 0.011 0.013 0.015 +w31 0.011 0.013 0.017 +w32 0.006 0.000 0.000 +w33 0.000 0.015 0.014 +w34 0.008 0.007 0.005 +w35 0.002 0.006 0.014 +w36 0.015 0.013 0.005 +w37 0.017 0.016 0.015 +w38 0.015 0.009 0.012 +w39 0.007 0.017 0.022 +w40 0.009 0.014 0.020 +w41 0.003 0.014 0.011 +w42 0.017 0.011 0.012 +w43 0.009 0.013 0.011 +w44 0.002 0.012 0.012 +w45 0.016 0.025 0.028 +w46 0.038 0.062 0.040 +w47 0.007 0.010 0.010 +w48 0.003 0.015 0.016 +w49 0.005 0.016 0.017 +w50 0.011 0.008 0.007 +w51 0.010 0.022 0.021 +w53 0.004 0.026 0.020 +w54 0.020 0.017 0.025 +w55 0.004 0.019 0.028 +w56 0.004 0.010 0.008 +w57 0.014 0.020 0.018 +w59 0.012 0.006 0.007 +w60 0.019 0.010 0.009 +w61 0.028 0.010 0.012 +w62 0.000 0.000 0.000 +w63 0.070 0.027 0.037 +w64 0.009 0.004 0.005 +w65 0.022 0.015 0.016 +w66 0.046 0.017 0.020 +w68 0.005 0.012 0.016 +w69 0.085 0.036 0.039 +w71 0.011 0.013 0.010 +w72 0.089 0.031 0.034 +w75 0.026 0.012 0.010 +w77 0.001 0.004 0.002 +w78 0.002 0.004 0.002 +w79 0.001 0.004 0.002 +w80 0.001 0.001 0.002 +w81 0.001 0.003 0.002 +w83 0.009 0.010 0.008 +w84 0.001 0.002 0.002 +w85 0.001 0.004 0.005 +w86 0.001 0.002 0.002 +w87 0.002 0.003 0.000 +w89 0.001 0.001 0.002 +w90 0.006 0.017 0.013 +w91 0.002 0.010 0.013 +w92 0.000 0.003 0.002 +w93 0.002 0.006 0.007 +w95 0.001 0.007 0.007 +w96 0.000 0.000 0.000 +w98 0.006 0.005 0.002 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/egypt.mod b/resources/3rdparty/glpk-4.53/examples/egypt.mod new file mode 100644 index 000000000..b051d4a73 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/egypt.mod @@ -0,0 +1,519 @@ +# EGYPT, a static model of fertilizer production +# +# References: +# Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language +# for Mathematical Programming." Management Science 36 (1990) 519-554. + +### SETS ### + +set center; # Locations from which final product may be shipped +set port within center; # Locations at which imports can be received +set plant within center; # Locations of plants + +set region; # Demand regions + +set unit; # Productive units +set proc; # Processes + +set nutr; # Nutrients + +set c_final; # Final products (fertilizers) +set c_inter; # Intermediate products +set c_ship within c_inter; # Intermediates for shipment +set c_raw; # Domestic raw materials and miscellaneous inputs + +set commod := c_final union c_inter union c_raw; + + # All commodities + +### PARAMETERS ### + +param cf75 {region,c_final} >= 0; + + # Consumption of fertilizer 1974-75 (1000 tpy) + +param fn {c_final,nutr} >= 0; + + # Nutrient content of fertilizers + +param cn75 {r in region, n in nutr} := sum {c in c_final} cf75[r,c] * fn[c,n]; + + # Consumption of nutrients 1974-75 (1000 tpy) + +param road {region,center} >= 0; + + # Road distances + +param rail_half {plant,plant} >= 0; +param rail {p1 in plant, p2 in plant} := + if rail_half[p1,p2] > 0 then rail_half[p1,p2] else rail_half[p2,p1]; + + # Interplant rail distances (kms) + +param impd_barg {plant} >= 0; +param impd_road {plant} >= 0; + + # Import distances (kms) by barge and road + +param tran_final {pl in plant, r in region} := + if road[r,pl] > 0 then .5 + .0144 * road[r,pl] else 0; + +param tran_import {r in region, po in port} := + if road[r,po] > 0 then .5 + .0144 * road[r,po] else 0; + +param tran_inter {p1 in plant, p2 in plant} := + if rail[p1,p2] > 0 then 3.5 + .03 * rail[p1,p2] else 0; + +param tran_raw {pl in plant} := + (if impd_barg[pl] > 0 then 1.0 + .0030 * impd_barg[pl] else 0) + + (if impd_road[pl] > 0 then 0.5 + .0144 * impd_road[pl] else 0); + + # Transport cost (le per ton) for: + # final products, imported final products, + # interplant shipment, imported raw materials + +param io {commod,proc}; # Input-output coefficients + +param util {unit,proc} >= 0; + + # Capacity utilization coefficients + +param p_imp {commod} >= 0; # Import Price (cif US$ per ton 1975) + +param p_r {c_raw} >= 0; +param p_pr {plant,c_raw} >= 0; + +param p_dom {pl in plant, c in c_raw} := + if p_r[c] > 0 then p_r[c] else p_pr[pl,c]; + + # Domestic raw material prices + +param dcap {plant,unit} >= 0; + + # Design capacity of plants (t/day) + +param icap {u in unit, pl in plant} := 0.33 * dcap[pl,u]; + + # Initial capacity of plants (t/day) + +param exch := 0.4; # Exchange rate + +param util_pct := 0.85; # Utilization percent for initial capacity + +### DERIVED SETS OF "POSSIBILITIES" ### + +set m_pos {pl in plant} := {u in unit: icap[u,pl] > 0}; + + # At each plant, set of units for which there is + # initial capacity + +set p_cap {pl in plant} := + {pr in proc: forall {u in unit: util[u,pr] > 0} u in m_pos[pl] }; + + # At each plant, set of processes for which + # all necessary units have some initial capacity + +set p_except {plant} within proc; + + # At each plant, list of processes that are + # arbitrarily ruled out + +set p_pos {pl in plant} := p_cap[pl] diff p_except[pl]; + + # At each plant, set of possible processes + +set cp_pos {c in commod} := {pl in plant: sum {pr in p_pos[pl]} io[c,pr] > 0}; + +set cc_pos {c in commod} := {pl in plant: sum {pr in p_pos[pl]} io[c,pr] < 0}; + +set c_pos {c in commod} := cp_pos[c] union cc_pos[c]; + + # For each commodity, set of plants that can + # produce it (cp_pos) or consume it (cc_pos), + # and their union (c_pos) + +### VARIABLES ### + +var Z {pl in plant, p_pos[pl]} >= 0; + + # Z[pl,pr] is level of process pr at plant pl + +var Xf {c in c_final, cp_pos[c], region} >= 0; + + # Xf[c,pl,r] is amount of final product c + # shipped from plant pl to region r + +var Xi {c in c_ship, cp_pos[c], cc_pos[c]} >= 0; + + # Xi[c,p1,p2] is amount of intermediate c + # shipped from plant p1 to plant p2 + +var Vf {c_final,region,port} >= 0; + + # Vf[c,r,po] is amount of final product c + # imported by region r from port po + +var Vr {c in c_raw, cc_pos[c]} >= 0; + + # Vr[c,pl] is amount of raw material c + # imported for use at plant pl + +var U {c in c_raw, cc_pos[c]} >= 0; + + # U[c,pl] is amount of raw material c + # purchased domestically for use at plant pl + +var Psip; # Domestic recurrent cost +var Psil; # Transport cost +var Psii; # Import cost + +### OBJECTIVE ### + +minimize Psi: Psip + Psil + Psii; + +### CONSTRAINTS ### + +subject to mbd {n in nutr, r in region}: + + sum {c in c_final} fn[c,n] * + (sum {po in port} Vf[c,r,po] + + sum {pl in cp_pos[c]} Xf[c,pl,r]) >= cn75[r,n]; + + # Total nutrients supplied to a region by all + # final products (sum of imports plus internal + # shipments from plants) must meet requirements + +subject to mbdb {c in c_final, r in region: cf75[r,c] > 0}: + + sum {po in port} Vf[c,r,po] + + sum {pl in cp_pos[c]} Xf[c,pl,r] >= cf75[r,c]; + + # Total of each final product supplied to each + # region (as in previous constraint) must meet + # requirements + +subject to mb {c in commod, pl in plant}: + + sum {pr in p_pos[pl]} io[c,pr] * Z[pl,pr] + + + ( if c in c_ship then + ( if pl in cp_pos[c] then sum {p2 in cc_pos[c]} Xi[c,pl,p2] ) + - ( if pl in cc_pos[c] then sum {p2 in cp_pos[c]} Xi[c,p2,pl] )) + + + ( if (c in c_raw and pl in cc_pos[c]) then + (( if p_imp[c] > 0 then Vr[c,pl] ) + + ( if p_dom[pl,c] > 0 then U[c,pl] ))) + + >= if (c in c_final and pl in cp_pos[c]) then sum {r in region} Xf[c,pl,r]; + + # For each commodity at each plant: sum of + # (1) production or consumption at plant, + # (2) inter-plant shipments in or out, + # (3) import and domestic purchases (raw only) + # is >= 0 for raw materials and intermediates; + # is >= the total shipped for final products + +subject to cc {pl in plant, u in m_pos[pl]}: + + sum {pr in p_pos[pl]} util[u,pr] * Z[pl,pr] <= util_pct * icap[u,pl]; + + # For each productive unit at each plant, + # total utilization by all processes + # may not exceed the unit's capacity + +subject to ap: + + Psip = sum {c in c_raw, pl in cc_pos[c]} p_dom[pl,c] * U[c,pl]; + + # Psip is the cost of domestic raw materials, + # summed over all plants that consume them + +subject to al: + + Psil = sum {c in c_final} ( + + sum {pl in cp_pos[c], r in region} + tran_final[pl,r] * Xf[c,pl,r] + + + sum {po in port, r in region} tran_import[r,po] * Vf[c,r,po] ) + + + sum {c in c_ship, p1 in cp_pos[c], p2 in cc_pos[c]} + tran_inter[p1,p2] * Xi[c,p1,p2] + + + sum {c in c_raw, pl in cc_pos[c]: p_imp[c] > 0} + tran_raw[pl] * Vr[c,pl]; + + # Total transport cost is sum of shipping costs for + # (1) all final products from all plants, + # (2) all imports of final products, + # (3) all intermediates shipped between plants, + # (4) all imports of raw materials + +subject to ai: + + Psii / exch = sum {c in c_final, r in region, po in port} + p_imp[c] * Vf[c,r,po] + + + sum {c in c_raw, pl in cc_pos[c]} p_imp[c] * Vr[c,pl]; + + # Total import cost -- at exchange rate -- + # is sum of import costs for final products + # in each region and raw materials at each plant + +### DATA ### + +data; + +set center := ASWAN HELWAN ASSIOUT KAFR_EL_ZT ABU_ZAABAL ABU_KIR TALKHA SUEZ ; + +set port := ABU_KIR ; + +set plant := ASWAN HELWAN ASSIOUT KAFR_EL_ZT ABU_ZAABAL ; + +set region := ALEXANDRIA BEHERA GHARBIA KAFR_EL_SH DAKAHLIA DAMIETTA + SHARKIA ISMAILIA SUEZ MENOUFIA KALUBIA GIZA BENI_SUEF FAYOUM + MINIA ASSIOUT NEW_VALLEY SOHAG QUENA ASWAN ; + +set unit := SULF_A_S SULF_A_P NITR_ACID AMM_ELEC AMM_C_GAS C_AMM_NITR + AMM_SULF SSP ; + +set proc := SULF_A_S SULF_A_P NITR_ACID AMM_ELEC AMM_C_GAS CAN_310 CAN_335 + AMM_SULF SSP_155 ; + +set nutr := N P205 ; + +set c_final := UREA CAN_260 CAN_310 CAN_335 AMM_SULF DAP SSP_155 C_250_55 + C_300_100 ; + +set c_inter := AMMONIA NITR_ACID SULF_ACID ; + +set c_ship := AMMONIA SULF_ACID ; + +set c_raw := EL_ASWAN COKE_GAS PHOS_ROCK LIMESTONE EL_SULFUR PYRITES + ELECTRIC BF_GAS WATER STEAM BAGS ; + +set p_except[ASWAN] := CAN_335 ; +set p_except[HELWAN] := CAN_310 ; +set p_except[ASSIOUT] := ; +set p_except[KAFR_EL_ZT] := ; +set p_except[ABU_ZAABAL] := ; + +param cf75 default 0.0 : + + CAN_260 CAN_310 CAN_335 AMM_SULF UREA := + +ALEXANDRIA . . 5.0 3.0 1.0 +ASSIOUT 1.0 20.0 26.0 1.0 27.0 +ASWAN . 40.0 . . . +BEHERA 1.0 . 25.0 90.0 35.0 +BENI_SUEF 1.0 . 15.0 1.0 20.0 +DAKAHLIA 1.0 . 26.0 60.0 20.0 +DAMIETTA . . 2.0 15.0 8.0 +FAYOUM 1.0 . 20.0 6.0 20.0 +GHARBIA . . 17.0 60.0 28.0 +GIZA . . 40.0 6.0 2.0 +ISMAILIA . . 4.0 6.0 2.0 +KAFR_EL_SH 1.0 . 10.0 45.0 22.0 +KALUBIA . . 25.0 16.0 7.0 +MENOUFIA 1.0 . 24.0 21.0 30.0 +MINIA 2.0 15.0 35.0 1.0 41.0 +NEW_VALLEY . . . . 1.0 +QUENA . 95.0 2.0 . 3.0 +SHARKIA 1.0 . 31.0 50.0 28.0 +SOHAG . 65.0 3.0 . 7.0 +SUEZ . . 1.0 . . + + : SSP_155 C_250_55 C_300_100 DAP := + +ALEXANDRIA 8.0 . . . +ASSIOUT 35.0 5.0 .1 . +ASWAN 8.0 . . . +BEHERA 64.0 1.0 .1 .1 +BENI_SUEF 13.0 3.0 . . +DAKAHLIA 52.0 1.0 . . +DAMIETTA 5.0 . . . +FAYOUM 17.0 1.0 . . +GHARBIA 57.0 1.0 .2 .1 +GIZA 14.0 1.0 .1 . +ISMAILIA 4.0 . . . +KAFR_EL_SH 25.0 2.0 .1 . +KALUBIA 22.0 1.0 . .1 +MENOUFIA 33.0 2.0 .1 .1 +MINIA 50.0 3.0 .2 .1 +NEW_VALLEY 1.0 . . . +QUENA 8.0 . . . +SHARKIA 43.0 1.0 .1 . +SOHAG 20.0 1.0 . . +SUEZ 1.0 . . . ; + +param fn default 0.0 : N P205 := + + AMM_SULF .206 . + CAN_260 .26 . + CAN_310 .31 . + CAN_335 .335 . + C_250_55 .25 .055 + C_300_100 .30 .10 + DAP .18 .46 + SSP_155 . .15 + UREA .46 . ; + +param road default 0.0 : + + ABU_KIR ABU_ZAABAL ASSIOUT ASWAN HELWAN KAFR_EL_ZT SUEZ TALKHA := + +ALEXANDRIA 16 210 607 1135 244 119 362 187 +ASSIOUT 616 420 . 518 362 504 527 518 +ASWAN 1134 938 518 . 880 1022 1045 1036 +BEHERA 76 50 547 1065 184 42 288 120 +BENI_SUEF 359 163 257 775 105 248 270 261 +DAKAHLIA 208 138 515 1033 152 58 219 3 +DAMIETTA 267 216 596 1114 233 131 286 66 +FAYOUM 341 145 308 826 88 230 252 243 +GHARBIA 150 65 485 1003 122 20 226 55 +GIZA 287 48 372 890 .9 133 169 146 +ISMAILIA 365 142 536 1054 173 241 89 146 +KAFR_EL_SH 145 105 525 1043 162 20 266 35 +KALUBIA 190 97 439 957 76 66 180 81 +MENOUFIA 157 154 472 990 109 33 213 90 +MINIA 384 288 132 650 230 372 394 386 +NEW_VALLEY 815 619 199 519 561 703 726 717 +QUENA 858 662 242 276 604 746 769 760 +SHARKIA 240 60 473 991 110 78 214 58 +SOHAG 715 519 99 419 461 603 626 617 +SUEZ 370 224 541 1059 178 246 . 298 ; + +param rail_half default 0 : + + KAFR_EL_ZT ABU_ZAABAL HELWAN ASSIOUT := + +ABU_ZAABAL 85 . . . +HELWAN 142 57 . . +ASSIOUT 504 420 362 . +ASWAN 1022 938 880 518 ; + +param : impd_barg impd_road := + +ABU_ZAABAL 210 .1 +ASSIOUT 583 0 +ASWAN 1087 10 +HELWAN 183 0 +KAFR_EL_ZT 104 6 ; + +param io default 0.0 := + + [*,AMM_C_GAS] AMMONIA 1.0 + BF_GAS -609. + COKE_GAS -2.0 + ELECTRIC -1960. + STEAM -4. + WATER -700. + + [*,AMM_ELEC] AMMONIA 1.0 + EL_ASWAN -12.0 + + [*,AMM_SULF] AMMONIA -.26 + AMM_SULF 1.0 + BAGS -22. + ELECTRIC -19. + SULF_ACID -.76 + WATER -17. + + [*,CAN_310] AMMONIA -.20 + BAGS -23. + CAN_310 1.0 + LIMESTONE -.12 + NITR_ACID -.71 + STEAM -.4 + WATER -49. + + [*,CAN_335] AMMONIA -.21 + BAGS -23. + CAN_335 1.0 + LIMESTONE -.04 + NITR_ACID -.76 + STEAM -.4 + WATER -49. + + [*,NITR_ACID] AMMONIA -.292 + ELECTRIC -231. + NITR_ACID 1.0 + WATER -.6 + + [*,SSP_155] BAGS -22. + ELECTRIC -14. + PHOS_ROCK -.62 + SSP_155 1.0 + SULF_ACID -.41 + WATER -6. + + [*,SULF_A_P] ELECTRIC -75. + PYRITES -.826 + SULF_ACID 1.0 + WATER -60. + + [*,SULF_A_S] ELECTRIC -50. + EL_SULFUR -.334 + SULF_ACID 1.0 + WATER -20. ; + +param util default 0 := + + [*,*] SULF_A_S SULF_A_S 1 SULF_A_P SULF_A_P 1 + NITR_ACID NITR_ACID 1 AMM_ELEC AMM_ELEC 1 + AMM_C_GAS AMM_C_GAS 1 SSP SSP_155 1 + C_AMM_NITR CAN_310 1 C_AMM_NITR CAN_335 1 + AMM_SULF AMM_SULF 1 ; + +param p_imp default 0.0 := + + PYRITES 17.5 AMM_SULF 75. + EL_SULFUR 55. DAP 175. + UREA 150. SSP_155 80. + CAN_260 75. C_250_55 100. + CAN_310 90. C_300_100 130. + CAN_335 100. ; + +param p_r default 0.0 := + + ELECTRIC .007 + BF_GAS .007 + WATER .031 + STEAM 1.25 + BAGS .28 ; + +param p_pr default 0.0 := + + [HELWAN,COKE_GAS] 16.0 + [ASWAN,EL_ASWAN] 1.0 + + [*,LIMESTONE] ASWAN 1.2 + HELWAN 1.2 + + [*,PHOS_ROCK] ABU_ZAABAL 4.0 + ASSIOUT 3.5 + KAFR_EL_ZT 5.0 ; + +param dcap default 0.0 := + + [ABU_ZAABAL,*] SSP 600 + SULF_A_P 227 + SULF_A_S 242 + + [ASSIOUT,*] SSP 600 + SULF_A_S 250 + + [ASWAN,*] AMM_ELEC 450 + C_AMM_NITR 1100 + NITR_ACID 800 + + [HELWAN,*] AMM_C_GAS 172 + AMM_SULF 24 + C_AMM_NITR 364 + NITR_ACID 282 + + [KAFR_EL_ZT,*] SSP 600 + SULF_A_P 50 + SULF_A_S 200 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/fctp.mod b/resources/3rdparty/glpk-4.53/examples/fctp.mod new file mode 100644 index 000000000..9d6382da6 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/fctp.mod @@ -0,0 +1,93 @@ +/* FCTP, Fixed-Charge Transportation Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Fixed-Charge Transportation Problem (FCTP) is obtained from + classical transportation problem by imposing a fixed cost on each + transportation link if there is a positive flow on that link. */ + +param m, integer, > 0; +/* number of sources */ + +param n, integer, > 0; +/* number of customers */ + +set I := 1..m; +/* set of sources */ + +set J := 1..n; +/* set of customers */ + +param supply{i in I}, >= 0; +/* supply at source i */ + +param demand{j in J}, >= 0; +/* demand at customer j */ + +param varcost{i in I, j in J}, >= 0; +/* variable cost (a cost per one unit shipped from i to j) */ + +param fixcost{i in I, j in J}, >= 0; +/* fixed cost (a cost for shipping any amount from i to j) */ + +var x{i in I, j in J}, >= 0; +/* amount shipped from source i to customer j */ + +s.t. f{i in I}: sum{j in J} x[i,j] = supply[i]; +/* observe supply at source i */ + +s.t. g{j in J}: sum{i in I} x[i,j] = demand[j]; +/* satisfy demand at customer j */ + +var y{i in I, j in J}, binary; +/* y[i,j] = 1 means some amount is shipped from i to j */ + +s.t. h{i in I, j in J}: x[i,j] <= min(supply[i], demand[j]) * y[i,j]; +/* if y[i,j] is 0, force x[i,j] to be 0 (may note that supply[i] and + demand[j] are implicit upper bounds for x[i,j] as follows from the + constraints f[i] and g[j]) */ + +minimize cost: sum{i in I, j in J} varcost[i,j] * x[i,j] + + sum{i in I, j in J} fixcost[i,j] * y[i,j]; +/* total transportation costs */ + +data; + +/* These data correspond to the instance bal8x12 from [Balinski]. */ + +/* The optimal solution is 471.55 */ + +param m := 8; + +param n := 12; + +param supply := 1 15.00, 2 20.00, 3 45.00, 4 35.00, + 5 25.00, 6 35.00, 7 10.00, 8 25.00; + +param demand := 1 20.00, 2 15.00, 3 20.00, 4 15.00, + 5 5.00, 6 20.00, 7 30.00, 8 10.00, + 9 35.00, 10 25.00, 11 10.00, 12 5.00; + +param varcost + : 1 2 3 4 5 6 7 8 9 10 11 12 := + 1 0.69 0.64 0.71 0.79 1.70 2.83 2.02 5.64 5.94 5.94 5.94 7.68 + 2 1.01 0.75 0.88 0.59 1.50 2.63 2.26 5.64 5.85 5.62 5.85 4.94 + 3 1.05 1.06 1.08 0.64 1.22 2.37 1.66 5.64 5.91 5.62 5.91 4.94 + 4 1.94 1.50 1.56 1.22 1.98 1.98 1.36 6.99 6.99 6.99 6.99 3.68 + 5 1.61 1.40 1.61 1.33 1.68 2.83 1.54 4.26 4.26 4.26 4.26 2.99 + 6 5.29 5.94 6.08 5.29 5.96 6.77 5.08 0.31 0.21 0.17 0.31 1.53 + 7 5.29 5.94 6.08 5.29 5.96 6.77 5.08 0.55 0.35 0.40 0.19 1.53 + 8 5.29 6.08 6.08 5.29 5.96 6.45 5.08 2.43 2.30 2.33 1.81 2.50 ; + +param fixcost + : 1 2 3 4 5 6 7 8 9 10 11 12 := + 1 11.0 16.0 18.0 17.0 10.0 20.0 17.0 13.0 15.0 12.0 14.0 14.0 + 2 14.0 17.0 17.0 13.0 15.0 13.0 16.0 11.0 20.0 11.0 15.0 10.0 + 3 12.0 13.0 20.0 17.0 13.0 15.0 16.0 13.0 12.0 13.0 10.0 18.0 + 4 16.0 19.0 16.0 11.0 15.0 12.0 18.0 12.0 18.0 13.0 13.0 14.0 + 5 19.0 18.0 15.0 16.0 12.0 14.0 20.0 19.0 11.0 17.0 16.0 18.0 + 6 13.0 20.0 20.0 17.0 15.0 12.0 14.0 11.0 12.0 19.0 15.0 16.0 + 7 11.0 12.0 15.0 10.0 17.0 11.0 11.0 16.0 10.0 18.0 17.0 12.0 + 8 17.0 10.0 20.0 12.0 17.0 20.0 16.0 15.0 10.0 12.0 16.0 18.0 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/food.mod b/resources/3rdparty/glpk-4.53/examples/food.mod new file mode 100644 index 000000000..cb1aa05ad --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/food.mod @@ -0,0 +1,127 @@ +/* Food Manufacture 1, section 12.1 in + * Williams, "Model Building in Mathematical Programming" + * + * Sebastian Nowozin <nowozin@gmail.com> + */ + +set oils; +set month; + +/* Buying prices of the raw oils in the next six month. */ +param buyingprices{month,oils}; + +/* Actual amount bought in each month. */ +var buys{month,oils} >= 0; + +/* Stock for each oil. */ +var stock{month,oils} >= 0; + +/* Price of the produced product */ +param productprice >= 0; +param storagecost; + +param oilhardness{oils} >= 0; + +/* Actual amount of output oil produced in each month */ +var production{m in month} >= 0; +var useoil{m in month, o in oils} >= 0; + +maximize totalprofit: + sum{m in month} productprice*production[m] + - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] + - sum{m in month, o in oils} storagecost*stock[m,o]; + +/* Constraints */ + +/* 1. Starting stock */ +s.t. startstock{o in oils}: + stock[1,o] = 500; +s.t. endstock{o in oils}: + stock[6,o] + buys[6,o] - useoil[6,o] >= 500; + +/* 2. Stock constraints */ +s.t. stocklimit{m in month, o in oils}: + stock[m,o] <= 1000; + +s.t. production1{m in month, o in oils}: + useoil[m,o] <= stock[m,o] + buys[m,o]; +s.t. production2{m1 in month, m2 in month, o in oils : m2 = m1+1}: + stock[m2,o] = stock[m1,o] + buys[m1,o] - useoil[m1,o]; + +s.t. production3a{m in month}: + sum{o in oils} oilhardness[o]*useoil[m,o] >= 3*production[m]; +s.t. production3b{m in month}: + sum{o in oils} oilhardness[o]*useoil[m,o] <= 6*production[m]; + +s.t. production4{m in month}: + production[m] = sum{o in oils} useoil[m,o]; + +/* 3. Refining constraints */ +s.t. refine1{m in month}: + useoil[m,"VEG1"]+useoil[m,"VEG2"] <= 200; +s.t. refine2{m in month}: + useoil[m,"OIL1"]+useoil[m,"OIL2"]+useoil[m,"OIL3"] <= 250; + +solve; + +for {m in month} { + printf "Month %d\n", m; + printf "PRODUCE %4.2f tons, hardness %4.2f\n", production[m], + (sum{o in oils} oilhardness[o]*useoil[m,o]) / (sum{o in oils} useoil[m,o]); + + printf "\tVEG1\tVEG2\tOIL1\tOIL2\tOIL3\n"; + printf "STOCK"; + printf "%d", m; + for {o in oils} { + printf "\t%4.2f", stock[m,o]; + } + printf "\nBUY"; + for {o in oils} { + printf "\t%4.2f", buys[m,o]; + } + printf "\nUSE"; + printf "%d", m; + for {o in oils} { + printf "\t%4.2f", useoil[m,o]; + } + printf "\n"; + printf "\n"; +} +printf "Total profit: %4.2f\n", + (sum{m in month} productprice*production[m] + - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] + - sum{m in month, o in oils} storagecost*stock[m,o]); +printf " turnover: %4.2f\n", + sum{m in month} productprice*production[m]; +printf " buying costs: %4.2f\n", + sum{m in month, o in oils} buyingprices[m,o]*buys[m,o]; +printf " storage costs: %4.2f\n", + sum{m in month, o in oils} storagecost*stock[m,o]; + + +data; + +param : oils : oilhardness := + VEG1 8.8 + VEG2 6.1 + OIL1 2.0 + OIL2 4.2 + OIL3 5.0 ; + +set month := 1 2 3 4 5 6; + +param buyingprices + +: VEG1 VEG2 OIL1 OIL2 OIL3 := + +1 110 120 130 110 115 +2 130 130 110 90 115 +3 110 140 130 100 95 +4 120 110 120 120 125 +5 100 120 150 110 105 +6 90 100 140 80 135 ; + +param productprice := 150; +param storagecost := 5; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/food2.mod b/resources/3rdparty/glpk-4.53/examples/food2.mod new file mode 100644 index 000000000..694b59462 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/food2.mod @@ -0,0 +1,150 @@ +/* Food Manufacture 2, section 12.2 in + * Williams, "Model Building in Mathematical Programming" + * + * Sebastian Nowozin <nowozin@gmail.com> + */ + +set oils; +set month; + +/* Buying prices of the raw oils in the next six month. */ +param buyingprices{month,oils}; + +/* Actual amount bought in each month. */ +var buys{month,oils} >= 0; + +/* Stock for each oil. */ +var stock{month,oils} >= 0; + +/* Price of the produced product */ +param productprice >= 0; +param storagecost; + +param oilhardness{oils} >= 0; +param M >= 0; + +/* Actual amount of output oil produced in each month */ +var production{m in month} >= 0; +var useoil{m in month, o in oils} >= 0, <= M; +var useoilb{m in month, o in oils}, binary; + +maximize totalprofit: + sum{m in month} productprice*production[m] + - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] + - sum{m in month, o in oils} storagecost*stock[m,o]; + +/* Constraints */ + +/* 1. Starting stock */ +s.t. startstock{o in oils}: + stock[1,o] = 500; +s.t. endstock{o in oils}: + stock[6,o] + buys[6,o] - useoil[6,o] >= 500; + +/* 2. Stock constraints */ +s.t. stocklimit{m in month, o in oils}: + stock[m,o] <= 1000; + +s.t. production1{m in month, o in oils}: + useoil[m,o] <= stock[m,o] + buys[m,o]; +s.t. production2{m1 in month, m2 in month, o in oils : m2 = m1+1}: + stock[m2,o] = stock[m1,o] + buys[m1,o] - useoil[m1,o]; + +s.t. production3a{m in month}: + sum{o in oils} oilhardness[o]*useoil[m,o] >= 3*production[m]; +s.t. production3b{m in month}: + sum{o in oils} oilhardness[o]*useoil[m,o] <= 6*production[m]; + +s.t. production4{m in month}: + production[m] = sum{o in oils} useoil[m,o]; + +/* 3. Refining constraints */ +s.t. refine1{m in month}: + useoil[m,"VEG1"]+useoil[m,"VEG2"] <= 200; +s.t. refine2{m in month}: + useoil[m,"OIL1"]+useoil[m,"OIL2"]+useoil[m,"OIL3"] <= 250; + +/* 4. Additional conditions: + * i) The food may never be made up of more than three oils every month + */ +s.t. useoilb_calc{m in month, o in oils}: + M*useoilb[m,o] >= useoil[m,o]; +s.t. useoilb_limit{m in month}: + sum{o in oils} useoilb[m,o] <= 3; + +/* ii) If an oil is used in a month, at least 20 tons must be used. + */ +s.t. useminimum{m in month, o in oils}: + 20*useoilb[m,o] <= useoil[m,o]; + +/* iii) If either of VEG1 or VEG2 is used in a month, OIL2 must also be used + */ +s.t. use_oil2a{m in month}: + useoilb[m,"VEG1"] <= useoilb[m,"OIL3"]; +s.t. use_oil2b{m in month}: + useoilb[m,"VEG2"] <= useoilb[m,"OIL3"]; + +solve; + +for {m in month} { + printf "Month %d\n", m; + printf "PRODUCE %4.2f tons, hardness %4.2f\n", production[m], + (sum{o in oils} oilhardness[o]*useoil[m,o]) / (sum{o in oils} useoil[m,o]); + + printf "\tVEG1\tVEG2\tOIL1\tOIL2\tOIL3\n"; + printf "STOCK"; + printf "%d", m; + for {o in oils} { + printf "\t%4.2f", stock[m,o]; + } + printf "\nBUY"; + for {o in oils} { + printf "\t%4.2f", buys[m,o]; + } + printf "\nUSE"; + printf "%d", m; + for {o in oils} { + printf "\t%4.2f", useoil[m,o]; + } + printf "\n"; + printf "\n"; +} +printf "Total profit: %4.2f\n", + (sum{m in month} productprice*production[m] + - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] + - sum{m in month, o in oils} storagecost*stock[m,o]); +printf " turnover: %4.2f\n", + sum{m in month} productprice*production[m]; +printf " buying costs: %4.2f\n", + sum{m in month, o in oils} buyingprices[m,o]*buys[m,o]; +printf " storage costs: %4.2f\n", + sum{m in month, o in oils} storagecost*stock[m,o]; + + +data; + +param : oils : oilhardness := + VEG1 8.8 + VEG2 6.1 + OIL1 2.0 + OIL2 4.2 + OIL3 5.0 ; + +set month := 1 2 3 4 5 6; + +param buyingprices + +: VEG1 VEG2 OIL1 OIL2 OIL3 := + +1 110 120 130 110 115 +2 130 130 110 90 115 +3 110 140 130 100 95 +4 120 110 120 120 125 +5 100 120 150 110 105 +6 90 100 140 80 135 ; + +param productprice := 150; +param storagecost := 5; +param M := 1000; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/gap.mod b/resources/3rdparty/glpk-4.53/examples/gap.mod new file mode 100644 index 000000000..22cdefa9f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/gap.mod @@ -0,0 +1,79 @@ +/* GAP, Generalized Assignment Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Generalized Assignment Problem (GAP) is to assign a set of jobs + to a set of agents subject to the constraints that each job must be + assigned exactly to one agent and the total resources consumed by all + jobs assigned to an agent must not exceed the agent's capacity. */ + +param m, integer, > 0; +/* number of agents */ + +param n, integer, > 0; +/* number of jobs */ + +set I := 1..m; +/* set of agents */ + +set J := 1..n; +/* set of jobs */ + +param a{i in I, j in J}, >= 0; +/* resource consumed in allocating job j to agent i */ + +param b{i in I}, >= 0; +/* resource capacity of agent i */ + +param c{i in I, j in J}, >= 0; +/* cost of allocating job j to agent i */ + +var x{i in I, j in J}, binary; +/* x[i,j] = 1 means job j is assigned to agent i */ + +s.t. one{j in J}: sum{i in I} x[i,j] = 1; +/* job j must be assigned exactly to one agent */ + +s.t. lim{i in I}: sum{j in J} a[i,j] * x[i,j] <= b[i]; +/* total amount of resources consumed by all jobs assigned to agent i + must not exceed the agent's capacity */ + +minimize obj: sum{i in I, j in J} c[i,j] * x[i,j]; +/* the objective is to find cheapest assignment (note that gap can also + be formulated as maximization problem) */ + +data; + +/* These data correspond to the instance c515-1 (gap1) from: + + I.H. Osman, "Heuristics for the Generalised Assignment Problem: + Simulated Annealing and Tabu Search Approaches", OR Spektrum, Volume + 17, 211-225, 1995 + + D. Cattrysse, M. Salomon and L.N. Van Wassenhove, "A set partitioning + heuristic for the generalized assignment problem", European Journal + of Operational Research, Volume 72, 167-174, 1994 */ + +/* The optimal solution is 261 (minimization) or 336 (maximization) */ + +param m := 5; + +param n := 15; + +param a : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 := + 1 8 15 14 23 8 16 8 25 9 17 25 15 10 8 24 + 2 15 7 23 22 11 11 12 10 17 16 7 16 10 18 22 + 3 21 20 6 22 24 10 24 9 21 14 11 14 11 19 16 + 4 20 11 8 14 9 5 6 19 19 7 6 6 13 9 18 + 5 8 13 13 13 10 20 25 16 16 17 10 10 5 12 23 ; + +param b := 1 36, 2 34, 3 38, 4 27, 5 33; + +param c : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 := + 1 17 21 22 18 24 15 20 18 19 18 16 22 24 24 16 + 2 23 16 21 16 17 16 19 25 18 21 17 15 25 17 24 + 3 16 20 16 25 24 16 17 19 19 18 20 16 17 21 24 + 4 19 19 22 22 20 16 19 17 21 19 25 23 25 25 25 + 5 18 19 15 15 21 25 16 16 23 15 22 17 19 22 24 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/glpsol.c b/resources/3rdparty/glpk-4.53/examples/glpsol.c new file mode 100644 index 000000000..b1014500e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/glpsol.c @@ -0,0 +1,10 @@ +/* glpsol.c */ + +#include <glpk.h> + +int main(int argc, const char *argv[]) +{ /* stand-alone LP/MIP solver */ + return glp_main(argc, argv); +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/graph.mod b/resources/3rdparty/glpk-4.53/examples/graph.mod new file mode 100644 index 000000000..bdcc969ac --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/graph.mod @@ -0,0 +1,98 @@ +/* graph.mod - graph visualization */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* This model creates a picture in EPS format to visualize a graph. */ + +param file, symbolic, default "graph.eps"; +/* output file to write the picture */ + +param R, default 2; +/* radius to draw vertices, in mm */ + +param n, integer, > 0; +/* number of vertices */ + +set V, default 1..n; +/* set of vertices */ + +set E, within V cross V; +/* set of edges */ + +param x{i in V}, default 50 * cos((i - 1) / card(V) * 8 * atan(1)); +param y{i in V}, default 50 * sin((i - 1) / card(V) * 8 * atan(1)); +/* x[i] and y[i] are coordinates of node i, in mm */ + +param x0 := (min{i in V} x[i]) - R - 3.0; +param y0 := (min{i in V} y[i]) - R - 3.0; +param x1 := (max{i in V} x[i]) + R + 3.0; +param y1 := (max{i in V} y[i]) + R + 3.0; + +printf "%%!PS-Adobe-3.0 EPSF-3.0\n" > file; +printf "%%%%BoundingBox: 0 0 %d %d\n", + (72 / 25.4) * (x1 - x0), (72 / 25.4) * (y1 - y0) >> file; +printf "/Helvetica findfont 6 scalefont setfont\n" >> file; +printf "/mm { 72 mul 25.4 div } def\n" >> file; + +for {(i,j) in E} +{ printf "newpath\n" >> file; + printf "%g mm %g mm moveto\n", x[i] - x0, y[i] - y0 >> file; + printf "%g mm %g mm lineto\n", x[j] - x0, y[j] - y0 >> file; + printf "closepath\n" >> file; + printf "stroke\n" >> file; +} + +for {i in V} +{ printf "newpath\n" >> file; + printf "%g mm %g mm %g mm 0 360 arc\n", + x[i] - x0, y[i] - y0, R >> file; + printf "closepath\n" >> file; + printf "gsave 1 1 1 setrgbcolor fill grestore\n" >> file; + printf "stroke\n" >> file; + printf "%g mm %g mm moveto\n", + x[i] - (if i <= 9 then 1.2 else 1.8) - x0, + y[i] - 0.8 - y0 >> file; + printf "( %d ) show\n", i >> file; +} + +printf "showpage\n" >> file; +printf "%%%%EOF\n" >> file; + +data; + +param +: V : x y := + 1 0 40 + 2 38 12 + 3 24 -32 + 4 -24 -32 + 5 -38 12 + 6 -19 26 + 7 19 26 + 8 31 -10 + 9 0 -32 + 10 -31 -10 + 11 -9 12 + 12 9 12 + 13 14 -5 + 14 0 -15 + 15 -14 -5 + 16 0 0 ; + +set E := + (1,*) 6 10 16 12 7 + (2,*) 7 6 16 13 8 + (3,*) 8 7 16 14 9 + (4,*) 9 8 16 15 10 + (5,*) 10 9 16 11 6 + (6,*) 14 + (7,*) 15 + (8,*) 11 + (9,*) 12 + (10,*) 13 + (11,*) 12 15 + (12,*) 13 + (13,*) 14 + (14,*) 15 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/hashi.mod b/resources/3rdparty/glpk-4.53/examples/hashi.mod new file mode 100644 index 000000000..48e8d9f7f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/hashi.mod @@ -0,0 +1,168 @@ +/* A solver for the Japanese number-puzzle Hashiwokakero + * (http://en.wikipedia.org/wiki/Hashiwokakero) + * + * Sebastian Nowozin <nowozin@gmail.com>, 13th January 2009 + */ + +param n := 25; +set rows := 1..n; +set cols := 1..n; +param givens{rows, cols}, integer, >= 0, <= 8, default 0; + +/* Set of vertices as (row,col) coordinates */ +set V := { (i,j) in { rows, cols }: givens[i,j] != 0 }; + +/* Set of feasible horizontal edges from (i,j) to (k,l) rightwards */ +set Eh := { (i,j,k,l) in { V, V }: + i = k and j < l and # Same row and left to right + card({ (s,t) in V: s = i and t > j and t < l }) = 0 # No vertex inbetween + }; + +/* Set of feasible vertical edges from (i,j) to (k,l) downwards */ +set Ev := { (i,j,k,l) in { V, V }: + j = l and i < k and # Same column and top to bottom + card({ (s,t) in V: t = j and s > i and s < k }) = 0 # No vertex inbetween + }; + +set E := Eh union Ev; + +/* Indicators: use edge once/twice */ +var xe1{E}, binary; +var xe2{E}, binary; + +/* Constraint: Do not use edge or do use once or do use twice */ +s.t. edge_sel{(i,j,k,l) in E}: + xe1[i,j,k,l] + xe2[i,j,k,l] <= 1; + +/* Constraint: There must be as many edges used as the node value */ +s.t. satisfy_vertex_demand{(s,t) in V}: + sum{(i,j,k,l) in E: (i = s and j = t) or (k = s and l = t)} + (xe1[i,j,k,l] + 2.0*xe2[i,j,k,l]) = givens[s,t]; + +/* Constraint: No crossings */ +s.t. no_crossing1{(i,j,k,l) in Eh, (s,t,u,v) in Ev: + s < i and u > i and j < t and l > t}: + xe1[i,j,k,l] + xe1[s,t,u,v] <= 1; +s.t. no_crossing2{(i,j,k,l) in Eh, (s,t,u,v) in Ev: + s < i and u > i and j < t and l > t}: + xe1[i,j,k,l] + xe2[s,t,u,v] <= 1; +s.t. no_crossing3{(i,j,k,l) in Eh, (s,t,u,v) in Ev: + s < i and u > i and j < t and l > t}: + xe2[i,j,k,l] + xe1[s,t,u,v] <= 1; +s.t. no_crossing4{(i,j,k,l) in Eh, (s,t,u,v) in Ev: + s < i and u > i and j < t and l > t}: + xe2[i,j,k,l] + xe2[s,t,u,v] <= 1; + + +/* Model connectivity by auxiliary network flow problem: + * One vertex becomes a target node and all other vertices send a unit flow + * to it. The edge selection variables xe1/xe2 are VUB constraints and + * therefore xe1/xe2 select the feasible graph for the max-flow problems. + */ +set node_target := { (s,t) in V: + card({ (i,j) in V: i < s or (i = s and j < t) }) = 0}; +set node_sources := { (s,t) in V: (s,t) not in node_target }; + +var flow_forward{ E }, >= 0; +var flow_backward{ E }, >= 0; +s.t. flow_conservation{ (s,t) in node_target, (p,q) in V }: + /* All incoming flows */ + - sum{(i,j,k,l) in E: k = p and l = q} flow_forward[i,j,k,l] + - sum{(i,j,k,l) in E: i = p and j = q} flow_backward[i,j,k,l] + /* All outgoing flows */ + + sum{(i,j,k,l) in E: k = p and l = q} flow_backward[i,j,k,l] + + sum{(i,j,k,l) in E: i = p and j = q} flow_forward[i,j,k,l] + = 0 + (if (p = s and q = t) then card(node_sources) else -1); + +/* Variable-Upper-Bound (VUB) constraints: xe1/xe2 bound the flows. + */ +s.t. connectivity_vub1{(i,j,k,l) in E}: + flow_forward[i,j,k,l] <= card(node_sources)*(xe1[i,j,k,l] + xe2[i,j,k,l]); +s.t. connectivity_vub2{(i,j,k,l) in E}: + flow_backward[i,j,k,l] <= card(node_sources)*(xe1[i,j,k,l] + xe2[i,j,k,l]); + +/* A feasible solution is enough + */ +minimize cost: 0; + +solve; + +/* Output solution graphically */ +printf "\nSolution:\n"; +for { row in rows } { + for { col in cols } { + /* First print this cell information: givens or space */ + printf{0..0: givens[row,col] != 0} "%d", givens[row,col]; + printf{0..0: givens[row,col] = 0 and + card({(i,j,k,l) in Eh: i = row and col >= j and col < l and + xe1[i,j,k,l] = 1}) = 1} "-"; + printf{0..0: givens[row,col] = 0 and + card({(i,j,k,l) in Eh: i = row and col >= j and col < l and + xe2[i,j,k,l] = 1}) = 1} "="; + printf{0..0: givens[row,col] = 0 + and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and + xe1[i,j,k,l] = 1}) = 1} "|"; + printf{0..0: givens[row,col] = 0 + and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and + xe2[i,j,k,l] = 1}) = 1} '"'; + printf{0..0: givens[row,col] = 0 + and card({(i,j,k,l) in Eh: i = row and col >= j and col < l and + (xe1[i,j,k,l] = 1 or xe2[i,j,k,l] = 1)}) = 0 + and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and + (xe1[i,j,k,l] = 1 or xe2[i,j,k,l] = 1)}) = 0} " "; + + /* Now print any edges */ + printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe1[i,j,k,l] = 1} "-"; + printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe2[i,j,k,l] = 1} "="; + + printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and + xe1[i,j,k,l] = 0 and xe2[i,j,k,l] = 0} " "; + printf{0..0: card({(i,j,k,l) in Eh: i = row and col >= j and col < l}) = 0} " "; + } + printf "\n"; + for { col in cols } { + printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe1[i,j,k,l] = 1} "|"; + printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe2[i,j,k,l] = 1} '"'; + printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and + xe1[i,j,k,l] = 0 and xe2[i,j,k,l] = 0} " "; + /* No vertical edges: skip also a field */ + printf{0..0: card({(i,j,k,l) in Ev: j = col and row >= i and row < k}) = 0} " "; + printf " "; + } + printf "\n"; +} + +data; + +/* This is a difficult 25x25 Hashiwokakero. + */ +param givens : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 +25 := + 1 2 . 2 . 2 . . 2 . 2 . . 2 . . . . 2 . 2 . 2 . 2 . + 2 . 1 . . . . 2 . . . 4 . . 5 . 2 . . 1 . 2 . 2 . 1 + 3 2 . . 5 . 4 . . 3 . . . . . 1 . . 4 . 5 . 1 . 1 . + 4 . . . . . . . . . . . 1 . 3 . . 1 . . . . . . . . + 5 2 . . 6 . 6 . . 8 . 5 . 2 . . 3 . 5 . 7 . . 2 . . + 6 . 1 . . . . . . . . . 1 . . 2 . . . . . 1 . . . 3 + 7 2 . . . . 5 . . 6 . 4 . . 2 . . . 2 . 5 . 4 . 2 . + 8 . 2 . 2 . . . . . . . . . . . 3 . . 3 . . . 1 . 2 + 9 . . . . . . . . . . 4 . 2 . 2 . . 1 . . . 3 . 1 . + 10 2 . 3 . . 6 . . 2 . . . . . . . . . . 3 . . . . . + 11 . . . . 1 . . 2 . . 5 . . 1 . 4 . 3 . . . . 2 . 4 + 12 . . 2 . . 1 . . . . . . 5 . 4 . . . . 4 . 3 . . . + 13 2 . . . 3 . 1 . . . . . . . . 3 . . 5 . 5 . . 2 . + 14 . . . . . 2 . 5 . . 7 . 5 . 3 . 1 . . 1 . . 1 . 4 + 15 2 . 5 . 3 . . . . 1 . 2 . 1 . . . . 2 . 4 . . 2 . + 16 . . . . . 1 . . . . . . . . . . 2 . . 2 . 1 . . 3 + 17 2 . 6 . 6 . . 2 . . 2 . 2 . 5 . . . . . 2 . . . . + 18 . . . . . 1 . . . 3 . . . . . 1 . . 1 . . 4 . 3 . + 19 . . 4 . 5 . . 2 . . . 2 . . 6 . 6 . . 3 . . . . 3 + 20 2 . . . . . . . . . 2 . . 1 . . . . . . 1 . . 1 . + 21 . . 3 . . 3 . 5 . 5 . . 4 . 6 . 7 . . 4 . 6 . . 4 + 22 2 . . . 3 . 5 . 2 . 1 . . . . . . . . . . . . . . + 23 . . . . . . . . . 1 . . . . . . 3 . 2 . . 5 . . 5 + 24 2 . 3 . 3 . 5 . 4 . 3 . 3 . 4 . . 2 . 2 . . . 1 . + 25 . 1 . 2 . 2 . . . 2 . 2 . . . 2 . . . . 2 . 2 . 2 + ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/huge.mod b/resources/3rdparty/glpk-4.53/examples/huge.mod new file mode 100644 index 000000000..a7d17e4c5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/huge.mod @@ -0,0 +1,25 @@ +/*Arithmetic Mean of a large number of Integers + - or - solve a very large constraint matrix + over 1 million rows and columns + Nigel_Galloway@operamail.com + March 18th., 2008. +*/ + +param e := 20; +/* set Sample := {-2**e..2**e-1}; */ +set Sample := {1..2**e-1}; + +var Mean; +var E{z in Sample}; + +/* sum of variances is zero */ +zumVariance: sum{z in Sample} E[z] = 0; + +/* Mean + variance[n] = Sample[n] */ +variances{z in Sample}: Mean + E[z] = z; + +solve; + +printf "The arithmetic mean of the integers from 1 to %d is %f\n", 2**e-1, Mean; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/iptsamp.c b/resources/3rdparty/glpk-4.53/examples/iptsamp.c new file mode 100644 index 000000000..d622d7361 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/iptsamp.c @@ -0,0 +1,17 @@ +/* iptsamp.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *P; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_interior(P, NULL); + glp_print_ipt(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/jssp.mod b/resources/3rdparty/glpk-4.53/examples/jssp.mod new file mode 100644 index 000000000..7ee51b989 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/jssp.mod @@ -0,0 +1,114 @@ +/* JSSP, Job-Shop Scheduling Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Job-Shop Scheduling Problem (JSSP) is to schedule a set of jobs + on a set of machines, subject to the constraint that each machine can + handle at most one job at a time and the fact that each job has a + specified processing order through the machines. The objective is to + schedule the jobs so as to minimize the maximum of their completion + times. + + Reference: + D. Applegate and W. Cook, "A Computational Study of the Job-Shop + Scheduling Problem", ORSA J. On Comput., Vol. 3, No. 2, Spring 1991, + pp. 149-156. */ + +param n, integer, > 0; +/* number of jobs */ + +param m, integer, > 0; +/* number of machines */ + +set J := 1..n; +/* set of jobs */ + +set M := 1..m; +/* set of machines */ + +param sigma{j in J, t in 1..m}, in M; +/* permutation of the machines, which represents the processing order + of j through the machines: j must be processed first on sigma[j,1], + then on sigma[j,2], etc. */ + +check{j in J, t1 in 1..m, t2 in 1..m: t1 <> t2}: + sigma[j,t1] != sigma[j,t2]; +/* sigma must be permutation */ + +param p{j in J, a in M}, >= 0; +/* processing time of j on a */ + +var x{j in J, a in M}, >= 0; +/* starting time of j on a */ + +s.t. ord{j in J, t in 2..m}: + x[j, sigma[j,t]] >= x[j, sigma[j,t-1]] + p[j, sigma[j,t-1]]; +/* j can be processed on sigma[j,t] only after it has been completely + processed on sigma[j,t-1] */ + +/* The disjunctive condition that each machine can handle at most one + job at a time is the following: + + x[i,a] >= x[j,a] + p[j,a] or x[j,a] >= x[i,a] + p[i,a] + + for all i, j in J, a in M. This condition is modeled through binary + variables Y as shown below. */ + +var Y{i in J, j in J, a in M}, binary; +/* Y[i,j,a] is 1 if i scheduled before j on machine a, and 0 if j is + scheduled before i */ + +param K := sum{j in J, a in M} p[j,a]; +/* some large constant */ + +display K; + +s.t. phi{i in J, j in J, a in M: i <> j}: + x[i,a] >= x[j,a] + p[j,a] - K * Y[i,j,a]; +/* x[i,a] >= x[j,a] + p[j,a] iff Y[i,j,a] is 0 */ + +s.t. psi{i in J, j in J, a in M: i <> j}: + x[j,a] >= x[i,a] + p[i,a] - K * (1 - Y[i,j,a]); +/* x[j,a] >= x[i,a] + p[i,a] iff Y[i,j,a] is 1 */ + +var z; +/* so-called makespan */ + +s.t. fin{j in J}: z >= x[j, sigma[j,m]] + p[j, sigma[j,m]]; +/* which is the maximum of the completion times of all the jobs */ + +minimize obj: z; +/* the objective is to make z as small as possible */ + +data; + +/* These data correspond to the instance ft06 (mt06) from: + + H. Fisher, G.L. Thompson (1963), Probabilistic learning combinations + of local job-shop scheduling rules, J.F. Muth, G.L. Thompson (eds.), + Industrial Scheduling, Prentice Hall, Englewood Cliffs, New Jersey, + 225-251 */ + +/* The optimal solution is 55 */ + +param n := 6; + +param m := 6; + +param sigma : 1 2 3 4 5 6 := + 1 3 1 2 4 6 5 + 2 2 3 5 6 1 4 + 3 3 4 6 1 2 5 + 4 2 1 3 4 5 6 + 5 3 2 5 6 1 4 + 6 2 4 6 1 5 3 ; + +param p : 1 2 3 4 5 6 := + 1 3 6 1 7 6 3 + 2 10 8 5 4 10 10 + 3 9 1 5 4 7 8 + 4 5 5 5 3 8 9 + 5 3 3 9 1 5 4 + 6 10 3 1 3 4 9 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/magic.mod b/resources/3rdparty/glpk-4.53/examples/magic.mod new file mode 100644 index 000000000..d1e64d018 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/magic.mod @@ -0,0 +1,54 @@ +/* MAGIC, Magic Square */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* In recreational mathematics, a magic square of order n is an + arrangement of n^2 numbers, usually distinct integers, in a square, + such that n numbers in all rows, all columns, and both diagonals sum + to the same constant. A normal magic square contains the integers + from 1 to n^2. + + (From Wikipedia, the free encyclopedia.) */ + +param n, integer, > 0, default 4; +/* square order */ + +set N := 1..n^2; +/* integers to be placed */ + +var x{i in 1..n, j in 1..n, k in N}, binary; +/* x[i,j,k] = 1 means that cell (i,j) contains integer k */ + +s.t. a{i in 1..n, j in 1..n}: sum{k in N} x[i,j,k] = 1; +/* each cell must be assigned exactly one integer */ + +s.t. b{k in N}: sum{i in 1..n, j in 1..n} x[i,j,k] = 1; +/* each integer must be assigned exactly to one cell */ + +var s; +/* the magic sum */ + +s.t. r{i in 1..n}: sum{j in 1..n, k in N} k * x[i,j,k] = s; +/* the sum in each row must be the magic sum */ + +s.t. c{j in 1..n}: sum{i in 1..n, k in N} k * x[i,j,k] = s; +/* the sum in each column must be the magic sum */ + +s.t. d: sum{i in 1..n, k in N} k * x[i,i,k] = s; +/* the sum in the diagonal must be the magic sum */ + +s.t. e: sum{i in 1..n, k in N} k * x[i,n-i+1,k] = s; +/* the sum in the co-diagonal must be the magic sum */ + +solve; + +printf "\n"; +printf "Magic sum is %d\n", s; +printf "\n"; +for{i in 1..n} +{ printf{j in 1..n} "%3d", sum{k in N} k * x[i,j,k]; + printf "\n"; +} +printf "\n"; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/maxcut.mod b/resources/3rdparty/glpk-4.53/examples/maxcut.mod new file mode 100644 index 000000000..db30b92e5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/maxcut.mod @@ -0,0 +1,85 @@ +/* MAXCUT, Maximum Cut Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Maximum Cut Problem in a network G = (V, E), where V is a set + of nodes, E is a set of edges, is to find the partition of V into + disjoint sets V1 and V2, which maximizes the sum of edge weights + w(e), where edge e has one endpoint in V1 and other endpoint in V2. + + Reference: + Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: + A guide to the theory of NP-completeness [Network design, Cuts and + Connectivity, Maximum Cut, ND16]. */ + +set E, dimen 2; +/* set of edges */ + +param w{(i,j) in E}, >= 0, default 1; +/* w[i,j] is weight of edge (i,j) */ + +set V := (setof{(i,j) in E} i) union (setof{(i,j) in E} j); +/* set of nodes */ + +var x{i in V}, binary; +/* x[i] = 0 means that node i is in set V1 + x[i] = 1 means that node i is in set V2 */ + +/* We need to include in the objective function only that edges (i,j) + from E, for which x[i] != x[j]. This can be modeled through binary + variables s[i,j] as follows: + + s[i,j] = x[i] xor x[j] = (x[i] + x[j]) mod 2, (1) + + where s[i,j] = 1 iff x[i] != x[j], that leads to the following + objective function: + + z = sum{(i,j) in E} w[i,j] * s[i,j]. (2) + + To describe "exclusive or" (1) we could think that s[i,j] is a minor + bit of the sum x[i] + x[j]. Then introducing binary variables t[i,j], + which represent a major bit of the sum x[i] + x[j], we can write: + + x[i] + x[j] = s[i,j] + 2 * t[i,j]. (3) + + An easy check shows that conditions (1) and (3) are equivalent. + + Note that condition (3) can be simplified by eliminating variables + s[i,j]. Indeed, from (3) it follows that: + + s[i,j] = x[i] + x[j] - 2 * t[i,j]. (4) + + Since the expression in the right-hand side of (4) is integral, this + condition can be rewritten in the equivalent form: + + 0 <= x[i] + x[j] - 2 * t[i,j] <= 1. (5) + + (One might note that (5) means t[i,j] = x[i] and x[j].) + + Substituting s[i,j] from (4) to (2) leads to the following objective + function: + + z = sum{(i,j) in E} w[i,j] * (x[i] + x[j] - 2 * t[i,j]), (6) + + which does not include variables s[i,j]. */ + +var t{(i,j) in E}, binary; +/* t[i,j] = x[i] and x[j] = (x[i] + x[j]) div 2 */ + +s.t. xor{(i,j) in E}: 0 <= x[i] + x[j] - 2 * t[i,j] <= 1; +/* see (4) */ + +maximize z: sum{(i,j) in E} w[i,j] * (x[i] + x[j] - 2 * t[i,j]); +/* see (6) */ + +data; + +/* In this example the network has 15 nodes and 22 edges. */ + +/* Optimal solution is 20 */ + +set E := + 1 2, 1 5, 2 3, 2 6, 3 4, 3 8, 4 9, 5 6, 5 7, 6 8, 7 8, 7 12, 8 9, + 8 12, 9 10, 9 14, 10 11, 10 14, 11 15, 12 13, 13 14, 14 15; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/maxflow.mod b/resources/3rdparty/glpk-4.53/examples/maxflow.mod new file mode 100644 index 000000000..20dfc3ee2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/maxflow.mod @@ -0,0 +1,83 @@ +/* MAXFLOW, Maximum Flow Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Maximum Flow Problem in a network G = (V, E), where V is a set + of nodes, E within V x V is a set of arcs, is to maximize the flow + from one given node s (source) to another given node t (sink) subject + to conservation of flow constraints at each node and flow capacities + on each arc. */ + +param n, integer, >= 2; +/* number of nodes */ + +set V, default {1..n}; +/* set of nodes */ + +set E, within V cross V; +/* set of arcs */ + +param a{(i,j) in E}, > 0; +/* a[i,j] is capacity of arc (i,j) */ + +param s, symbolic, in V, default 1; +/* source node */ + +param t, symbolic, in V, != s, default n; +/* sink node */ + +var x{(i,j) in E}, >= 0, <= a[i,j]; +/* x[i,j] is elementary flow through arc (i,j) to be found */ + +var flow, >= 0; +/* total flow from s to t */ + +s.t. node{i in V}: +/* node[i] is conservation constraint for node i */ + + sum{(j,i) in E} x[j,i] + (if i = s then flow) + /* summary flow into node i through all ingoing arcs */ + + = /* must be equal to */ + + sum{(i,j) in E} x[i,j] + (if i = t then flow); + /* summary flow from node i through all outgoing arcs */ + +maximize obj: flow; +/* objective is to maximize the total flow through the network */ + +solve; + +printf{1..56} "="; printf "\n"; +printf "Maximum flow from node %s to node %s is %g\n\n", s, t, flow; +printf "Starting node Ending node Arc capacity Flow in arc\n"; +printf "------------- ----------- ------------ -----------\n"; +printf{(i,j) in E: x[i,j] != 0}: "%13s %11s %12g %11g\n", i, j, + a[i,j], x[i,j]; +printf{1..56} "="; printf "\n"; + +data; + +/* These data correspond to an example from [Christofides]. */ + +/* Optimal solution is 29 */ + +param n := 9; + +param : E : a := + 1 2 14 + 1 4 23 + 2 3 10 + 2 4 9 + 3 5 12 + 3 8 18 + 4 5 26 + 5 2 11 + 5 6 25 + 5 7 4 + 6 7 7 + 6 8 8 + 7 9 15 + 8 9 20; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/mfasp.mod b/resources/3rdparty/glpk-4.53/examples/mfasp.mod new file mode 100644 index 000000000..b4382818a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/mfasp.mod @@ -0,0 +1,62 @@ +/* MFASP, Minimum Feedback Arc Set Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Minimum Feedback Arc Set Problem for a given directed graph + G = (V, E), where V is a set of vertices and E is a set of arcs, is + to find a minimal subset of arcs, which being removed from the graph + make it acyclic. + + Reference: + Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: + A guide to the theory of NP-completeness [Graph Theory, Covering and + Partitioning, Minimum Feedback Arc Set, GT9]. */ + +param n, integer, >= 0; +/* number of vertices */ + +set V, default 1..n; +/* set of vertices */ + +set E, within V cross V, +default setof{i in V, j in V: i <> j and Uniform(0,1) <= 0.15} (i,j); +/* set of arcs */ + +printf "Graph has %d vertices and %d arcs\n", card(V), card(E); + +var x{(i,j) in E}, binary; +/* x[i,j] = 1 means that (i->j) is a feedback arc */ + +/* It is known that a digraph G = (V, E) is acyclic if and only if its + vertices can be assigned numbers from 1 to |V| in such a way that + k[i] + 1 <= k[j] for every arc (i->j) in E, where k[i] is a number + assigned to vertex i. We may use this condition to require that the + digraph G = (V, E \ E'), where E' is a subset of feedback arcs, is + acyclic. */ + +var k{i in V}, >= 1, <= card(V); +/* k[i] is a number assigned to vertex i */ + +s.t. r{(i,j) in E}: k[j] - k[i] >= 1 - card(V) * x[i,j]; +/* note that x[i,j] = 1 leads to a redundant constraint */ + +minimize obj: sum{(i,j) in E} x[i,j]; +/* the objective is to minimize the cardinality of a subset of feedback + arcs */ + +solve; + +printf "Minimum feedback arc set:\n"; +printf{(i,j) in E: x[i,j]} "%d %d\n", i, j; + +data; + +/* The optimal solution is 3 */ + +param n := 15; + +set E := 1 2, 2 3, 3 4, 3 8, 4 9, 5 1, 6 5, 7 5, 8 6, 8 7, 8 9, 9 10, + 10 11, 10 14, 11 15, 12 7, 12 8, 12 13, 13 8, 13 12, 13 14, + 14 9, 15 14; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/mfvsp.mod b/resources/3rdparty/glpk-4.53/examples/mfvsp.mod new file mode 100644 index 000000000..a03009dea --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/mfvsp.mod @@ -0,0 +1,62 @@ +/* MFVSP, Minimum Feedback Vertex Set Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Minimum Feedback Vertex Set Problem for a given directed graph + G = (V, E), where V is a set of vertices and E is a set of arcs, is + to find a minimal subset of vertices, which being removed from the + graph make it acyclic. + + Reference: + Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: + A guide to the theory of NP-completeness [Graph Theory, Covering and + Partitioning, Minimum Feedback Vertex Set, GT8]. */ + +param n, integer, >= 0; +/* number of vertices */ + +set V, default 1..n; +/* set of vertices */ + +set E, within V cross V, +default setof{i in V, j in V: i <> j and Uniform(0,1) <= 0.15} (i,j); +/* set of arcs */ + +printf "Graph has %d vertices and %d arcs\n", card(V), card(E); + +var x{i in V}, binary; +/* x[i] = 1 means that i is a feedback vertex */ + +/* It is known that a digraph G = (V, E) is acyclic if and only if its + vertices can be assigned numbers from 1 to |V| in such a way that + k[i] + 1 <= k[j] for every arc (i->j) in E, where k[i] is a number + assigned to vertex i. We may use this condition to require that the + digraph G = (V, E \ E'), where E' is a subset of feedback arcs, is + acyclic. */ + +var k{i in V}, >= 1, <= card(V); +/* k[i] is a number assigned to vertex i */ + +s.t. r{(i,j) in E}: k[j] - k[i] >= 1 - card(V) * (x[i] + x[j]); +/* note that x[i] = 1 or x[j] = 1 leads to a redundant constraint */ + +minimize obj: sum{i in V} x[i]; +/* the objective is to minimize the cardinality of a subset of feedback + vertices */ + +solve; + +printf "Minimum feedback vertex set:\n"; +printf{i in V: x[i]} "%d\n", i; + +data; + +/* The optimal solution is 3 */ + +param n := 15; + +set E := 1 2, 2 3, 3 4, 3 8, 4 9, 5 1, 6 5, 7 5, 8 6, 8 7, 8 9, 9 10, + 10 11, 10 14, 11 15, 12 7, 12 8, 12 13, 13 8, 13 12, 13 14, + 14 9, 15 14; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/min01ks.mod b/resources/3rdparty/glpk-4.53/examples/min01ks.mod new file mode 100644 index 000000000..4baa3f406 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/min01ks.mod @@ -0,0 +1,111 @@ +/* min01ks.mod - finding minimal equivalent 0-1 knapsack inequality */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* It is obvious that for a given 0-1 knapsack inequality + + a[1] x[1] + ... + a[n] x[n] <= b, x[j] in {0, 1} (1) + + there exist infinitely many equivalent inequalities with exactly the + same feasible solutions. + + Given a[j]'s and b this model allows to find an inequality + + alfa[1] x[1] + ... + alfa[n] x[n] <= beta, x[j] in {0, 1}, (2) + + which is equivalent to (1) and where alfa[j]'s and beta are smallest + non-negative integers. + + This model has the following formulation: + + minimize + + z = |alfa[1]| + ... + |alfa[n]| + |beta| = (3) + + = alfa[1] + ... + alfa[n] + beta + + subject to + + alfa[1] x[1] + ... + alfa[n] x[n] <= beta (4) + + for all x satisfying to (1) + + alfa[1] x[1] + ... + alfa[n] x[n] >= beta + 1 (5) + + for all x not satisfying to (1) + + alfa[1], ..., alfa[n], beta are non-negative integers. + + Note that this model has n+1 variables and 2^n constraints. + + It is interesting, as noticed in [1] and explained in [2], that + in most cases LP relaxation of the MIP formulation above has integer + optimal solution. + + References + + 1. G.H.Bradley, P.L.Hammer, L.Wolsey, "Coefficient Reduction for + Inequalities in 0-1 Variables", Math.Prog.7 (1974), 263-282. + + 2. G.J.Koehler, "A Study on Coefficient Reduction of Binary Knapsack + Inequalities", University of Florida, 2001. */ + +param n, integer, > 0; +/* number of variables in the knapsack inequality */ + +set N := 1..n; +/* set of knapsack items */ + +/* all binary n-vectors are numbered by 0, 1, ..., 2^n-1, where vector + 0 is 00...00, vector 1 is 00...01, etc. */ + +set U := 0..2^n-1; +/* set of numbers of all binary n-vectors */ + +param x{i in U, j in N}, binary, := (i div 2^(j-1)) mod 2; +/* x[i,j] is j-th component of i-th binary n-vector */ + +param a{j in N}, >= 0; +/* original coefficients */ + +param b, >= 0; +/* original right-hand side */ + +set D := setof{i in U: sum{j in N} a[j] * x[i,j] <= b} i; +/* set of numbers of binary n-vectors, which (vectors) are feasible, + i.e. satisfy to the original knapsack inequality (1) */ + +var alfa{j in N}, integer, >= 0; +/* coefficients to be found */ + +var beta, integer, >= 0; +/* right-hand side to be found */ + +minimize z: sum{j in N} alfa[j] + beta; /* (3) */ + +phi{i in D}: sum{j in N} alfa[j] * x[i,j] <= beta; /* (4) */ + +psi{i in U diff D}: sum{j in N} alfa[j] * x[i,j] >= beta + 1; /* (5) */ + +solve; + +printf "\nOriginal 0-1 knapsack inequality:\n"; +for {j in 1..n} printf (if j = 1 then "" else " + ") & "%g x%d", + a[j], j; +printf " <= %g\n", b; +printf "\nMinimized equivalent inequality:\n"; +for {j in 1..n} printf (if j = 1 then "" else " + ") & "%g x%d", + alfa[j], j; +printf " <= %g\n\n", beta; + +data; + +/* These data correspond to the very first example from [1]. */ + +param n := 8; + +param a := [1]65, [2]64, [3]41, [4]22, [5]13, [6]12, [7]8, [8]2; + +param b := 80; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/misp.mod b/resources/3rdparty/glpk-4.53/examples/misp.mod new file mode 100644 index 000000000..b2b1f6b94 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/misp.mod @@ -0,0 +1,665 @@ +/* MISP, Maximum Independent Set Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* Let G = (V,E) be an undirected graph with vertex set V and edge set + * E. Vertices u, v in V are non-adjacent if (u,v) not in E. A subset + * of the vertices S within V is independent if all vertices in S are + * pairwise non-adjacent. The Maximum Independent Set Problem (MISP) is + * to find an independent set having the largest cardinality. */ + +param n, integer, > 0; +/* number of vertices */ + +set V := 1..n; +/* set of vertices */ + +set E within V cross V; +/* set of edges */ + +var x{i in V}, binary; +/* x[i] = 1 means vertex i belongs to independent set */ + +s.t. edge{(i,j) in E}: x[i] + x[j] <= 1; +/* if there is edge (i,j), vertices i and j cannot belong to the same + independent set */ + +maximize obj: sum{i in V} x[i]; +/* the objective is to maximize the cardinality of independent set */ + +data; + +/* These data corresponds to the test instance from: + * + * M.G.C. Resende, T.A.Feo, S.H.Smith, "Algorithm 787 -- FORTRAN + * subroutines for approximate solution of the maximum independent set + * problem using GRASP," Trans. on Math. Softw., Vol. 24, No. 4, + * December 1998, pp. 386-394. */ + +/* The optimal solution is 7. */ + +param n := 50; + +set E := + 1 2 + 1 3 + 1 5 + 1 7 + 1 8 + 1 12 + 1 15 + 1 16 + 1 19 + 1 20 + 1 21 + 1 22 + 1 28 + 1 30 + 1 34 + 1 35 + 1 37 + 1 41 + 1 42 + 1 47 + 1 50 + 2 3 + 2 5 + 2 6 + 2 7 + 2 8 + 2 9 + 2 10 + 2 13 + 2 17 + 2 19 + 2 20 + 2 21 + 2 23 + 2 25 + 2 26 + 2 29 + 2 31 + 2 35 + 2 36 + 2 44 + 2 45 + 2 46 + 2 50 + 3 5 + 3 6 + 3 8 + 3 9 + 3 10 + 3 11 + 3 14 + 3 16 + 3 23 + 3 24 + 3 26 + 3 27 + 3 28 + 3 29 + 3 30 + 3 31 + 3 34 + 3 35 + 3 36 + 3 39 + 3 41 + 3 42 + 3 43 + 3 44 + 3 50 + 4 6 + 4 7 + 4 9 + 4 10 + 4 11 + 4 13 + 4 14 + 4 15 + 4 17 + 4 21 + 4 22 + 4 23 + 4 24 + 4 25 + 4 27 + 4 28 + 4 30 + 4 31 + 4 33 + 4 34 + 4 35 + 4 36 + 4 37 + 4 38 + 4 40 + 4 41 + 4 42 + 4 46 + 4 49 + 5 6 + 5 11 + 5 14 + 5 21 + 5 24 + 5 25 + 5 28 + 5 35 + 5 38 + 5 39 + 5 41 + 5 44 + 5 49 + 5 50 + 6 8 + 6 9 + 6 10 + 6 13 + 6 14 + 6 16 + 6 17 + 6 19 + 6 22 + 6 23 + 6 26 + 6 27 + 6 30 + 6 34 + 6 35 + 6 38 + 6 39 + 6 40 + 6 41 + 6 44 + 6 45 + 6 47 + 6 50 + 7 8 + 7 9 + 7 10 + 7 11 + 7 13 + 7 15 + 7 16 + 7 18 + 7 20 + 7 22 + 7 23 + 7 24 + 7 25 + 7 33 + 7 35 + 7 36 + 7 38 + 7 43 + 7 45 + 7 46 + 7 47 + 8 10 + 8 11 + 8 13 + 8 16 + 8 17 + 8 18 + 8 19 + 8 20 + 8 21 + 8 22 + 8 23 + 8 24 + 8 25 + 8 26 + 8 33 + 8 35 + 8 36 + 8 39 + 8 42 + 8 44 + 8 48 + 8 49 + 9 12 + 9 14 + 9 17 + 9 19 + 9 20 + 9 23 + 9 28 + 9 30 + 9 31 + 9 32 + 9 33 + 9 34 + 9 38 + 9 39 + 9 42 + 9 44 + 9 45 + 9 46 + 10 11 + 10 13 + 10 15 + 10 16 + 10 17 + 10 20 + 10 21 + 10 22 + 10 23 + 10 25 + 10 26 + 10 27 + 10 28 + 10 30 + 10 31 + 10 32 + 10 37 + 10 38 + 10 41 + 10 43 + 10 44 + 10 45 + 10 50 + 11 12 + 11 14 + 11 15 + 11 18 + 11 21 + 11 24 + 11 25 + 11 26 + 11 29 + 11 32 + 11 33 + 11 35 + 11 36 + 11 37 + 11 39 + 11 40 + 11 42 + 11 43 + 11 45 + 11 47 + 11 49 + 11 50 + 12 13 + 12 16 + 12 17 + 12 19 + 12 24 + 12 25 + 12 26 + 12 30 + 12 31 + 12 32 + 12 34 + 12 36 + 12 37 + 12 39 + 12 41 + 12 44 + 12 47 + 12 48 + 12 49 + 13 15 + 13 16 + 13 18 + 13 19 + 13 20 + 13 22 + 13 23 + 13 24 + 13 27 + 13 28 + 13 29 + 13 31 + 13 33 + 13 35 + 13 36 + 13 37 + 13 44 + 13 47 + 13 49 + 13 50 + 14 15 + 14 16 + 14 17 + 14 18 + 14 19 + 14 20 + 14 21 + 14 26 + 14 28 + 14 29 + 14 30 + 14 31 + 14 32 + 14 34 + 14 35 + 14 36 + 14 38 + 14 39 + 14 41 + 14 44 + 14 46 + 14 47 + 14 48 + 15 18 + 15 21 + 15 22 + 15 23 + 15 25 + 15 28 + 15 29 + 15 30 + 15 33 + 15 34 + 15 36 + 15 37 + 15 38 + 15 39 + 15 40 + 15 43 + 15 44 + 15 46 + 15 50 + 16 17 + 16 19 + 16 20 + 16 25 + 16 26 + 16 29 + 16 35 + 16 38 + 16 39 + 16 40 + 16 41 + 16 42 + 16 44 + 17 18 + 17 19 + 17 21 + 17 22 + 17 23 + 17 25 + 17 26 + 17 28 + 17 29 + 17 33 + 17 37 + 17 44 + 17 45 + 17 48 + 18 20 + 18 24 + 18 27 + 18 28 + 18 31 + 18 32 + 18 34 + 18 35 + 18 36 + 18 37 + 18 38 + 18 45 + 18 48 + 18 49 + 18 50 + 19 22 + 19 24 + 19 28 + 19 29 + 19 36 + 19 37 + 19 39 + 19 41 + 19 43 + 19 45 + 19 48 + 19 49 + 20 21 + 20 22 + 20 24 + 20 25 + 20 26 + 20 27 + 20 29 + 20 30 + 20 31 + 20 33 + 20 34 + 20 35 + 20 38 + 20 39 + 20 41 + 20 42 + 20 43 + 20 44 + 20 45 + 20 46 + 20 48 + 20 49 + 21 22 + 21 23 + 21 29 + 21 31 + 21 35 + 21 38 + 21 42 + 21 46 + 21 47 + 22 23 + 22 26 + 22 27 + 22 28 + 22 29 + 22 30 + 22 39 + 22 40 + 22 41 + 22 42 + 22 44 + 22 45 + 22 46 + 22 47 + 22 49 + 22 50 + 23 28 + 23 31 + 23 32 + 23 33 + 23 34 + 23 35 + 23 36 + 23 39 + 23 40 + 23 41 + 23 42 + 23 44 + 23 45 + 23 48 + 23 49 + 23 50 + 24 25 + 24 27 + 24 29 + 24 30 + 24 31 + 24 33 + 24 34 + 24 38 + 24 42 + 24 43 + 24 44 + 24 49 + 24 50 + 25 26 + 25 27 + 25 29 + 25 30 + 25 33 + 25 34 + 25 36 + 25 38 + 25 40 + 25 41 + 25 42 + 25 44 + 25 46 + 25 47 + 25 48 + 25 49 + 26 28 + 26 31 + 26 32 + 26 33 + 26 37 + 26 38 + 26 39 + 26 40 + 26 41 + 26 42 + 26 45 + 26 47 + 26 48 + 26 49 + 27 29 + 27 30 + 27 33 + 27 34 + 27 35 + 27 39 + 27 40 + 27 46 + 27 48 + 28 29 + 28 37 + 28 40 + 28 42 + 28 44 + 28 46 + 28 47 + 28 50 + 29 35 + 29 38 + 29 39 + 29 41 + 29 42 + 29 48 + 30 31 + 30 32 + 30 35 + 30 37 + 30 38 + 30 40 + 30 43 + 30 45 + 30 46 + 30 47 + 30 48 + 31 33 + 31 35 + 31 38 + 31 40 + 31 41 + 31 42 + 31 44 + 31 46 + 31 47 + 31 50 + 32 33 + 32 35 + 32 39 + 32 40 + 32 46 + 32 49 + 32 50 + 33 34 + 33 36 + 33 37 + 33 40 + 33 42 + 33 43 + 33 44 + 33 45 + 33 50 + 34 35 + 34 36 + 34 37 + 34 38 + 34 40 + 34 43 + 34 44 + 34 49 + 34 50 + 35 36 + 35 38 + 35 41 + 35 42 + 35 43 + 35 45 + 35 46 + 35 47 + 35 49 + 35 50 + 36 37 + 36 39 + 36 40 + 36 41 + 36 42 + 36 43 + 36 48 + 36 50 + 37 38 + 37 41 + 37 43 + 37 46 + 37 47 + 37 48 + 37 49 + 37 50 + 38 41 + 38 45 + 38 46 + 38 48 + 38 49 + 38 50 + 39 43 + 39 46 + 39 47 + 39 48 + 39 49 + 40 43 + 40 45 + 40 48 + 40 50 + 41 42 + 41 43 + 41 44 + 41 45 + 41 46 + 41 48 + 41 49 + 42 43 + 42 44 + 42 46 + 42 48 + 42 49 + 43 45 + 43 46 + 43 48 + 43 50 + 44 45 + 44 48 + 45 46 + 45 47 + 45 48 + 46 49 + 47 49 + 47 50 + 48 49 + 48 50 + 49 50 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/misp1.dat b/resources/3rdparty/glpk-4.53/examples/misp1.dat new file mode 100644 index 000000000..2c2ed1ba5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/misp1.dat @@ -0,0 +1,1489 @@ +/* misp1.dat (data for misp.mod to illustrate clique cuts) */ + +/* These data corresponds to the test instance 1dc.128 (graphs from + * single-deletion-correcting codes) from: + * + * N.J.A.Sloane, "Challenge Problems: Independent Sets In Graphs." + * http://neilsloane.com/doc/graphs.html (June 2013). */ + +/* Optimal solution is 16. */ + +data; + +param n := 128; + +set E := /* 1471 edges */ + 1 2 + 1 3 + 1 5 + 1 9 + 1 17 + 1 33 + 1 65 + 2 3 + 2 4 + 2 5 + 2 6 + 2 9 + 2 10 + 2 17 + 2 18 + 2 33 + 2 34 + 2 65 + 2 66 + 3 4 + 3 5 + 3 6 + 3 7 + 3 9 + 3 10 + 3 11 + 3 17 + 3 18 + 3 19 + 3 33 + 3 34 + 3 35 + 3 65 + 3 66 + 3 67 + 4 6 + 4 7 + 4 8 + 4 10 + 4 12 + 4 18 + 4 20 + 4 34 + 4 36 + 4 66 + 4 68 + 5 6 + 5 7 + 5 9 + 5 10 + 5 11 + 5 13 + 5 17 + 5 19 + 5 21 + 5 33 + 5 35 + 5 37 + 5 65 + 5 67 + 5 69 + 6 7 + 6 8 + 6 10 + 6 11 + 6 12 + 6 14 + 6 18 + 6 19 + 6 20 + 6 22 + 6 34 + 6 35 + 6 36 + 6 38 + 6 66 + 6 67 + 6 68 + 6 70 + 7 8 + 7 11 + 7 12 + 7 13 + 7 14 + 7 15 + 7 19 + 7 20 + 7 23 + 7 35 + 7 36 + 7 39 + 7 67 + 7 68 + 7 71 + 8 12 + 8 14 + 8 15 + 8 16 + 8 20 + 8 24 + 8 36 + 8 40 + 8 68 + 8 72 + 9 10 + 9 11 + 9 13 + 9 17 + 9 18 + 9 19 + 9 21 + 9 25 + 9 33 + 9 37 + 9 41 + 9 65 + 9 69 + 9 73 + 10 11 + 10 12 + 10 13 + 10 14 + 10 18 + 10 19 + 10 20 + 10 21 + 10 22 + 10 26 + 10 34 + 10 37 + 10 38 + 10 42 + 10 66 + 10 69 + 10 70 + 10 74 + 11 12 + 11 13 + 11 14 + 11 15 + 11 19 + 11 21 + 11 22 + 11 23 + 11 27 + 11 35 + 11 37 + 11 38 + 11 39 + 11 43 + 11 67 + 11 69 + 11 70 + 11 71 + 11 75 + 12 14 + 12 15 + 12 16 + 12 20 + 12 22 + 12 23 + 12 24 + 12 28 + 12 36 + 12 38 + 12 40 + 12 44 + 12 68 + 12 70 + 12 72 + 12 76 + 13 14 + 13 15 + 13 21 + 13 23 + 13 25 + 13 26 + 13 27 + 13 29 + 13 37 + 13 39 + 13 45 + 13 69 + 13 71 + 13 77 + 14 15 + 14 16 + 14 22 + 14 23 + 14 24 + 14 26 + 14 27 + 14 28 + 14 30 + 14 38 + 14 39 + 14 40 + 14 46 + 14 70 + 14 71 + 14 72 + 14 78 + 15 16 + 15 23 + 15 24 + 15 27 + 15 29 + 15 30 + 15 31 + 15 39 + 15 40 + 15 47 + 15 71 + 15 72 + 15 79 + 16 24 + 16 28 + 16 30 + 16 31 + 16 32 + 16 40 + 16 48 + 16 72 + 16 80 + 17 18 + 17 19 + 17 21 + 17 25 + 17 33 + 17 34 + 17 35 + 17 37 + 17 41 + 17 49 + 17 65 + 17 73 + 17 81 + 18 19 + 18 20 + 18 21 + 18 22 + 18 25 + 18 26 + 18 34 + 18 35 + 18 36 + 18 38 + 18 41 + 18 42 + 18 50 + 18 66 + 18 73 + 18 74 + 18 82 + 19 20 + 19 21 + 19 22 + 19 23 + 19 25 + 19 26 + 19 27 + 19 35 + 19 37 + 19 38 + 19 39 + 19 41 + 19 42 + 19 43 + 19 51 + 19 67 + 19 73 + 19 74 + 19 75 + 19 83 + 20 22 + 20 23 + 20 24 + 20 26 + 20 28 + 20 36 + 20 38 + 20 39 + 20 40 + 20 42 + 20 44 + 20 52 + 20 68 + 20 74 + 20 76 + 20 84 + 21 22 + 21 23 + 21 25 + 21 26 + 21 27 + 21 29 + 21 37 + 21 41 + 21 42 + 21 43 + 21 45 + 21 53 + 21 69 + 21 73 + 21 75 + 21 77 + 21 85 + 22 23 + 22 24 + 22 26 + 22 27 + 22 28 + 22 30 + 22 38 + 22 42 + 22 43 + 22 44 + 22 46 + 22 54 + 22 70 + 22 74 + 22 75 + 22 76 + 22 78 + 22 86 + 23 24 + 23 27 + 23 28 + 23 29 + 23 30 + 23 31 + 23 39 + 23 43 + 23 44 + 23 45 + 23 46 + 23 47 + 23 55 + 23 71 + 23 75 + 23 76 + 23 79 + 23 87 + 24 28 + 24 30 + 24 31 + 24 32 + 24 40 + 24 44 + 24 46 + 24 47 + 24 48 + 24 56 + 24 72 + 24 76 + 24 80 + 24 88 + 25 26 + 25 27 + 25 29 + 25 41 + 25 45 + 25 49 + 25 50 + 25 51 + 25 53 + 25 57 + 25 73 + 25 77 + 25 89 + 26 27 + 26 28 + 26 29 + 26 30 + 26 42 + 26 45 + 26 46 + 26 50 + 26 51 + 26 52 + 26 54 + 26 58 + 26 74 + 26 77 + 26 78 + 26 90 + 27 28 + 27 29 + 27 30 + 27 31 + 27 43 + 27 45 + 27 46 + 27 47 + 27 51 + 27 53 + 27 54 + 27 55 + 27 59 + 27 75 + 27 77 + 27 78 + 27 79 + 27 91 + 28 30 + 28 31 + 28 32 + 28 44 + 28 46 + 28 48 + 28 52 + 28 54 + 28 55 + 28 56 + 28 60 + 28 76 + 28 78 + 28 80 + 28 92 + 29 30 + 29 31 + 29 45 + 29 47 + 29 53 + 29 57 + 29 58 + 29 59 + 29 61 + 29 77 + 29 79 + 29 93 + 30 31 + 30 32 + 30 46 + 30 47 + 30 48 + 30 54 + 30 58 + 30 59 + 30 60 + 30 62 + 30 78 + 30 79 + 30 80 + 30 94 + 31 32 + 31 47 + 31 48 + 31 55 + 31 59 + 31 61 + 31 62 + 31 63 + 31 79 + 31 80 + 31 95 + 32 48 + 32 56 + 32 60 + 32 62 + 32 63 + 32 64 + 32 80 + 32 96 + 33 34 + 33 35 + 33 37 + 33 41 + 33 49 + 33 65 + 33 66 + 33 67 + 33 69 + 33 73 + 33 81 + 33 97 + 34 35 + 34 36 + 34 37 + 34 38 + 34 41 + 34 42 + 34 49 + 34 50 + 34 66 + 34 67 + 34 68 + 34 70 + 34 74 + 34 81 + 34 82 + 34 98 + 35 36 + 35 37 + 35 38 + 35 39 + 35 41 + 35 42 + 35 43 + 35 49 + 35 50 + 35 51 + 35 67 + 35 69 + 35 70 + 35 71 + 35 75 + 35 81 + 35 82 + 35 83 + 35 99 + 36 38 + 36 39 + 36 40 + 36 42 + 36 44 + 36 50 + 36 52 + 36 68 + 36 70 + 36 71 + 36 72 + 36 76 + 36 82 + 36 84 + 36 100 + 37 38 + 37 39 + 37 41 + 37 42 + 37 43 + 37 45 + 37 49 + 37 51 + 37 53 + 37 69 + 37 73 + 37 74 + 37 75 + 37 77 + 37 81 + 37 83 + 37 85 + 37 101 + 38 39 + 38 40 + 38 42 + 38 43 + 38 44 + 38 46 + 38 50 + 38 51 + 38 52 + 38 54 + 38 70 + 38 74 + 38 75 + 38 76 + 38 78 + 38 82 + 38 83 + 38 84 + 38 86 + 38 102 + 39 40 + 39 43 + 39 44 + 39 45 + 39 46 + 39 47 + 39 51 + 39 52 + 39 55 + 39 71 + 39 75 + 39 77 + 39 78 + 39 79 + 39 83 + 39 84 + 39 87 + 39 103 + 40 44 + 40 46 + 40 47 + 40 48 + 40 52 + 40 56 + 40 72 + 40 76 + 40 78 + 40 79 + 40 80 + 40 84 + 40 88 + 40 104 + 41 42 + 41 43 + 41 45 + 41 49 + 41 50 + 41 51 + 41 53 + 41 57 + 41 73 + 41 81 + 41 82 + 41 83 + 41 85 + 41 89 + 41 105 + 42 43 + 42 44 + 42 45 + 42 46 + 42 50 + 42 51 + 42 52 + 42 53 + 42 54 + 42 58 + 42 74 + 42 82 + 42 83 + 42 84 + 42 85 + 42 86 + 42 90 + 42 106 + 43 44 + 43 45 + 43 46 + 43 47 + 43 51 + 43 53 + 43 54 + 43 55 + 43 59 + 43 75 + 43 83 + 43 85 + 43 86 + 43 87 + 43 91 + 43 107 + 44 46 + 44 47 + 44 48 + 44 52 + 44 54 + 44 55 + 44 56 + 44 60 + 44 76 + 44 84 + 44 86 + 44 87 + 44 88 + 44 92 + 44 108 + 45 46 + 45 47 + 45 53 + 45 55 + 45 57 + 45 58 + 45 59 + 45 61 + 45 77 + 45 85 + 45 87 + 45 89 + 45 90 + 45 91 + 45 93 + 45 109 + 46 47 + 46 48 + 46 54 + 46 55 + 46 56 + 46 58 + 46 59 + 46 60 + 46 62 + 46 78 + 46 86 + 46 87 + 46 88 + 46 90 + 46 91 + 46 92 + 46 94 + 46 110 + 47 48 + 47 55 + 47 56 + 47 59 + 47 61 + 47 62 + 47 63 + 47 79 + 47 87 + 47 88 + 47 91 + 47 93 + 47 94 + 47 95 + 47 111 + 48 56 + 48 60 + 48 62 + 48 63 + 48 64 + 48 80 + 48 88 + 48 92 + 48 94 + 48 95 + 48 96 + 48 112 + 49 50 + 49 51 + 49 53 + 49 57 + 49 81 + 49 89 + 49 97 + 49 98 + 49 99 + 49 101 + 49 105 + 49 113 + 50 51 + 50 52 + 50 53 + 50 54 + 50 57 + 50 58 + 50 82 + 50 89 + 50 90 + 50 98 + 50 99 + 50 100 + 50 102 + 50 106 + 50 114 + 51 52 + 51 53 + 51 54 + 51 55 + 51 57 + 51 58 + 51 59 + 51 83 + 51 89 + 51 90 + 51 91 + 51 99 + 51 101 + 51 102 + 51 103 + 51 107 + 51 115 + 52 54 + 52 55 + 52 56 + 52 58 + 52 60 + 52 84 + 52 90 + 52 92 + 52 100 + 52 102 + 52 103 + 52 104 + 52 108 + 52 116 + 53 54 + 53 55 + 53 57 + 53 58 + 53 59 + 53 61 + 53 85 + 53 89 + 53 91 + 53 93 + 53 101 + 53 105 + 53 106 + 53 107 + 53 109 + 53 117 + 54 55 + 54 56 + 54 58 + 54 59 + 54 60 + 54 62 + 54 86 + 54 90 + 54 91 + 54 92 + 54 94 + 54 102 + 54 106 + 54 107 + 54 108 + 54 110 + 54 118 + 55 56 + 55 59 + 55 60 + 55 61 + 55 62 + 55 63 + 55 87 + 55 91 + 55 92 + 55 95 + 55 103 + 55 107 + 55 109 + 55 110 + 55 111 + 55 119 + 56 60 + 56 62 + 56 63 + 56 64 + 56 88 + 56 92 + 56 96 + 56 104 + 56 108 + 56 110 + 56 111 + 56 112 + 56 120 + 57 58 + 57 59 + 57 61 + 57 89 + 57 93 + 57 105 + 57 113 + 57 114 + 57 115 + 57 117 + 57 121 + 58 59 + 58 60 + 58 61 + 58 62 + 58 90 + 58 93 + 58 94 + 58 106 + 58 114 + 58 115 + 58 116 + 58 118 + 58 122 + 59 60 + 59 61 + 59 62 + 59 63 + 59 91 + 59 93 + 59 94 + 59 95 + 59 107 + 59 115 + 59 117 + 59 118 + 59 119 + 59 123 + 60 62 + 60 63 + 60 64 + 60 92 + 60 94 + 60 96 + 60 108 + 60 116 + 60 118 + 60 119 + 60 120 + 60 124 + 61 62 + 61 63 + 61 93 + 61 95 + 61 109 + 61 117 + 61 121 + 61 122 + 61 123 + 61 125 + 62 63 + 62 64 + 62 94 + 62 95 + 62 96 + 62 110 + 62 118 + 62 122 + 62 123 + 62 124 + 62 126 + 63 64 + 63 95 + 63 96 + 63 111 + 63 119 + 63 123 + 63 125 + 63 126 + 63 127 + 64 96 + 64 112 + 64 120 + 64 124 + 64 126 + 64 127 + 64 128 + 65 66 + 65 67 + 65 69 + 65 73 + 65 81 + 65 97 + 66 67 + 66 68 + 66 69 + 66 70 + 66 73 + 66 74 + 66 81 + 66 82 + 66 97 + 66 98 + 67 68 + 67 69 + 67 70 + 67 71 + 67 73 + 67 74 + 67 75 + 67 81 + 67 82 + 67 83 + 67 97 + 67 98 + 67 99 + 68 70 + 68 71 + 68 72 + 68 74 + 68 76 + 68 82 + 68 84 + 68 98 + 68 100 + 69 70 + 69 71 + 69 73 + 69 74 + 69 75 + 69 77 + 69 81 + 69 83 + 69 85 + 69 97 + 69 99 + 69 101 + 70 71 + 70 72 + 70 74 + 70 75 + 70 76 + 70 78 + 70 82 + 70 83 + 70 84 + 70 86 + 70 98 + 70 99 + 70 100 + 70 102 + 71 72 + 71 75 + 71 76 + 71 77 + 71 78 + 71 79 + 71 83 + 71 84 + 71 87 + 71 99 + 71 100 + 71 103 + 72 76 + 72 78 + 72 79 + 72 80 + 72 84 + 72 88 + 72 100 + 72 104 + 73 74 + 73 75 + 73 77 + 73 81 + 73 82 + 73 83 + 73 85 + 73 89 + 73 97 + 73 101 + 73 105 + 74 75 + 74 76 + 74 77 + 74 78 + 74 82 + 74 83 + 74 84 + 74 85 + 74 86 + 74 90 + 74 98 + 74 101 + 74 102 + 74 106 + 75 76 + 75 77 + 75 78 + 75 79 + 75 83 + 75 85 + 75 86 + 75 87 + 75 91 + 75 99 + 75 101 + 75 102 + 75 103 + 75 107 + 76 78 + 76 79 + 76 80 + 76 84 + 76 86 + 76 87 + 76 88 + 76 92 + 76 100 + 76 102 + 76 104 + 76 108 + 77 78 + 77 79 + 77 85 + 77 87 + 77 89 + 77 90 + 77 91 + 77 93 + 77 101 + 77 103 + 77 109 + 78 79 + 78 80 + 78 86 + 78 87 + 78 88 + 78 90 + 78 91 + 78 92 + 78 94 + 78 102 + 78 103 + 78 104 + 78 110 + 79 80 + 79 87 + 79 88 + 79 91 + 79 93 + 79 94 + 79 95 + 79 103 + 79 104 + 79 111 + 80 88 + 80 92 + 80 94 + 80 95 + 80 96 + 80 104 + 80 112 + 81 82 + 81 83 + 81 85 + 81 89 + 81 97 + 81 98 + 81 99 + 81 101 + 81 105 + 81 113 + 82 83 + 82 84 + 82 85 + 82 86 + 82 89 + 82 90 + 82 98 + 82 99 + 82 100 + 82 102 + 82 105 + 82 106 + 82 114 + 83 84 + 83 85 + 83 86 + 83 87 + 83 89 + 83 90 + 83 91 + 83 99 + 83 101 + 83 102 + 83 103 + 83 105 + 83 106 + 83 107 + 83 115 + 84 86 + 84 87 + 84 88 + 84 90 + 84 92 + 84 100 + 84 102 + 84 103 + 84 104 + 84 106 + 84 108 + 84 116 + 85 86 + 85 87 + 85 89 + 85 90 + 85 91 + 85 93 + 85 101 + 85 105 + 85 106 + 85 107 + 85 109 + 85 117 + 86 87 + 86 88 + 86 90 + 86 91 + 86 92 + 86 94 + 86 102 + 86 106 + 86 107 + 86 108 + 86 110 + 86 118 + 87 88 + 87 91 + 87 92 + 87 93 + 87 94 + 87 95 + 87 103 + 87 107 + 87 108 + 87 109 + 87 110 + 87 111 + 87 119 + 88 92 + 88 94 + 88 95 + 88 96 + 88 104 + 88 108 + 88 110 + 88 111 + 88 112 + 88 120 + 89 90 + 89 91 + 89 93 + 89 105 + 89 109 + 89 113 + 89 114 + 89 115 + 89 117 + 89 121 + 90 91 + 90 92 + 90 93 + 90 94 + 90 106 + 90 109 + 90 110 + 90 114 + 90 115 + 90 116 + 90 118 + 90 122 + 91 92 + 91 93 + 91 94 + 91 95 + 91 107 + 91 109 + 91 110 + 91 111 + 91 115 + 91 117 + 91 118 + 91 119 + 91 123 + 92 94 + 92 95 + 92 96 + 92 108 + 92 110 + 92 112 + 92 116 + 92 118 + 92 119 + 92 120 + 92 124 + 93 94 + 93 95 + 93 109 + 93 111 + 93 117 + 93 121 + 93 122 + 93 123 + 93 125 + 94 95 + 94 96 + 94 110 + 94 111 + 94 112 + 94 118 + 94 122 + 94 123 + 94 124 + 94 126 + 95 96 + 95 111 + 95 112 + 95 119 + 95 123 + 95 125 + 95 126 + 95 127 + 96 112 + 96 120 + 96 124 + 96 126 + 96 127 + 96 128 + 97 98 + 97 99 + 97 101 + 97 105 + 97 113 + 98 99 + 98 100 + 98 101 + 98 102 + 98 105 + 98 106 + 98 113 + 98 114 + 99 100 + 99 101 + 99 102 + 99 103 + 99 105 + 99 106 + 99 107 + 99 113 + 99 114 + 99 115 + 100 102 + 100 103 + 100 104 + 100 106 + 100 108 + 100 114 + 100 116 + 101 102 + 101 103 + 101 105 + 101 106 + 101 107 + 101 109 + 101 113 + 101 115 + 101 117 + 102 103 + 102 104 + 102 106 + 102 107 + 102 108 + 102 110 + 102 114 + 102 115 + 102 116 + 102 118 + 103 104 + 103 107 + 103 108 + 103 109 + 103 110 + 103 111 + 103 115 + 103 116 + 103 119 + 104 108 + 104 110 + 104 111 + 104 112 + 104 116 + 104 120 + 105 106 + 105 107 + 105 109 + 105 113 + 105 114 + 105 115 + 105 117 + 105 121 + 106 107 + 106 108 + 106 109 + 106 110 + 106 114 + 106 115 + 106 116 + 106 117 + 106 118 + 106 122 + 107 108 + 107 109 + 107 110 + 107 111 + 107 115 + 107 117 + 107 118 + 107 119 + 107 123 + 108 110 + 108 111 + 108 112 + 108 116 + 108 118 + 108 119 + 108 120 + 108 124 + 109 110 + 109 111 + 109 117 + 109 119 + 109 121 + 109 122 + 109 123 + 109 125 + 110 111 + 110 112 + 110 118 + 110 119 + 110 120 + 110 122 + 110 123 + 110 124 + 110 126 + 111 112 + 111 119 + 111 120 + 111 123 + 111 125 + 111 126 + 111 127 + 112 120 + 112 124 + 112 126 + 112 127 + 112 128 + 113 114 + 113 115 + 113 117 + 113 121 + 114 115 + 114 116 + 114 117 + 114 118 + 114 121 + 114 122 + 115 116 + 115 117 + 115 118 + 115 119 + 115 121 + 115 122 + 115 123 + 116 118 + 116 119 + 116 120 + 116 122 + 116 124 + 117 118 + 117 119 + 117 121 + 117 122 + 117 123 + 117 125 + 118 119 + 118 120 + 118 122 + 118 123 + 118 124 + 118 126 + 119 120 + 119 123 + 119 124 + 119 125 + 119 126 + 119 127 + 120 124 + 120 126 + 120 127 + 120 128 + 121 122 + 121 123 + 121 125 + 122 123 + 122 124 + 122 125 + 122 126 + 123 124 + 123 125 + 123 126 + 123 127 + 124 126 + 124 127 + 124 128 + 125 126 + 125 127 + 126 127 + 126 128 + 127 128 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/misp2.dat b/resources/3rdparty/glpk-4.53/examples/misp2.dat new file mode 100644 index 000000000..c9a61161e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/misp2.dat @@ -0,0 +1,3857 @@ +/* misp2.dat (data for misp.mod to illustrate clique cuts) */ + +/* These data corresponds to the test instance 1dc.256 (graphs from + * single-deletion-correcting codes) from: + * + * N.J.A.Sloane, "Challenge Problems: Independent Sets In Graphs." + * http://neilsloane.com/doc/graphs.html (June 2013). */ + +/* Optimal solution is 30. */ + +data; + +param n := 256; + +set E := /* 3839 edges */ + 1 2 + 1 3 + 1 5 + 1 9 + 1 17 + 1 33 + 1 65 + 1 129 + 2 3 + 2 4 + 2 5 + 2 6 + 2 9 + 2 10 + 2 17 + 2 18 + 2 33 + 2 34 + 2 65 + 2 66 + 2 129 + 2 130 + 3 4 + 3 5 + 3 6 + 3 7 + 3 9 + 3 10 + 3 11 + 3 17 + 3 18 + 3 19 + 3 33 + 3 34 + 3 35 + 3 65 + 3 66 + 3 67 + 3 129 + 3 130 + 3 131 + 4 6 + 4 7 + 4 8 + 4 10 + 4 12 + 4 18 + 4 20 + 4 34 + 4 36 + 4 66 + 4 68 + 4 130 + 4 132 + 5 6 + 5 7 + 5 9 + 5 10 + 5 11 + 5 13 + 5 17 + 5 19 + 5 21 + 5 33 + 5 35 + 5 37 + 5 65 + 5 67 + 5 69 + 5 129 + 5 131 + 5 133 + 6 7 + 6 8 + 6 10 + 6 11 + 6 12 + 6 14 + 6 18 + 6 19 + 6 20 + 6 22 + 6 34 + 6 35 + 6 36 + 6 38 + 6 66 + 6 67 + 6 68 + 6 70 + 6 130 + 6 131 + 6 132 + 6 134 + 7 8 + 7 11 + 7 12 + 7 13 + 7 14 + 7 15 + 7 19 + 7 20 + 7 23 + 7 35 + 7 36 + 7 39 + 7 67 + 7 68 + 7 71 + 7 131 + 7 132 + 7 135 + 8 12 + 8 14 + 8 15 + 8 16 + 8 20 + 8 24 + 8 36 + 8 40 + 8 68 + 8 72 + 8 132 + 8 136 + 9 10 + 9 11 + 9 13 + 9 17 + 9 18 + 9 19 + 9 21 + 9 25 + 9 33 + 9 37 + 9 41 + 9 65 + 9 69 + 9 73 + 9 129 + 9 133 + 9 137 + 10 11 + 10 12 + 10 13 + 10 14 + 10 18 + 10 19 + 10 20 + 10 21 + 10 22 + 10 26 + 10 34 + 10 37 + 10 38 + 10 42 + 10 66 + 10 69 + 10 70 + 10 74 + 10 130 + 10 133 + 10 134 + 10 138 + 11 12 + 11 13 + 11 14 + 11 15 + 11 19 + 11 21 + 11 22 + 11 23 + 11 27 + 11 35 + 11 37 + 11 38 + 11 39 + 11 43 + 11 67 + 11 69 + 11 70 + 11 71 + 11 75 + 11 131 + 11 133 + 11 134 + 11 135 + 11 139 + 12 14 + 12 15 + 12 16 + 12 20 + 12 22 + 12 23 + 12 24 + 12 28 + 12 36 + 12 38 + 12 40 + 12 44 + 12 68 + 12 70 + 12 72 + 12 76 + 12 132 + 12 134 + 12 136 + 12 140 + 13 14 + 13 15 + 13 21 + 13 23 + 13 25 + 13 26 + 13 27 + 13 29 + 13 37 + 13 39 + 13 45 + 13 69 + 13 71 + 13 77 + 13 133 + 13 135 + 13 141 + 14 15 + 14 16 + 14 22 + 14 23 + 14 24 + 14 26 + 14 27 + 14 28 + 14 30 + 14 38 + 14 39 + 14 40 + 14 46 + 14 70 + 14 71 + 14 72 + 14 78 + 14 134 + 14 135 + 14 136 + 14 142 + 15 16 + 15 23 + 15 24 + 15 27 + 15 29 + 15 30 + 15 31 + 15 39 + 15 40 + 15 47 + 15 71 + 15 72 + 15 79 + 15 135 + 15 136 + 15 143 + 16 24 + 16 28 + 16 30 + 16 31 + 16 32 + 16 40 + 16 48 + 16 72 + 16 80 + 16 136 + 16 144 + 17 18 + 17 19 + 17 21 + 17 25 + 17 33 + 17 34 + 17 35 + 17 37 + 17 41 + 17 49 + 17 65 + 17 73 + 17 81 + 17 129 + 17 137 + 17 145 + 18 19 + 18 20 + 18 21 + 18 22 + 18 25 + 18 26 + 18 34 + 18 35 + 18 36 + 18 38 + 18 41 + 18 42 + 18 50 + 18 66 + 18 73 + 18 74 + 18 82 + 18 130 + 18 137 + 18 138 + 18 146 + 19 20 + 19 21 + 19 22 + 19 23 + 19 25 + 19 26 + 19 27 + 19 35 + 19 37 + 19 38 + 19 39 + 19 41 + 19 42 + 19 43 + 19 51 + 19 67 + 19 73 + 19 74 + 19 75 + 19 83 + 19 131 + 19 137 + 19 138 + 19 139 + 19 147 + 20 22 + 20 23 + 20 24 + 20 26 + 20 28 + 20 36 + 20 38 + 20 39 + 20 40 + 20 42 + 20 44 + 20 52 + 20 68 + 20 74 + 20 76 + 20 84 + 20 132 + 20 138 + 20 140 + 20 148 + 21 22 + 21 23 + 21 25 + 21 26 + 21 27 + 21 29 + 21 37 + 21 41 + 21 42 + 21 43 + 21 45 + 21 53 + 21 69 + 21 73 + 21 75 + 21 77 + 21 85 + 21 133 + 21 137 + 21 139 + 21 141 + 21 149 + 22 23 + 22 24 + 22 26 + 22 27 + 22 28 + 22 30 + 22 38 + 22 42 + 22 43 + 22 44 + 22 46 + 22 54 + 22 70 + 22 74 + 22 75 + 22 76 + 22 78 + 22 86 + 22 134 + 22 138 + 22 139 + 22 140 + 22 142 + 22 150 + 23 24 + 23 27 + 23 28 + 23 29 + 23 30 + 23 31 + 23 39 + 23 43 + 23 44 + 23 45 + 23 46 + 23 47 + 23 55 + 23 71 + 23 75 + 23 76 + 23 79 + 23 87 + 23 135 + 23 139 + 23 140 + 23 143 + 23 151 + 24 28 + 24 30 + 24 31 + 24 32 + 24 40 + 24 44 + 24 46 + 24 47 + 24 48 + 24 56 + 24 72 + 24 76 + 24 80 + 24 88 + 24 136 + 24 140 + 24 144 + 24 152 + 25 26 + 25 27 + 25 29 + 25 41 + 25 45 + 25 49 + 25 50 + 25 51 + 25 53 + 25 57 + 25 73 + 25 77 + 25 89 + 25 137 + 25 141 + 25 153 + 26 27 + 26 28 + 26 29 + 26 30 + 26 42 + 26 45 + 26 46 + 26 50 + 26 51 + 26 52 + 26 54 + 26 58 + 26 74 + 26 77 + 26 78 + 26 90 + 26 138 + 26 141 + 26 142 + 26 154 + 27 28 + 27 29 + 27 30 + 27 31 + 27 43 + 27 45 + 27 46 + 27 47 + 27 51 + 27 53 + 27 54 + 27 55 + 27 59 + 27 75 + 27 77 + 27 78 + 27 79 + 27 91 + 27 139 + 27 141 + 27 142 + 27 143 + 27 155 + 28 30 + 28 31 + 28 32 + 28 44 + 28 46 + 28 48 + 28 52 + 28 54 + 28 55 + 28 56 + 28 60 + 28 76 + 28 78 + 28 80 + 28 92 + 28 140 + 28 142 + 28 144 + 28 156 + 29 30 + 29 31 + 29 45 + 29 47 + 29 53 + 29 57 + 29 58 + 29 59 + 29 61 + 29 77 + 29 79 + 29 93 + 29 141 + 29 143 + 29 157 + 30 31 + 30 32 + 30 46 + 30 47 + 30 48 + 30 54 + 30 58 + 30 59 + 30 60 + 30 62 + 30 78 + 30 79 + 30 80 + 30 94 + 30 142 + 30 143 + 30 144 + 30 158 + 31 32 + 31 47 + 31 48 + 31 55 + 31 59 + 31 61 + 31 62 + 31 63 + 31 79 + 31 80 + 31 95 + 31 143 + 31 144 + 31 159 + 32 48 + 32 56 + 32 60 + 32 62 + 32 63 + 32 64 + 32 80 + 32 96 + 32 144 + 32 160 + 33 34 + 33 35 + 33 37 + 33 41 + 33 49 + 33 65 + 33 66 + 33 67 + 33 69 + 33 73 + 33 81 + 33 97 + 33 129 + 33 145 + 33 161 + 34 35 + 34 36 + 34 37 + 34 38 + 34 41 + 34 42 + 34 49 + 34 50 + 34 66 + 34 67 + 34 68 + 34 70 + 34 74 + 34 81 + 34 82 + 34 98 + 34 130 + 34 145 + 34 146 + 34 162 + 35 36 + 35 37 + 35 38 + 35 39 + 35 41 + 35 42 + 35 43 + 35 49 + 35 50 + 35 51 + 35 67 + 35 69 + 35 70 + 35 71 + 35 75 + 35 81 + 35 82 + 35 83 + 35 99 + 35 131 + 35 145 + 35 146 + 35 147 + 35 163 + 36 38 + 36 39 + 36 40 + 36 42 + 36 44 + 36 50 + 36 52 + 36 68 + 36 70 + 36 71 + 36 72 + 36 76 + 36 82 + 36 84 + 36 100 + 36 132 + 36 146 + 36 148 + 36 164 + 37 38 + 37 39 + 37 41 + 37 42 + 37 43 + 37 45 + 37 49 + 37 51 + 37 53 + 37 69 + 37 73 + 37 74 + 37 75 + 37 77 + 37 81 + 37 83 + 37 85 + 37 101 + 37 133 + 37 145 + 37 147 + 37 149 + 37 165 + 38 39 + 38 40 + 38 42 + 38 43 + 38 44 + 38 46 + 38 50 + 38 51 + 38 52 + 38 54 + 38 70 + 38 74 + 38 75 + 38 76 + 38 78 + 38 82 + 38 83 + 38 84 + 38 86 + 38 102 + 38 134 + 38 146 + 38 147 + 38 148 + 38 150 + 38 166 + 39 40 + 39 43 + 39 44 + 39 45 + 39 46 + 39 47 + 39 51 + 39 52 + 39 55 + 39 71 + 39 75 + 39 77 + 39 78 + 39 79 + 39 83 + 39 84 + 39 87 + 39 103 + 39 135 + 39 147 + 39 148 + 39 151 + 39 167 + 40 44 + 40 46 + 40 47 + 40 48 + 40 52 + 40 56 + 40 72 + 40 76 + 40 78 + 40 79 + 40 80 + 40 84 + 40 88 + 40 104 + 40 136 + 40 148 + 40 152 + 40 168 + 41 42 + 41 43 + 41 45 + 41 49 + 41 50 + 41 51 + 41 53 + 41 57 + 41 73 + 41 81 + 41 82 + 41 83 + 41 85 + 41 89 + 41 105 + 41 137 + 41 145 + 41 149 + 41 153 + 41 169 + 42 43 + 42 44 + 42 45 + 42 46 + 42 50 + 42 51 + 42 52 + 42 53 + 42 54 + 42 58 + 42 74 + 42 82 + 42 83 + 42 84 + 42 85 + 42 86 + 42 90 + 42 106 + 42 138 + 42 146 + 42 149 + 42 150 + 42 154 + 42 170 + 43 44 + 43 45 + 43 46 + 43 47 + 43 51 + 43 53 + 43 54 + 43 55 + 43 59 + 43 75 + 43 83 + 43 85 + 43 86 + 43 87 + 43 91 + 43 107 + 43 139 + 43 147 + 43 149 + 43 150 + 43 151 + 43 155 + 43 171 + 44 46 + 44 47 + 44 48 + 44 52 + 44 54 + 44 55 + 44 56 + 44 60 + 44 76 + 44 84 + 44 86 + 44 87 + 44 88 + 44 92 + 44 108 + 44 140 + 44 148 + 44 150 + 44 152 + 44 156 + 44 172 + 45 46 + 45 47 + 45 53 + 45 55 + 45 57 + 45 58 + 45 59 + 45 61 + 45 77 + 45 85 + 45 87 + 45 89 + 45 90 + 45 91 + 45 93 + 45 109 + 45 141 + 45 149 + 45 151 + 45 157 + 45 173 + 46 47 + 46 48 + 46 54 + 46 55 + 46 56 + 46 58 + 46 59 + 46 60 + 46 62 + 46 78 + 46 86 + 46 87 + 46 88 + 46 90 + 46 91 + 46 92 + 46 94 + 46 110 + 46 142 + 46 150 + 46 151 + 46 152 + 46 158 + 46 174 + 47 48 + 47 55 + 47 56 + 47 59 + 47 61 + 47 62 + 47 63 + 47 79 + 47 87 + 47 88 + 47 91 + 47 93 + 47 94 + 47 95 + 47 111 + 47 143 + 47 151 + 47 152 + 47 159 + 47 175 + 48 56 + 48 60 + 48 62 + 48 63 + 48 64 + 48 80 + 48 88 + 48 92 + 48 94 + 48 95 + 48 96 + 48 112 + 48 144 + 48 152 + 48 160 + 48 176 + 49 50 + 49 51 + 49 53 + 49 57 + 49 81 + 49 89 + 49 97 + 49 98 + 49 99 + 49 101 + 49 105 + 49 113 + 49 145 + 49 153 + 49 177 + 50 51 + 50 52 + 50 53 + 50 54 + 50 57 + 50 58 + 50 82 + 50 89 + 50 90 + 50 98 + 50 99 + 50 100 + 50 102 + 50 106 + 50 114 + 50 146 + 50 153 + 50 154 + 50 178 + 51 52 + 51 53 + 51 54 + 51 55 + 51 57 + 51 58 + 51 59 + 51 83 + 51 89 + 51 90 + 51 91 + 51 99 + 51 101 + 51 102 + 51 103 + 51 107 + 51 115 + 51 147 + 51 153 + 51 154 + 51 155 + 51 179 + 52 54 + 52 55 + 52 56 + 52 58 + 52 60 + 52 84 + 52 90 + 52 92 + 52 100 + 52 102 + 52 103 + 52 104 + 52 108 + 52 116 + 52 148 + 52 154 + 52 156 + 52 180 + 53 54 + 53 55 + 53 57 + 53 58 + 53 59 + 53 61 + 53 85 + 53 89 + 53 91 + 53 93 + 53 101 + 53 105 + 53 106 + 53 107 + 53 109 + 53 117 + 53 149 + 53 153 + 53 155 + 53 157 + 53 181 + 54 55 + 54 56 + 54 58 + 54 59 + 54 60 + 54 62 + 54 86 + 54 90 + 54 91 + 54 92 + 54 94 + 54 102 + 54 106 + 54 107 + 54 108 + 54 110 + 54 118 + 54 150 + 54 154 + 54 155 + 54 156 + 54 158 + 54 182 + 55 56 + 55 59 + 55 60 + 55 61 + 55 62 + 55 63 + 55 87 + 55 91 + 55 92 + 55 95 + 55 103 + 55 107 + 55 109 + 55 110 + 55 111 + 55 119 + 55 151 + 55 155 + 55 156 + 55 159 + 55 183 + 56 60 + 56 62 + 56 63 + 56 64 + 56 88 + 56 92 + 56 96 + 56 104 + 56 108 + 56 110 + 56 111 + 56 112 + 56 120 + 56 152 + 56 156 + 56 160 + 56 184 + 57 58 + 57 59 + 57 61 + 57 89 + 57 93 + 57 105 + 57 113 + 57 114 + 57 115 + 57 117 + 57 121 + 57 153 + 57 157 + 57 185 + 58 59 + 58 60 + 58 61 + 58 62 + 58 90 + 58 93 + 58 94 + 58 106 + 58 114 + 58 115 + 58 116 + 58 118 + 58 122 + 58 154 + 58 157 + 58 158 + 58 186 + 59 60 + 59 61 + 59 62 + 59 63 + 59 91 + 59 93 + 59 94 + 59 95 + 59 107 + 59 115 + 59 117 + 59 118 + 59 119 + 59 123 + 59 155 + 59 157 + 59 158 + 59 159 + 59 187 + 60 62 + 60 63 + 60 64 + 60 92 + 60 94 + 60 96 + 60 108 + 60 116 + 60 118 + 60 119 + 60 120 + 60 124 + 60 156 + 60 158 + 60 160 + 60 188 + 61 62 + 61 63 + 61 93 + 61 95 + 61 109 + 61 117 + 61 121 + 61 122 + 61 123 + 61 125 + 61 157 + 61 159 + 61 189 + 62 63 + 62 64 + 62 94 + 62 95 + 62 96 + 62 110 + 62 118 + 62 122 + 62 123 + 62 124 + 62 126 + 62 158 + 62 159 + 62 160 + 62 190 + 63 64 + 63 95 + 63 96 + 63 111 + 63 119 + 63 123 + 63 125 + 63 126 + 63 127 + 63 159 + 63 160 + 63 191 + 64 96 + 64 112 + 64 120 + 64 124 + 64 126 + 64 127 + 64 128 + 64 160 + 64 192 + 65 66 + 65 67 + 65 69 + 65 73 + 65 81 + 65 97 + 65 129 + 65 130 + 65 131 + 65 133 + 65 137 + 65 145 + 65 161 + 65 193 + 66 67 + 66 68 + 66 69 + 66 70 + 66 73 + 66 74 + 66 81 + 66 82 + 66 97 + 66 98 + 66 130 + 66 131 + 66 132 + 66 134 + 66 138 + 66 146 + 66 161 + 66 162 + 66 194 + 67 68 + 67 69 + 67 70 + 67 71 + 67 73 + 67 74 + 67 75 + 67 81 + 67 82 + 67 83 + 67 97 + 67 98 + 67 99 + 67 131 + 67 133 + 67 134 + 67 135 + 67 139 + 67 147 + 67 161 + 67 162 + 67 163 + 67 195 + 68 70 + 68 71 + 68 72 + 68 74 + 68 76 + 68 82 + 68 84 + 68 98 + 68 100 + 68 132 + 68 134 + 68 135 + 68 136 + 68 140 + 68 148 + 68 162 + 68 164 + 68 196 + 69 70 + 69 71 + 69 73 + 69 74 + 69 75 + 69 77 + 69 81 + 69 83 + 69 85 + 69 97 + 69 99 + 69 101 + 69 133 + 69 137 + 69 138 + 69 139 + 69 141 + 69 149 + 69 161 + 69 163 + 69 165 + 69 197 + 70 71 + 70 72 + 70 74 + 70 75 + 70 76 + 70 78 + 70 82 + 70 83 + 70 84 + 70 86 + 70 98 + 70 99 + 70 100 + 70 102 + 70 134 + 70 138 + 70 139 + 70 140 + 70 142 + 70 150 + 70 162 + 70 163 + 70 164 + 70 166 + 70 198 + 71 72 + 71 75 + 71 76 + 71 77 + 71 78 + 71 79 + 71 83 + 71 84 + 71 87 + 71 99 + 71 100 + 71 103 + 71 135 + 71 139 + 71 141 + 71 142 + 71 143 + 71 151 + 71 163 + 71 164 + 71 167 + 71 199 + 72 76 + 72 78 + 72 79 + 72 80 + 72 84 + 72 88 + 72 100 + 72 104 + 72 136 + 72 140 + 72 142 + 72 143 + 72 144 + 72 152 + 72 164 + 72 168 + 72 200 + 73 74 + 73 75 + 73 77 + 73 81 + 73 82 + 73 83 + 73 85 + 73 89 + 73 97 + 73 101 + 73 105 + 73 137 + 73 145 + 73 146 + 73 147 + 73 149 + 73 153 + 73 161 + 73 165 + 73 169 + 73 201 + 74 75 + 74 76 + 74 77 + 74 78 + 74 82 + 74 83 + 74 84 + 74 85 + 74 86 + 74 90 + 74 98 + 74 101 + 74 102 + 74 106 + 74 138 + 74 146 + 74 147 + 74 148 + 74 150 + 74 154 + 74 162 + 74 165 + 74 166 + 74 170 + 74 202 + 75 76 + 75 77 + 75 78 + 75 79 + 75 83 + 75 85 + 75 86 + 75 87 + 75 91 + 75 99 + 75 101 + 75 102 + 75 103 + 75 107 + 75 139 + 75 147 + 75 149 + 75 150 + 75 151 + 75 155 + 75 163 + 75 165 + 75 166 + 75 167 + 75 171 + 75 203 + 76 78 + 76 79 + 76 80 + 76 84 + 76 86 + 76 87 + 76 88 + 76 92 + 76 100 + 76 102 + 76 104 + 76 108 + 76 140 + 76 148 + 76 150 + 76 151 + 76 152 + 76 156 + 76 164 + 76 166 + 76 168 + 76 172 + 76 204 + 77 78 + 77 79 + 77 85 + 77 87 + 77 89 + 77 90 + 77 91 + 77 93 + 77 101 + 77 103 + 77 109 + 77 141 + 77 149 + 77 153 + 77 154 + 77 155 + 77 157 + 77 165 + 77 167 + 77 173 + 77 205 + 78 79 + 78 80 + 78 86 + 78 87 + 78 88 + 78 90 + 78 91 + 78 92 + 78 94 + 78 102 + 78 103 + 78 104 + 78 110 + 78 142 + 78 150 + 78 154 + 78 155 + 78 156 + 78 158 + 78 166 + 78 167 + 78 168 + 78 174 + 78 206 + 79 80 + 79 87 + 79 88 + 79 91 + 79 93 + 79 94 + 79 95 + 79 103 + 79 104 + 79 111 + 79 143 + 79 151 + 79 155 + 79 157 + 79 158 + 79 159 + 79 167 + 79 168 + 79 175 + 79 207 + 80 88 + 80 92 + 80 94 + 80 95 + 80 96 + 80 104 + 80 112 + 80 144 + 80 152 + 80 156 + 80 158 + 80 159 + 80 160 + 80 168 + 80 176 + 80 208 + 81 82 + 81 83 + 81 85 + 81 89 + 81 97 + 81 98 + 81 99 + 81 101 + 81 105 + 81 113 + 81 145 + 81 161 + 81 162 + 81 163 + 81 165 + 81 169 + 81 177 + 81 209 + 82 83 + 82 84 + 82 85 + 82 86 + 82 89 + 82 90 + 82 98 + 82 99 + 82 100 + 82 102 + 82 105 + 82 106 + 82 114 + 82 146 + 82 162 + 82 163 + 82 164 + 82 166 + 82 169 + 82 170 + 82 178 + 82 210 + 83 84 + 83 85 + 83 86 + 83 87 + 83 89 + 83 90 + 83 91 + 83 99 + 83 101 + 83 102 + 83 103 + 83 105 + 83 106 + 83 107 + 83 115 + 83 147 + 83 163 + 83 165 + 83 166 + 83 167 + 83 169 + 83 170 + 83 171 + 83 179 + 83 211 + 84 86 + 84 87 + 84 88 + 84 90 + 84 92 + 84 100 + 84 102 + 84 103 + 84 104 + 84 106 + 84 108 + 84 116 + 84 148 + 84 164 + 84 166 + 84 167 + 84 168 + 84 170 + 84 172 + 84 180 + 84 212 + 85 86 + 85 87 + 85 89 + 85 90 + 85 91 + 85 93 + 85 101 + 85 105 + 85 106 + 85 107 + 85 109 + 85 117 + 85 149 + 85 165 + 85 169 + 85 170 + 85 171 + 85 173 + 85 181 + 85 213 + 86 87 + 86 88 + 86 90 + 86 91 + 86 92 + 86 94 + 86 102 + 86 106 + 86 107 + 86 108 + 86 110 + 86 118 + 86 150 + 86 166 + 86 170 + 86 171 + 86 172 + 86 174 + 86 182 + 86 214 + 87 88 + 87 91 + 87 92 + 87 93 + 87 94 + 87 95 + 87 103 + 87 107 + 87 108 + 87 109 + 87 110 + 87 111 + 87 119 + 87 151 + 87 167 + 87 171 + 87 172 + 87 173 + 87 174 + 87 175 + 87 183 + 87 215 + 88 92 + 88 94 + 88 95 + 88 96 + 88 104 + 88 108 + 88 110 + 88 111 + 88 112 + 88 120 + 88 152 + 88 168 + 88 172 + 88 174 + 88 175 + 88 176 + 88 184 + 88 216 + 89 90 + 89 91 + 89 93 + 89 105 + 89 109 + 89 113 + 89 114 + 89 115 + 89 117 + 89 121 + 89 153 + 89 169 + 89 173 + 89 177 + 89 178 + 89 179 + 89 181 + 89 185 + 89 217 + 90 91 + 90 92 + 90 93 + 90 94 + 90 106 + 90 109 + 90 110 + 90 114 + 90 115 + 90 116 + 90 118 + 90 122 + 90 154 + 90 170 + 90 173 + 90 174 + 90 178 + 90 179 + 90 180 + 90 182 + 90 186 + 90 218 + 91 92 + 91 93 + 91 94 + 91 95 + 91 107 + 91 109 + 91 110 + 91 111 + 91 115 + 91 117 + 91 118 + 91 119 + 91 123 + 91 155 + 91 171 + 91 173 + 91 174 + 91 175 + 91 179 + 91 181 + 91 182 + 91 183 + 91 187 + 91 219 + 92 94 + 92 95 + 92 96 + 92 108 + 92 110 + 92 112 + 92 116 + 92 118 + 92 119 + 92 120 + 92 124 + 92 156 + 92 172 + 92 174 + 92 176 + 92 180 + 92 182 + 92 183 + 92 184 + 92 188 + 92 220 + 93 94 + 93 95 + 93 109 + 93 111 + 93 117 + 93 121 + 93 122 + 93 123 + 93 125 + 93 157 + 93 173 + 93 175 + 93 181 + 93 185 + 93 186 + 93 187 + 93 189 + 93 221 + 94 95 + 94 96 + 94 110 + 94 111 + 94 112 + 94 118 + 94 122 + 94 123 + 94 124 + 94 126 + 94 158 + 94 174 + 94 175 + 94 176 + 94 182 + 94 186 + 94 187 + 94 188 + 94 190 + 94 222 + 95 96 + 95 111 + 95 112 + 95 119 + 95 123 + 95 125 + 95 126 + 95 127 + 95 159 + 95 175 + 95 176 + 95 183 + 95 187 + 95 189 + 95 190 + 95 191 + 95 223 + 96 112 + 96 120 + 96 124 + 96 126 + 96 127 + 96 128 + 96 160 + 96 176 + 96 184 + 96 188 + 96 190 + 96 191 + 96 192 + 96 224 + 97 98 + 97 99 + 97 101 + 97 105 + 97 113 + 97 161 + 97 177 + 97 193 + 97 194 + 97 195 + 97 197 + 97 201 + 97 209 + 97 225 + 98 99 + 98 100 + 98 101 + 98 102 + 98 105 + 98 106 + 98 113 + 98 114 + 98 162 + 98 177 + 98 178 + 98 194 + 98 195 + 98 196 + 98 198 + 98 202 + 98 210 + 98 226 + 99 100 + 99 101 + 99 102 + 99 103 + 99 105 + 99 106 + 99 107 + 99 113 + 99 114 + 99 115 + 99 163 + 99 177 + 99 178 + 99 179 + 99 195 + 99 197 + 99 198 + 99 199 + 99 203 + 99 211 + 99 227 + 100 102 + 100 103 + 100 104 + 100 106 + 100 108 + 100 114 + 100 116 + 100 164 + 100 178 + 100 180 + 100 196 + 100 198 + 100 199 + 100 200 + 100 204 + 100 212 + 100 228 + 101 102 + 101 103 + 101 105 + 101 106 + 101 107 + 101 109 + 101 113 + 101 115 + 101 117 + 101 165 + 101 177 + 101 179 + 101 181 + 101 197 + 101 201 + 101 202 + 101 203 + 101 205 + 101 213 + 101 229 + 102 103 + 102 104 + 102 106 + 102 107 + 102 108 + 102 110 + 102 114 + 102 115 + 102 116 + 102 118 + 102 166 + 102 178 + 102 179 + 102 180 + 102 182 + 102 198 + 102 202 + 102 203 + 102 204 + 102 206 + 102 214 + 102 230 + 103 104 + 103 107 + 103 108 + 103 109 + 103 110 + 103 111 + 103 115 + 103 116 + 103 119 + 103 167 + 103 179 + 103 180 + 103 183 + 103 199 + 103 203 + 103 205 + 103 206 + 103 207 + 103 215 + 103 231 + 104 108 + 104 110 + 104 111 + 104 112 + 104 116 + 104 120 + 104 168 + 104 180 + 104 184 + 104 200 + 104 204 + 104 206 + 104 207 + 104 208 + 104 216 + 104 232 + 105 106 + 105 107 + 105 109 + 105 113 + 105 114 + 105 115 + 105 117 + 105 121 + 105 169 + 105 177 + 105 181 + 105 185 + 105 201 + 105 209 + 105 210 + 105 211 + 105 213 + 105 217 + 105 233 + 106 107 + 106 108 + 106 109 + 106 110 + 106 114 + 106 115 + 106 116 + 106 117 + 106 118 + 106 122 + 106 170 + 106 178 + 106 181 + 106 182 + 106 186 + 106 202 + 106 210 + 106 211 + 106 212 + 106 214 + 106 218 + 106 234 + 107 108 + 107 109 + 107 110 + 107 111 + 107 115 + 107 117 + 107 118 + 107 119 + 107 123 + 107 171 + 107 179 + 107 181 + 107 182 + 107 183 + 107 187 + 107 203 + 107 211 + 107 213 + 107 214 + 107 215 + 107 219 + 107 235 + 108 110 + 108 111 + 108 112 + 108 116 + 108 118 + 108 119 + 108 120 + 108 124 + 108 172 + 108 180 + 108 182 + 108 184 + 108 188 + 108 204 + 108 212 + 108 214 + 108 215 + 108 216 + 108 220 + 108 236 + 109 110 + 109 111 + 109 117 + 109 119 + 109 121 + 109 122 + 109 123 + 109 125 + 109 173 + 109 181 + 109 183 + 109 189 + 109 205 + 109 213 + 109 217 + 109 218 + 109 219 + 109 221 + 109 237 + 110 111 + 110 112 + 110 118 + 110 119 + 110 120 + 110 122 + 110 123 + 110 124 + 110 126 + 110 174 + 110 182 + 110 183 + 110 184 + 110 190 + 110 206 + 110 214 + 110 218 + 110 219 + 110 220 + 110 222 + 110 238 + 111 112 + 111 119 + 111 120 + 111 123 + 111 125 + 111 126 + 111 127 + 111 175 + 111 183 + 111 184 + 111 191 + 111 207 + 111 215 + 111 219 + 111 221 + 111 222 + 111 223 + 111 239 + 112 120 + 112 124 + 112 126 + 112 127 + 112 128 + 112 176 + 112 184 + 112 192 + 112 208 + 112 216 + 112 220 + 112 222 + 112 223 + 112 224 + 112 240 + 113 114 + 113 115 + 113 117 + 113 121 + 113 177 + 113 185 + 113 209 + 113 225 + 113 226 + 113 227 + 113 229 + 113 233 + 113 241 + 114 115 + 114 116 + 114 117 + 114 118 + 114 121 + 114 122 + 114 178 + 114 185 + 114 186 + 114 210 + 114 226 + 114 227 + 114 228 + 114 230 + 114 234 + 114 242 + 115 116 + 115 117 + 115 118 + 115 119 + 115 121 + 115 122 + 115 123 + 115 179 + 115 185 + 115 186 + 115 187 + 115 211 + 115 227 + 115 229 + 115 230 + 115 231 + 115 235 + 115 243 + 116 118 + 116 119 + 116 120 + 116 122 + 116 124 + 116 180 + 116 186 + 116 188 + 116 212 + 116 228 + 116 230 + 116 231 + 116 232 + 116 236 + 116 244 + 117 118 + 117 119 + 117 121 + 117 122 + 117 123 + 117 125 + 117 181 + 117 185 + 117 187 + 117 189 + 117 213 + 117 229 + 117 233 + 117 234 + 117 235 + 117 237 + 117 245 + 118 119 + 118 120 + 118 122 + 118 123 + 118 124 + 118 126 + 118 182 + 118 186 + 118 187 + 118 188 + 118 190 + 118 214 + 118 230 + 118 234 + 118 235 + 118 236 + 118 238 + 118 246 + 119 120 + 119 123 + 119 124 + 119 125 + 119 126 + 119 127 + 119 183 + 119 187 + 119 188 + 119 191 + 119 215 + 119 231 + 119 235 + 119 237 + 119 238 + 119 239 + 119 247 + 120 124 + 120 126 + 120 127 + 120 128 + 120 184 + 120 188 + 120 192 + 120 216 + 120 232 + 120 236 + 120 238 + 120 239 + 120 240 + 120 248 + 121 122 + 121 123 + 121 125 + 121 185 + 121 189 + 121 217 + 121 233 + 121 241 + 121 242 + 121 243 + 121 245 + 121 249 + 122 123 + 122 124 + 122 125 + 122 126 + 122 186 + 122 189 + 122 190 + 122 218 + 122 234 + 122 242 + 122 243 + 122 244 + 122 246 + 122 250 + 123 124 + 123 125 + 123 126 + 123 127 + 123 187 + 123 189 + 123 190 + 123 191 + 123 219 + 123 235 + 123 243 + 123 245 + 123 246 + 123 247 + 123 251 + 124 126 + 124 127 + 124 128 + 124 188 + 124 190 + 124 192 + 124 220 + 124 236 + 124 244 + 124 246 + 124 247 + 124 248 + 124 252 + 125 126 + 125 127 + 125 189 + 125 191 + 125 221 + 125 237 + 125 245 + 125 249 + 125 250 + 125 251 + 125 253 + 126 127 + 126 128 + 126 190 + 126 191 + 126 192 + 126 222 + 126 238 + 126 246 + 126 250 + 126 251 + 126 252 + 126 254 + 127 128 + 127 191 + 127 192 + 127 223 + 127 239 + 127 247 + 127 251 + 127 253 + 127 254 + 127 255 + 128 192 + 128 224 + 128 240 + 128 248 + 128 252 + 128 254 + 128 255 + 128 256 + 129 130 + 129 131 + 129 133 + 129 137 + 129 145 + 129 161 + 129 193 + 130 131 + 130 132 + 130 133 + 130 134 + 130 137 + 130 138 + 130 145 + 130 146 + 130 161 + 130 162 + 130 193 + 130 194 + 131 132 + 131 133 + 131 134 + 131 135 + 131 137 + 131 138 + 131 139 + 131 145 + 131 146 + 131 147 + 131 161 + 131 162 + 131 163 + 131 193 + 131 194 + 131 195 + 132 134 + 132 135 + 132 136 + 132 138 + 132 140 + 132 146 + 132 148 + 132 162 + 132 164 + 132 194 + 132 196 + 133 134 + 133 135 + 133 137 + 133 138 + 133 139 + 133 141 + 133 145 + 133 147 + 133 149 + 133 161 + 133 163 + 133 165 + 133 193 + 133 195 + 133 197 + 134 135 + 134 136 + 134 138 + 134 139 + 134 140 + 134 142 + 134 146 + 134 147 + 134 148 + 134 150 + 134 162 + 134 163 + 134 164 + 134 166 + 134 194 + 134 195 + 134 196 + 134 198 + 135 136 + 135 139 + 135 140 + 135 141 + 135 142 + 135 143 + 135 147 + 135 148 + 135 151 + 135 163 + 135 164 + 135 167 + 135 195 + 135 196 + 135 199 + 136 140 + 136 142 + 136 143 + 136 144 + 136 148 + 136 152 + 136 164 + 136 168 + 136 196 + 136 200 + 137 138 + 137 139 + 137 141 + 137 145 + 137 146 + 137 147 + 137 149 + 137 153 + 137 161 + 137 165 + 137 169 + 137 193 + 137 197 + 137 201 + 138 139 + 138 140 + 138 141 + 138 142 + 138 146 + 138 147 + 138 148 + 138 149 + 138 150 + 138 154 + 138 162 + 138 165 + 138 166 + 138 170 + 138 194 + 138 197 + 138 198 + 138 202 + 139 140 + 139 141 + 139 142 + 139 143 + 139 147 + 139 149 + 139 150 + 139 151 + 139 155 + 139 163 + 139 165 + 139 166 + 139 167 + 139 171 + 139 195 + 139 197 + 139 198 + 139 199 + 139 203 + 140 142 + 140 143 + 140 144 + 140 148 + 140 150 + 140 151 + 140 152 + 140 156 + 140 164 + 140 166 + 140 168 + 140 172 + 140 196 + 140 198 + 140 200 + 140 204 + 141 142 + 141 143 + 141 149 + 141 151 + 141 153 + 141 154 + 141 155 + 141 157 + 141 165 + 141 167 + 141 173 + 141 197 + 141 199 + 141 205 + 142 143 + 142 144 + 142 150 + 142 151 + 142 152 + 142 154 + 142 155 + 142 156 + 142 158 + 142 166 + 142 167 + 142 168 + 142 174 + 142 198 + 142 199 + 142 200 + 142 206 + 143 144 + 143 151 + 143 152 + 143 155 + 143 157 + 143 158 + 143 159 + 143 167 + 143 168 + 143 175 + 143 199 + 143 200 + 143 207 + 144 152 + 144 156 + 144 158 + 144 159 + 144 160 + 144 168 + 144 176 + 144 200 + 144 208 + 145 146 + 145 147 + 145 149 + 145 153 + 145 161 + 145 162 + 145 163 + 145 165 + 145 169 + 145 177 + 145 193 + 145 201 + 145 209 + 146 147 + 146 148 + 146 149 + 146 150 + 146 153 + 146 154 + 146 162 + 146 163 + 146 164 + 146 166 + 146 169 + 146 170 + 146 178 + 146 194 + 146 201 + 146 202 + 146 210 + 147 148 + 147 149 + 147 150 + 147 151 + 147 153 + 147 154 + 147 155 + 147 163 + 147 165 + 147 166 + 147 167 + 147 169 + 147 170 + 147 171 + 147 179 + 147 195 + 147 201 + 147 202 + 147 203 + 147 211 + 148 150 + 148 151 + 148 152 + 148 154 + 148 156 + 148 164 + 148 166 + 148 167 + 148 168 + 148 170 + 148 172 + 148 180 + 148 196 + 148 202 + 148 204 + 148 212 + 149 150 + 149 151 + 149 153 + 149 154 + 149 155 + 149 157 + 149 165 + 149 169 + 149 170 + 149 171 + 149 173 + 149 181 + 149 197 + 149 201 + 149 203 + 149 205 + 149 213 + 150 151 + 150 152 + 150 154 + 150 155 + 150 156 + 150 158 + 150 166 + 150 170 + 150 171 + 150 172 + 150 174 + 150 182 + 150 198 + 150 202 + 150 203 + 150 204 + 150 206 + 150 214 + 151 152 + 151 155 + 151 156 + 151 157 + 151 158 + 151 159 + 151 167 + 151 171 + 151 172 + 151 173 + 151 174 + 151 175 + 151 183 + 151 199 + 151 203 + 151 204 + 151 207 + 151 215 + 152 156 + 152 158 + 152 159 + 152 160 + 152 168 + 152 172 + 152 174 + 152 175 + 152 176 + 152 184 + 152 200 + 152 204 + 152 208 + 152 216 + 153 154 + 153 155 + 153 157 + 153 169 + 153 173 + 153 177 + 153 178 + 153 179 + 153 181 + 153 185 + 153 201 + 153 205 + 153 217 + 154 155 + 154 156 + 154 157 + 154 158 + 154 170 + 154 173 + 154 174 + 154 178 + 154 179 + 154 180 + 154 182 + 154 186 + 154 202 + 154 205 + 154 206 + 154 218 + 155 156 + 155 157 + 155 158 + 155 159 + 155 171 + 155 173 + 155 174 + 155 175 + 155 179 + 155 181 + 155 182 + 155 183 + 155 187 + 155 203 + 155 205 + 155 206 + 155 207 + 155 219 + 156 158 + 156 159 + 156 160 + 156 172 + 156 174 + 156 176 + 156 180 + 156 182 + 156 183 + 156 184 + 156 188 + 156 204 + 156 206 + 156 208 + 156 220 + 157 158 + 157 159 + 157 173 + 157 175 + 157 181 + 157 185 + 157 186 + 157 187 + 157 189 + 157 205 + 157 207 + 157 221 + 158 159 + 158 160 + 158 174 + 158 175 + 158 176 + 158 182 + 158 186 + 158 187 + 158 188 + 158 190 + 158 206 + 158 207 + 158 208 + 158 222 + 159 160 + 159 175 + 159 176 + 159 183 + 159 187 + 159 189 + 159 190 + 159 191 + 159 207 + 159 208 + 159 223 + 160 176 + 160 184 + 160 188 + 160 190 + 160 191 + 160 192 + 160 208 + 160 224 + 161 162 + 161 163 + 161 165 + 161 169 + 161 177 + 161 193 + 161 194 + 161 195 + 161 197 + 161 201 + 161 209 + 161 225 + 162 163 + 162 164 + 162 165 + 162 166 + 162 169 + 162 170 + 162 177 + 162 178 + 162 194 + 162 195 + 162 196 + 162 198 + 162 202 + 162 209 + 162 210 + 162 226 + 163 164 + 163 165 + 163 166 + 163 167 + 163 169 + 163 170 + 163 171 + 163 177 + 163 178 + 163 179 + 163 195 + 163 197 + 163 198 + 163 199 + 163 203 + 163 209 + 163 210 + 163 211 + 163 227 + 164 166 + 164 167 + 164 168 + 164 170 + 164 172 + 164 178 + 164 180 + 164 196 + 164 198 + 164 199 + 164 200 + 164 204 + 164 210 + 164 212 + 164 228 + 165 166 + 165 167 + 165 169 + 165 170 + 165 171 + 165 173 + 165 177 + 165 179 + 165 181 + 165 197 + 165 201 + 165 202 + 165 203 + 165 205 + 165 209 + 165 211 + 165 213 + 165 229 + 166 167 + 166 168 + 166 170 + 166 171 + 166 172 + 166 174 + 166 178 + 166 179 + 166 180 + 166 182 + 166 198 + 166 202 + 166 203 + 166 204 + 166 206 + 166 210 + 166 211 + 166 212 + 166 214 + 166 230 + 167 168 + 167 171 + 167 172 + 167 173 + 167 174 + 167 175 + 167 179 + 167 180 + 167 183 + 167 199 + 167 203 + 167 205 + 167 206 + 167 207 + 167 211 + 167 212 + 167 215 + 167 231 + 168 172 + 168 174 + 168 175 + 168 176 + 168 180 + 168 184 + 168 200 + 168 204 + 168 206 + 168 207 + 168 208 + 168 212 + 168 216 + 168 232 + 169 170 + 169 171 + 169 173 + 169 177 + 169 178 + 169 179 + 169 181 + 169 185 + 169 201 + 169 209 + 169 210 + 169 211 + 169 213 + 169 217 + 169 233 + 170 171 + 170 172 + 170 173 + 170 174 + 170 178 + 170 179 + 170 180 + 170 181 + 170 182 + 170 186 + 170 202 + 170 210 + 170 211 + 170 212 + 170 213 + 170 214 + 170 218 + 170 234 + 171 172 + 171 173 + 171 174 + 171 175 + 171 179 + 171 181 + 171 182 + 171 183 + 171 187 + 171 203 + 171 211 + 171 213 + 171 214 + 171 215 + 171 219 + 171 235 + 172 174 + 172 175 + 172 176 + 172 180 + 172 182 + 172 183 + 172 184 + 172 188 + 172 204 + 172 212 + 172 214 + 172 215 + 172 216 + 172 220 + 172 236 + 173 174 + 173 175 + 173 181 + 173 183 + 173 185 + 173 186 + 173 187 + 173 189 + 173 205 + 173 213 + 173 215 + 173 217 + 173 218 + 173 219 + 173 221 + 173 237 + 174 175 + 174 176 + 174 182 + 174 183 + 174 184 + 174 186 + 174 187 + 174 188 + 174 190 + 174 206 + 174 214 + 174 215 + 174 216 + 174 218 + 174 219 + 174 220 + 174 222 + 174 238 + 175 176 + 175 183 + 175 184 + 175 187 + 175 189 + 175 190 + 175 191 + 175 207 + 175 215 + 175 216 + 175 219 + 175 221 + 175 222 + 175 223 + 175 239 + 176 184 + 176 188 + 176 190 + 176 191 + 176 192 + 176 208 + 176 216 + 176 220 + 176 222 + 176 223 + 176 224 + 176 240 + 177 178 + 177 179 + 177 181 + 177 185 + 177 209 + 177 217 + 177 225 + 177 226 + 177 227 + 177 229 + 177 233 + 177 241 + 178 179 + 178 180 + 178 181 + 178 182 + 178 185 + 178 186 + 178 210 + 178 217 + 178 218 + 178 226 + 178 227 + 178 228 + 178 230 + 178 234 + 178 242 + 179 180 + 179 181 + 179 182 + 179 183 + 179 185 + 179 186 + 179 187 + 179 211 + 179 217 + 179 218 + 179 219 + 179 227 + 179 229 + 179 230 + 179 231 + 179 235 + 179 243 + 180 182 + 180 183 + 180 184 + 180 186 + 180 188 + 180 212 + 180 218 + 180 220 + 180 228 + 180 230 + 180 231 + 180 232 + 180 236 + 180 244 + 181 182 + 181 183 + 181 185 + 181 186 + 181 187 + 181 189 + 181 213 + 181 217 + 181 219 + 181 221 + 181 229 + 181 233 + 181 234 + 181 235 + 181 237 + 181 245 + 182 183 + 182 184 + 182 186 + 182 187 + 182 188 + 182 190 + 182 214 + 182 218 + 182 219 + 182 220 + 182 222 + 182 230 + 182 234 + 182 235 + 182 236 + 182 238 + 182 246 + 183 184 + 183 187 + 183 188 + 183 189 + 183 190 + 183 191 + 183 215 + 183 219 + 183 220 + 183 223 + 183 231 + 183 235 + 183 237 + 183 238 + 183 239 + 183 247 + 184 188 + 184 190 + 184 191 + 184 192 + 184 216 + 184 220 + 184 224 + 184 232 + 184 236 + 184 238 + 184 239 + 184 240 + 184 248 + 185 186 + 185 187 + 185 189 + 185 217 + 185 221 + 185 233 + 185 241 + 185 242 + 185 243 + 185 245 + 185 249 + 186 187 + 186 188 + 186 189 + 186 190 + 186 218 + 186 221 + 186 222 + 186 234 + 186 242 + 186 243 + 186 244 + 186 246 + 186 250 + 187 188 + 187 189 + 187 190 + 187 191 + 187 219 + 187 221 + 187 222 + 187 223 + 187 235 + 187 243 + 187 245 + 187 246 + 187 247 + 187 251 + 188 190 + 188 191 + 188 192 + 188 220 + 188 222 + 188 224 + 188 236 + 188 244 + 188 246 + 188 247 + 188 248 + 188 252 + 189 190 + 189 191 + 189 221 + 189 223 + 189 237 + 189 245 + 189 249 + 189 250 + 189 251 + 189 253 + 190 191 + 190 192 + 190 222 + 190 223 + 190 224 + 190 238 + 190 246 + 190 250 + 190 251 + 190 252 + 190 254 + 191 192 + 191 223 + 191 224 + 191 239 + 191 247 + 191 251 + 191 253 + 191 254 + 191 255 + 192 224 + 192 240 + 192 248 + 192 252 + 192 254 + 192 255 + 192 256 + 193 194 + 193 195 + 193 197 + 193 201 + 193 209 + 193 225 + 194 195 + 194 196 + 194 197 + 194 198 + 194 201 + 194 202 + 194 209 + 194 210 + 194 225 + 194 226 + 195 196 + 195 197 + 195 198 + 195 199 + 195 201 + 195 202 + 195 203 + 195 209 + 195 210 + 195 211 + 195 225 + 195 226 + 195 227 + 196 198 + 196 199 + 196 200 + 196 202 + 196 204 + 196 210 + 196 212 + 196 226 + 196 228 + 197 198 + 197 199 + 197 201 + 197 202 + 197 203 + 197 205 + 197 209 + 197 211 + 197 213 + 197 225 + 197 227 + 197 229 + 198 199 + 198 200 + 198 202 + 198 203 + 198 204 + 198 206 + 198 210 + 198 211 + 198 212 + 198 214 + 198 226 + 198 227 + 198 228 + 198 230 + 199 200 + 199 203 + 199 204 + 199 205 + 199 206 + 199 207 + 199 211 + 199 212 + 199 215 + 199 227 + 199 228 + 199 231 + 200 204 + 200 206 + 200 207 + 200 208 + 200 212 + 200 216 + 200 228 + 200 232 + 201 202 + 201 203 + 201 205 + 201 209 + 201 210 + 201 211 + 201 213 + 201 217 + 201 225 + 201 229 + 201 233 + 202 203 + 202 204 + 202 205 + 202 206 + 202 210 + 202 211 + 202 212 + 202 213 + 202 214 + 202 218 + 202 226 + 202 229 + 202 230 + 202 234 + 203 204 + 203 205 + 203 206 + 203 207 + 203 211 + 203 213 + 203 214 + 203 215 + 203 219 + 203 227 + 203 229 + 203 230 + 203 231 + 203 235 + 204 206 + 204 207 + 204 208 + 204 212 + 204 214 + 204 215 + 204 216 + 204 220 + 204 228 + 204 230 + 204 232 + 204 236 + 205 206 + 205 207 + 205 213 + 205 215 + 205 217 + 205 218 + 205 219 + 205 221 + 205 229 + 205 231 + 205 237 + 206 207 + 206 208 + 206 214 + 206 215 + 206 216 + 206 218 + 206 219 + 206 220 + 206 222 + 206 230 + 206 231 + 206 232 + 206 238 + 207 208 + 207 215 + 207 216 + 207 219 + 207 221 + 207 222 + 207 223 + 207 231 + 207 232 + 207 239 + 208 216 + 208 220 + 208 222 + 208 223 + 208 224 + 208 232 + 208 240 + 209 210 + 209 211 + 209 213 + 209 217 + 209 225 + 209 226 + 209 227 + 209 229 + 209 233 + 209 241 + 210 211 + 210 212 + 210 213 + 210 214 + 210 217 + 210 218 + 210 226 + 210 227 + 210 228 + 210 230 + 210 233 + 210 234 + 210 242 + 211 212 + 211 213 + 211 214 + 211 215 + 211 217 + 211 218 + 211 219 + 211 227 + 211 229 + 211 230 + 211 231 + 211 233 + 211 234 + 211 235 + 211 243 + 212 214 + 212 215 + 212 216 + 212 218 + 212 220 + 212 228 + 212 230 + 212 231 + 212 232 + 212 234 + 212 236 + 212 244 + 213 214 + 213 215 + 213 217 + 213 218 + 213 219 + 213 221 + 213 229 + 213 233 + 213 234 + 213 235 + 213 237 + 213 245 + 214 215 + 214 216 + 214 218 + 214 219 + 214 220 + 214 222 + 214 230 + 214 234 + 214 235 + 214 236 + 214 238 + 214 246 + 215 216 + 215 219 + 215 220 + 215 221 + 215 222 + 215 223 + 215 231 + 215 235 + 215 236 + 215 237 + 215 238 + 215 239 + 215 247 + 216 220 + 216 222 + 216 223 + 216 224 + 216 232 + 216 236 + 216 238 + 216 239 + 216 240 + 216 248 + 217 218 + 217 219 + 217 221 + 217 233 + 217 237 + 217 241 + 217 242 + 217 243 + 217 245 + 217 249 + 218 219 + 218 220 + 218 221 + 218 222 + 218 234 + 218 237 + 218 238 + 218 242 + 218 243 + 218 244 + 218 246 + 218 250 + 219 220 + 219 221 + 219 222 + 219 223 + 219 235 + 219 237 + 219 238 + 219 239 + 219 243 + 219 245 + 219 246 + 219 247 + 219 251 + 220 222 + 220 223 + 220 224 + 220 236 + 220 238 + 220 240 + 220 244 + 220 246 + 220 247 + 220 248 + 220 252 + 221 222 + 221 223 + 221 237 + 221 239 + 221 245 + 221 249 + 221 250 + 221 251 + 221 253 + 222 223 + 222 224 + 222 238 + 222 239 + 222 240 + 222 246 + 222 250 + 222 251 + 222 252 + 222 254 + 223 224 + 223 239 + 223 240 + 223 247 + 223 251 + 223 253 + 223 254 + 223 255 + 224 240 + 224 248 + 224 252 + 224 254 + 224 255 + 224 256 + 225 226 + 225 227 + 225 229 + 225 233 + 225 241 + 226 227 + 226 228 + 226 229 + 226 230 + 226 233 + 226 234 + 226 241 + 226 242 + 227 228 + 227 229 + 227 230 + 227 231 + 227 233 + 227 234 + 227 235 + 227 241 + 227 242 + 227 243 + 228 230 + 228 231 + 228 232 + 228 234 + 228 236 + 228 242 + 228 244 + 229 230 + 229 231 + 229 233 + 229 234 + 229 235 + 229 237 + 229 241 + 229 243 + 229 245 + 230 231 + 230 232 + 230 234 + 230 235 + 230 236 + 230 238 + 230 242 + 230 243 + 230 244 + 230 246 + 231 232 + 231 235 + 231 236 + 231 237 + 231 238 + 231 239 + 231 243 + 231 244 + 231 247 + 232 236 + 232 238 + 232 239 + 232 240 + 232 244 + 232 248 + 233 234 + 233 235 + 233 237 + 233 241 + 233 242 + 233 243 + 233 245 + 233 249 + 234 235 + 234 236 + 234 237 + 234 238 + 234 242 + 234 243 + 234 244 + 234 245 + 234 246 + 234 250 + 235 236 + 235 237 + 235 238 + 235 239 + 235 243 + 235 245 + 235 246 + 235 247 + 235 251 + 236 238 + 236 239 + 236 240 + 236 244 + 236 246 + 236 247 + 236 248 + 236 252 + 237 238 + 237 239 + 237 245 + 237 247 + 237 249 + 237 250 + 237 251 + 237 253 + 238 239 + 238 240 + 238 246 + 238 247 + 238 248 + 238 250 + 238 251 + 238 252 + 238 254 + 239 240 + 239 247 + 239 248 + 239 251 + 239 253 + 239 254 + 239 255 + 240 248 + 240 252 + 240 254 + 240 255 + 240 256 + 241 242 + 241 243 + 241 245 + 241 249 + 242 243 + 242 244 + 242 245 + 242 246 + 242 249 + 242 250 + 243 244 + 243 245 + 243 246 + 243 247 + 243 249 + 243 250 + 243 251 + 244 246 + 244 247 + 244 248 + 244 250 + 244 252 + 245 246 + 245 247 + 245 249 + 245 250 + 245 251 + 245 253 + 246 247 + 246 248 + 246 250 + 246 251 + 246 252 + 246 254 + 247 248 + 247 251 + 247 252 + 247 253 + 247 254 + 247 255 + 248 252 + 248 254 + 248 255 + 248 256 + 249 250 + 249 251 + 249 253 + 250 251 + 250 252 + 250 253 + 250 254 + 251 252 + 251 253 + 251 254 + 251 255 + 252 254 + 252 255 + 252 256 + 253 254 + 253 255 + 254 255 + 254 256 + 255 256 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/money.mod b/resources/3rdparty/glpk-4.53/examples/money.mod new file mode 100644 index 000000000..e43ef390b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/money.mod @@ -0,0 +1,62 @@ +/* MONEY, a crypto-arithmetic puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* This is the classic example of a crypto-arithmetic puzzle published + in the Strand Magazine by Henry Dudeney: + + S E N D + + + M O R E + --------- + M O N E Y + + In this puzzle the same letters mean the same digits. The question + is: how to replace all the letters with the respective digits that + makes the calculation correct? + + The solution to this puzzle is: + O = 0, M = 1, Y = 2, E = 5, N = 6, D = 7, R = 8, and S = 9. + + References: + H. E. Dudeney, in Strand Magazine vol. 68 (July 1924), pp. 97, 214. + + (From Wikipedia, the free encyclopedia.) */ + +set LETTERS := { 'D', 'E', 'M', 'N', 'O', 'R', 'S', 'Y' }; +/* set of letters */ + +set DIGITS := 0..9; +/* set of digits */ + +var x{i in LETTERS, d in DIGITS}, binary; +/* x[i,d] = 1 means that letter i is digit d */ + +s.t. one{i in LETTERS}: sum{d in DIGITS} x[i,d] = 1; +/* each letter must correspond exactly to one digit */ + +s.t. alldiff{d in DIGITS}: sum{i in LETTERS} x[i,d] <= 1; +/* different letters must correspond to different digits; note that + some digits may not correspond to any letters at all */ + +var dig{i in LETTERS}; +/* dig[i] is a digit corresponding to letter i */ + +s.t. map{i in LETTERS}: dig[i] = sum{d in DIGITS} d * x[i,d]; + +var carry{1..3}, binary; +/* carry bits */ + +s.t. sum1: dig['D'] + dig['E'] = dig['Y'] + 10 * carry[1]; +s.t. sum2: dig['N'] + dig['R'] + carry[1] = dig['E'] + 10 * carry[2]; +s.t. sum3: dig['E'] + dig['O'] + carry[2] = dig['N'] + 10 * carry[3]; +s.t. sum4: dig['S'] + dig['M'] + carry[3] = dig['O'] + 10 * dig['M']; +s.t. note: dig['M'] >= 1; /* M must not be 0 */ + +solve; +/* solve the puzzle */ + +display dig; +/* and display its solution */ + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/mplsamp1.c b/resources/3rdparty/glpk-4.53/examples/mplsamp1.c new file mode 100644 index 000000000..7c5e47d4d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/mplsamp1.c @@ -0,0 +1,32 @@ +/* mplsamp1.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *lp; + glp_tran *tran; + int ret; + lp = glp_create_prob(); + tran = glp_mpl_alloc_wksp(); + ret = glp_mpl_read_model(tran, "egypt.mod", 0); + if (ret != 0) + { fprintf(stderr, "Error on translating model\n"); + goto skip; + } + ret = glp_mpl_generate(tran, NULL); + if (ret != 0) + { fprintf(stderr, "Error on generating model\n"); + goto skip; + } + glp_mpl_build_prob(tran, lp); + ret = glp_write_mps(lp, GLP_MPS_FILE, NULL, "egypt.mps"); + if (ret != 0) + fprintf(stderr, "Error on writing MPS file\n"); +skip: glp_mpl_free_wksp(tran); + glp_delete_prob(lp); + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/mplsamp2.c b/resources/3rdparty/glpk-4.53/examples/mplsamp2.c new file mode 100644 index 000000000..0ff6ad0ff --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/mplsamp2.c @@ -0,0 +1,39 @@ +/* mplsamp2.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *mip; + glp_tran *tran; + int ret; + mip = glp_create_prob(); + tran = glp_mpl_alloc_wksp(); + ret = glp_mpl_read_model(tran, "sudoku.mod", 1); + if (ret != 0) + { fprintf(stderr, "Error on translating model\n"); + goto skip; + } + ret = glp_mpl_read_data(tran, "sudoku.dat"); + if (ret != 0) + { fprintf(stderr, "Error on translating data\n"); + goto skip; + } + ret = glp_mpl_generate(tran, NULL); + if (ret != 0) + { fprintf(stderr, "Error on generating model\n"); + goto skip; + } + glp_mpl_build_prob(tran, mip); + glp_simplex(mip, NULL); + glp_intopt(mip, NULL); + ret = glp_mpl_postsolve(tran, mip, GLP_MIP); + if (ret != 0) + fprintf(stderr, "Error on postsolving model\n"); +skip: glp_mpl_free_wksp(tran); + glp_delete_prob(mip); + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/murtagh.mps b/resources/3rdparty/glpk-4.53/examples/murtagh.mps new file mode 100644 index 000000000..c03741b51 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/murtagh.mps @@ -0,0 +1,600 @@ +*NAME: OIL +*ROWS: 74 +*COLUMNS: 81 +*NONZERO: 504 +*OPT SOLN: 126.057 +*SOURCE: Bruce Murtagh, "Advanced Linear Programming" +*APPLICATION: oil refinery model +*COMMENTS: problem is maximization +* +NAME OIL REFINERY EXAMPLE +ROWS + N PROFIT + L MVOLBOL + L MVOLCOL + E MVOLLNC + E MVOLLNB + E MVOLSRK + E MVOLSRD + E MVOLVBB + E MVOLVBC + E MVOLRCR + E MVOLHVO + E UBALKWH + E UBALH2O + E UBALSTM + E UBALFUL + E MVOLB95 + E MVOLB90 + E MVOLLHG + E MVOLC3S + E MVOLNC4 + E MVOLLSR + E MVOLHSR + E MVOLIC4 + L VCAPSGP + E MVOLRFG + E MSCFHYL + E MVOLR90 + E MVOLR95 + E MVOLF90 + E MVOLF95 + L VCAPRFG + E MVOLLCO + E MVOLHHG + E MVOLHCD + L VCAPHVO + L VCAPHOL + E MVOLC3U + E MVOLC4U + E MVOLFCG + E MVOLSLR + L VCAPCCU + E MVOLLA3 + E MVOLLA4 + L VCAPALK + L XLPRPRE + L XHPRPRE + L XTELPRE + L XRVPPRE + L X200PRE + L X230PRE + E EVOLPRE + L XPSCPRE + L XRSCREG + L XLPRINT + L XHPRINT + L XTELINT + L XRVPINT + L X200INT + L X230INT + E EVOLINT + L XLPRREG + L XHPRREG + L XTELREG + L XRVPREG + L X200REG + L X230REG + E EVOLREG + E EVOLLPG + E EVOLJP4 + L XRVXJP4 + L XRVNJP4 + E EVOLDSL + E EVOLRSD + L XVISRSD +COLUMNS + VCRDBOL MVOLBOL 1.0 + VCRDBOL MVOLLNB -.537 + VCRDBOL MVOLSRK -.131 + VCRDBOL MVOLSRD -.1155 + VCRDBOL MVOLVBB -.037 + VCRDBOL MVOLRCR -.0365 + VCRDBOL MVOLHVO -.143 + VCRDBOL UBALKWH .302 + VCRDBOL UBALH2O .150 + VCRDBOL UBALSTM .003 + VCRDBOL UBALFUL .0587 + VCRDBOL PROFIT -12.8 + VCRDCOL MVOLCOL 1. + VCRDCOL MVOLLNC -.2931 + VCRDCOL MVOLSRK -.1170 + VCRDCOL MVOLSRD -.0649 + VCRDCOL MVOLVBC -.18 + VCRDCOL MVOLRCR -.1233 + VCRDCOL MVOLHVO -.2217 + VCRDCOL UBALKWH .384 + VCRDCOL UBALH2O .185 + VCRDCOL UBALSTM .003 + VCRDCOL UBALFUL .1053 + VCRDCOL PROFIT -11.48 + VSGPLNC MVOLLNC 1. + VSGPLNC MVOLC3S -.0112 + VSGPLNC MVOLNC4 -.0378 + VSGPLNC MVOLLSR -.1502 + VSGPLNC MVOLHSR -.7953 + VSGPLNC MVOLIC4 -.0099 + VSGPLNC UBALKWH .721 + VSGPLNC UBALH2O .185 + VSGPLNC UBALSTM .013 + VSGPLNC UBALFUL .0488 + VSGPLNC VCAPSGP 1. + VSGPLNB MVOLLNB 1. + VSGPLNB MVOLC3S -.0277 + VSGPLNB MVOLNC4 -.0563 + VSGPLNB MVOLLSR -.199 + VSGPLNB MVOLHSR -.6873 + VSGPLNB MVOLIC4 -.017 + VSGPLNB UBALKWH .495 + VSGPLNB UBALH2O .209 + VSGPLNB UBALSTM .013 + VSGPLNB UBALFUL .0506 + VSGPLNB VCAPSGP 1. + VSGPLHG MVOLLHG 1.0 + VSGPLHG MVOLC3S -.175 + VSGPLHG MVOLNC4 -.27 + VSGPLHG MVOLLSR -.028 + VSGPLHG MVOLIC4 -.455 + VSGPLHG UBALKWH .495 + VSGPLHG UBALH2O .209 + VSGPLHG UBALSTM .013 + VSGPLHG UBALFUL .0448 + VSGPB95 MVOLB95 1. + VSGPB95 MVOLC3S -.2836 + VSGPB95 MVOLNC4 -.3285 + VSGPB95 MVOLLSR -.0241 + VSGPB95 MVOLIC4 -.2502 + VSGPB95 UBALKWH .495 + VSGPB95 UBALH2O .209 + VSGPB95 UBALSTM .013 + VSGPB95 UBALFUL .0506 + VSGPB90 MVOLB90 1. + VSGPB90 MVOLC3S -.271 + VSGPB90 MVOLNC4 -.3289 + VSGPB90 MVOLLSR -.0255 + VSGPB90 MVOLIC4 -.2656 + VSGPB90 UBALKWH .495 + VSGPB90 UBALH2O .209 + VSGPB90 UBALSTM .013 + VSGPB90 UBALFUL .0506 + VH2RHSR MVOLHSR 1. + VH2RHSR MVOLRFG -1. + VH2RHSR MSCFHYL .0327 + VH2RHSR UBALKWH .793 + VH2RHSR UBALH2O .045 + VH2RHSR UBALFUL .094 + VH2RHSR PROFIT -.0176 + VRFFRF1 MVOLRFG 1.0 + VRFFRF1 MVOLR90 -1.0 + VRFFRF2 MVOLRFG 1.0 + VRFFRF2 MVOLR95 -1.0 + VRFFHH1 MVOLR90 -1.0 + VRFFHH1 MVOLHHG 1.0 + VRFFHH2 MVOLR95 -1.0 + VRFFHH2 MVOLHHG 1.0 + VRFGR90 MVOLR90 1.0 + VRFGR90 MVOLB90 -.0404 + VRFGR90 MVOLF90 -0.8564 + VRFGR90 MSCFHYL -0.8239 + VRFGR90 UBALKWH .792 + VRFGR90 UBALH2O .297 + VRFGR90 UBALSTM 0.0063 + VRFGR90 UBALFUL -0.156 + VRFGR90 VCAPRFG 1.0 + VRFGR90 PROFIT -0.1512 + VRFGR95 MVOLR95 1.0 + VRFGR95 MVOLB95 -0.0588 + VRFGR95 MVOLF95 -0.8145 + VRFGR95 MSCFHYL -.7689 + VRFGR95 UBALKWH 1.03 + VRFGR95 UBALH2O .387 + VRFGR95 UBALSTM 0.008 + VRFGR95 UBALFUL -.2112 + VRFGR95 VCAPRFG 1.3 + VRFGR95 PROFIT -0.304 + VHOLLCO MVOLLCO 1.0 + VHOLLCO MVOLHHG -.6627 + VHOLLCO MVOLLHG -0.2414 + VHOLLCO MVOLHCD -.2930 + VHOLLCO MSCFHYL 2.3 + VHOLLCO UBALFUL -.2054 + VHOLLCO UBALH2O 0.826 + VHOLLCO UBALKWH 14.61 + VHOLLCO VCAPHOL 1.0 + VHOLLCO PROFIT -0.2112 + VHOLSRD MVOLSRD 1.0 + VHOLSRD MVOLHHG -.6627 + VHOLSRD MVOLLHG -0.2414 + VHOLSRD MVOLHCD -.2930 + VHOLSRD MSCFHYL 2.3 + VHOLSRD UBALFUL -.2054 + VHOLSRD UBALH2O 0.826 + VHOLSRD UBALKWH 14.61 + VHOLSRD VCAPHOL 1.0 + VHOLSRD PROFIT -0.2112 + VHOLRCR MVOLRCR 1.0 + VHOLRCR MVOLHHG -.5875 + VHOLRCR MVOLLHG -0.3321 + VHOLRCR MVOLHCD -.3620 + VHOLRCR MSCFHYL 2.3 + VHOLRCR UBALFUL -.2054 + VHOLRCR UBALH2O 0.826 + VHOLRCR UBALKWH 14.61 + VHOLRCR VCAPHOL 1.0 + VHOLRCR PROFIT -0.2112 + VHOLHVO MVOLHVO 1.0 + VHOLHVO MVOLHHG -.5875 + VHOLHVO MVOLLHG -0.3321 + VHOLHVO MVOLHCD -.3620 + VHOLHVO MSCFHYL 2.3 + VHOLHVO UBALFUL -.2054 + VHOLHVO UBALH2O 0.826 + VHOLHVO UBALKWH 14.61 + VHOLHVO VCAPHVO 1.0 + VHOLHVO VCAPHOL 1.0 + VHOLHVO PROFIT -0.2112 + VCCUSRK MVOLSRK 1.0 + VCCUSRK MVOLNC4 -0.0184 + VCCUSRK MVOLC3S -0.0303 + VCCUSRK MVOLIC4 -0.0564 + VCCUSRK MVOLC3U -0.0655 + VCCUSRK MVOLC4U -0.0780 + VCCUSRK MVOLFCG -0.4750 + VCCUSRK MVOLLCO -0.3050 + VCCUSRK UBALSTM -.0654 + VCCUSRK UBALFUL -.2703 + VCCUSRK UBALH2O .632 + VCCUSRK UBALKWH .6807 + VCCUSRK VCAPCCU 1. + VCCUSRK PROFIT -.2112 + VCCUSRD MVOLSRD 1. + VCCUSRD MVOLNC4 -.0184 + VCCUSRD MVOLC3S -.0303 + VCCUSRD MVOLIC4 -.0564 + VCCUSRD MVOLC3U -.0655 + VCCUSRD MVOLC4U -.0780 + VCCUSRD MVOLFCG -.4750 + VCCUSRD MVOLLCO -.3050 + VCCUSRD UBALSTM -.0654 + VCCUSRD UBALFUL -.2703 + VCCUSRD UBALH2O 0.632 + VCCUSRD UBALKWH .6807 + VCCUSRD VCAPCCU 1. + VCCUSRD PROFIT -.2112 + VCCURCR MVOLRCR 1.0 + VCCURCR MVOLNC4 -.0185 + VCCURCR MVOLC3S -.0328 + VCCURCR MVOLIC4 -.0568 + VCCURCR MVOLC3U -.0658 + VCCURCR MVOLC4U -.0806 + VCCURCR MVOLFCG -.4934 + VCCURCR MVOLLCO -.2922 + VCCURCR MVOLSLR -.0096 + VCCURCR UBALSTM -.0654 + VCCURCR UBALFUL -.2703 + VCCURCR UBALH2O 0.632 + VCCURCR UBALKWH .6807 + VCCURCR VCAPCCU 1. + VCCURCR PROFIT -.2112 + VCCUHVO MVOLHVO 1.0 + VCCUHVO MVOLNC4 -.0185 + VCCUHVO MVOLC3S -.0328 + VCCUHVO MVOLIC4 -.0568 + VCCUHVO MVOLC3U -.0658 + VCCUHVO MVOLC4U -.0806 + VCCUHVO MVOLFCG -.4934 + VCCUHVO MVOLLCO -.2922 + VCCUHVO MVOLSLR -.0096 + VCCUHVO UBALSTM -.0654 + VCCUHVO UBALFUL -.2703 + VCCUHVO UBALH2O 0.632 + VCCUHVO UBALKWH .6807 + VCCUHVO VCAPHVO 1. + VCCUHVO VCAPCCU 1. + VCCUHVO PROFIT -.2112 + VALKLA3 MVOLIC4 .7600 + VALKLA3 MVOLC3U .5714 + VALKLA3 MVOLLA3 -1.0 + VALKLA3 UBALSTM .1869 + VALKLA3 UBALFUL .2796 + VALKLA3 UBALH2O 2.241 + VALKLA3 UBALKWH 2.766 + VALKLA3 VCAPALK 1.0 + VALKLA3 PROFIT -.512 + VALKLA4 MVOLIC4 .6571 + VALKLA4 MVOLC4U .5714 + VALKLA4 MVOLC3S -.0571 + VALKLA4 MVOLNC4 -.0114 + VALKLA4 MVOLLA4 -1.0 + VALKLA4 UBALSTM .1724 + VALKLA4 UBALFUL .2579 + VALKLA4 UBALH2O 2.067 + VALKLA4 UBALKWH 2.552 + VALKLA4 VCAPALK 1.0 + VALKLA4 PROFIT -.472 + VALKIC4 MVOLIC4 1.0 + VALKIC4 MVOLNC4 -1.0 + VALKC3U MVOLC3U 1.0 + VALKC3U MVOLC3S -1.0 + VALKC4U MVOLC4U 1.0 + VALKC4U MVOLNC4 -1.0 + UTILC3S MVOLC3S 1. + UTILC3S UBALFUL -3.814 + UTILNC4 MVOLNC4 1. + UTILNC4 UBALFUL -4.316 + UTILIC4 MVOLIC4 1. + UTILIC4 UBALFUL -4.153 + UTILC3U MVOLC3U 1. + UTILC3U UBALFUL -3.808 + UTILC4U MVOLC4U 1. + UTILC4U UBALFUL -4.44 + UTILHYL MSCFHYL 1. + UTILHYL UBALFUL -.305 + UTILSTM UBALSTM -1. + UTILSTM UBALFUL 1.42 + UTILSTM PROFIT -.16 + PURCPC4 MVOLIC4 -.5 + PURCPC4 MVOLNC4 -.5 + PURCPC4 PROFIT -12. + PURCH2O UBALH2O -1. + PURCH2O PROFIT -.0528 + PURCKWH UBALKWH -1. + PURCKWH PROFIT -.04 + PURCFUL UBALFUL -1. + PURCFUL PROFIT -1.6 + PURCFLR UBALFUL 1. + BLPGC3S MVOLC3S 1.0 + BLPGC3S EVOLLPG -1.0 + BLPGNC4 MVOLNC4 1.0 + BLPGNC4 EVOLLPG -1.0 + SELLLPG EVOLLPG 1.0 + SELLLPG PROFIT 11.0 + BUP4LSR MVOLLSR 1.0 + BUP4LSR EVOLJP4 -1.0 + BUP4LSR XRVXJP4 14.0 + BUP4LSR XRVNJP4 -14.0 + BUP4HSR MVOLHSR 1.0 + BUP4HSR EVOLJP4 -1.0 + BUP4HSR XRVXJP4 0.8 + BUP4HSR XRVNJP4 -0.8 + SELLJP4 EVOLJP4 1.0 + SELLJP4 XRVXJP4 -3.0 + SELLJP4 XRVNJP4 2.0 + SELLJP4 PROFIT 16.8 + BDSLSRK MVOLSRK 1.0 + BDSLSRK EVOLDSL -1.0 + BDSLSRD MVOLSRD 1.0 + BDSLSRD EVOLDSL -1.0 + SELLDSL EVOLDSL 1.0 + SELLDSL PROFIT 14.4 + BPRELSR MVOLLSR 1. + BPRELSR XLPRPRE -7.95 + BPRELSR XHPRPRE -8.70 + BPRELSR XTELPRE -3.00 + BPRELSR XRVPPRE 14.00 + BPRELSR X200PRE 1. + BPRELSR X230PRE -1. + BPRELSR EVOLPRE -1. + BPREHCD MVOLHCD 1.0 + BPREHCD XLPRPRE -8.84 + BPREHCD XHPRPRE -9.45 + BPREHCD XTELPRE -3.00 + BPREHCD XRVPPRE 12.00 + BPREHCD X200PRE 1. + BPREHCD X230PRE -1. + BPREHCD EVOLPRE -1. + BPREF95 MVOLF95 1.0 + BPREF95 XLPRPRE -9.43 + BPREF95 XHPRPRE -9.57 + BPREF95 XTELPRE -3. + BPREF95 XRVPPRE 3.5 + BPREF95 X200PRE .233 + BPREF95 X230PRE -.358 + BPREF95 EVOLPRE -1. + BPREF90 MVOLF90 1.0 + BPREF90 XLPRPRE -9.03 + BPREF90 XHPRPRE -9.32 + BPREF90 XTELPRE -3.0 + BPREF90 XRVPPRE 3.5 + BPREF90 X200PRE .205 + BPREF90 X230PRE -.333 + BPREF90 EVOLPRE -1. + BPREFCG MVOLFCG 1.0 + BPREFCG XLPRPRE -9.23 + BPREFCG XHPRPRE -9.22 + BPREFCG XTELPRE -3. + BPREFCG XRVPPRE 6. + BPREFCG X200PRE .381 + BPREFCG X230PRE -.509 + BPREFCG EVOLPRE -1. + BPRELA3 MVOLLA3 1.0 + BPRELA3 XLPRPRE -9.4 + BPRELA3 XHPRPRE -9.85 + BPRELA3 XTELPRE -3.0 + BPRELA3 XRVPPRE 2.5 + BPRELA3 X200PRE 0.39 + BPRELA3 X230PRE -0.77 + BPRELA3 EVOLPRE -1.0 + BPRELA4 MVOLLA4 1.0 + BPRELA4 XLPRPRE -9.74 + BPRELA4 XHPRPRE -10.1 + BPRELA4 XTELPRE -3.0 + BPRELA4 XRVPPRE 3.3 + BPRELA4 X200PRE 0.233 + BPRELA4 X230PRE -0.58 + BPRELA4 EVOLPRE -1.0 + BPRENC4 MVOLNC4 1.0 + BPRENC4 XLPRPRE -9.74 + BPRENC4 XHPRPRE -9.9 + BPRENC4 XTELPRE -3.0 + BPRENC4 XRVPPRE 66.0 + BPRENC4 X200PRE 1.0 + BPRENC4 X230PRE -1.0 + BPRENC4 EVOLPRE -1.0 + BPRETEL XLPRPRE -0.493 + BPRETEL XHPRPRE -0.165 + BPRETEL XTELPRE 1.0 + BPRETEL PROFIT -0.3696 + SELLPRE XLPRPRE 10.03 + SELLPRE XHPRPRE 10.03 + SELLPRE XRVPPRE -9.5 + SELLPRE X200PRE -0.5 + SELLPRE X230PRE 0.5 + SELLPRE XPSCPRE 0.64 + SELLPRE XRSCREG 0.35 + SELLPRE EVOLPRE 1.0 + SELLPRE PROFIT 21.44 + BINTLSR MVOLLSR 1.0 + BINTLSR XLPRINT -7.98 + BINTLSR XHPRINT -8.58 + BINTLSR XTELINT -3.0 + BINTLSR XRVPINT 14.0 + BINTLSR X200INT 1.0 + BINTLSR X230INT -1.0 + BINTLSR EVOLINT -1.0 + BINTHCD MVOLHCD 1. + BINTHCD XLPRINT -8.87 + BINTHCD XHPRINT -9.33 + BINTHCD XTELINT -3.0 + BINTHCD XRVPINT 12.0 + BINTHCD X200INT 1.0 + BINTHCD X230INT -1. + BINTHCD EVOLINT -1.0 + BINTF95 MVOLF95 1. + BINTF95 XLPRINT -9.46 + BINTF95 XHPRINT -9.45 + BINTF95 XTELINT -3.0 + BINTF95 XRVPINT 3.5 + BINTF95 X200INT .233 + BINTF95 X230INT -.358 + BINTF95 EVOLINT -1.0 + BINTF90 MVOLF90 1. + BINTF90 XLPRINT -9.06 + BINTF90 XHPRINT -9.20 + BINTF90 XTELINT -3.0 + BINTF90 XRVPINT 3.5 + BINTF90 X200INT .205 + BINTF90 X230INT -.333 + BINTF90 EVOLINT -1.0 + BINTFCG MVOLFCG 1. + BINTFCG XLPRINT -9.26 + BINTFCG XHPRINT -9.13 + BINTFCG XTELINT -3.0 + BINTFCG XRVPINT 6. + BINTFCG X200INT .318 + BINTFCG X230INT -.509 + BINTFCG EVOLINT -1.0 + BINTNC4 MVOLNC4 1. + BINTNC4 XLPRINT -9.77 + BINTNC4 XHPRINT -9.78 + BINTNC4 XTELINT -3.0 + BINTNC4 XRVPINT 66. + BINTNC4 X200INT 1.0 + BINTNC4 X230INT -1. + BINTNC4 EVOLINT -1.0 + BINTTEL XLPRINT -.435 + BINTTEL XHPRINT -.208 + BINTTEL XTELINT 1. + BINTTEL PROFIT -.3696 + SELLINT XLPRINT 9.65 + SELLINT XHPRINT 9.65 + SELLINT XRVPINT -9.5 + SELLINT X200INT -0.5 + SELLINT X230INT 0.5 + SELLINT XPSCPRE -.36 + SELLINT XRSCREG 0.35 + SELLINT EVOLINT 1.0 + SELLINT PROFIT 20.32 + BREGLSR MVOLLSR 1.0 + BREGLSR XLPRREG -7.99 + BREGLSR XHPRREG -8.59 + BREGLSR XTELREG -3.0 + BREGLSR XRVPREG 14.0 + BREGLSR X200REG 1.0 + BREGLSR X230REG -1.0 + BREGLSR EVOLREG -1.0 + BREGHCD MVOLHCD 1.0 + BREGHCD XLPRREG -8.88 + BREGHCD XHPRREG -9.34 + BREGHCD XTELREG -3.0 + BREGHCD XRVPREG 12.0 + BREGHCD X200REG 1.0 + BREGHCD X230REG -1.0 + BREGHCD EVOLREG -1.0 + BREGF95 MVOLF95 1.0 + BREGF95 XLPRREG -9.47 + BREGF95 XHPRREG -9.46 + BREGF95 XTELREG -3.0 + BREGF95 XRVPREG 3.5 + BREGF95 X200REG .233 + BREGF95 X230REG -0.358 + BREGF95 EVOLREG -1.0 + BREGF90 MVOLF90 1.0 + BREGF90 XLPRREG -9.07 + BREGF90 XHPRREG -9.21 + BREGF90 XTELREG -3.0 + BREGF90 XRVPREG 3.5 + BREGF90 X200REG .205 + BREGF90 X230REG -0.333 + BREGF90 EVOLREG -1.0 + BREGFCG MVOLFCG 1.0 + BREGFCG XLPRREG -9.27 + BREGFCG XHPRREG -9.14 + BREGFCG XTELREG -3.0 + BREGFCG XRVPREG 6.0 + BREGFCG X200REG 0.318 + BREGFCG X230REG -0.509 + BREGFCG EVOLREG -1.0 + BREGNC4 MVOLNC4 1.0 + BREGNC4 XLPRREG -9.78 + BREGNC4 XHPRREG -9.79 + BREGNC4 XTELREG -3.0 + BREGNC4 XRVPREG 66.0 + BREGNC4 X200REG 1.0 + BREGNC4 X230REG -1.0 + BREGNC4 EVOLREG -1.0 + BREGTEL XLPRREG -0.426 + BREGTEL XHPRREG -.204 + BREGTEL XTELREG 1.0 + BREGTEL PROFIT -0.3696 + SELLREG XLPRREG 9.05 + SELLREG XHPRREG 9.05 + SELLREG XRVPREG -9.5 + SELLREG X200REG -0.5 + SELLREG X230REG 0.5 + SELLREG XPSCPRE -0.36 + SELLREG XRSCREG -0.65 + SELLREG EVOLREG 1.0 + SELLREG PROFIT 18.04 + BRSDVBB MVOLVBB 1.0 + BRSDVBB EVOLRSD -1.0 + BRSDVBB XVISRSD 10.1 + BRSDVBC MVOLVBC 1.0 + BRSDVBC EVOLRSD -1.0 + BRSDVBC XVISRSD 12.63 + BRSDRCR MVOLRCR 1.0 + BRSDRCR EVOLRSD -1.0 + BRSDRCR XVISRSD 6.9 + BRSDHVO MVOLHVO 1.0 + BRSDHVO EVOLRSD -1.0 + BRSDHVO XVISRSD 8.05 + BRSDHVO VCAPHVO 1.0 + BRSDSLR MVOLSLR 1.0 + BRSDSLR EVOLRSD -1.0 + BRSDSLR XVISRSD 8.05 + BRSDLCO MVOLLCO 1.0 + BRSDLCO EVOLRSD -1.0 + BRSDLCO XVISRSD 4.4 + SELLRSD EVOLRSD 1.0 + SELLRSD XVISRSD -10.1 + SELLRSD PROFIT 8.00 +RHS + LIMITMAX MVOLBOL 26.316 + LIMITMAX MVOLCOL 21.052 + LIMITMAX VCAPSGP 23.25 + LIMITMAX VCAPHVO 5.25 + LIMITMAX VCAPRFG 13.455 + LIMITMAX VCAPHOL 3.87 + LIMITMAX VCAPCCU 7.26 + LIMITMAX VCAPALK 10. +ENDATA diff --git a/resources/3rdparty/glpk-4.53/examples/mvcp.mod b/resources/3rdparty/glpk-4.53/examples/mvcp.mod new file mode 100644 index 000000000..e016bda28 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/mvcp.mod @@ -0,0 +1,43 @@ +/* MVCP, Minimum Vertex Cover Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Minimum Vertex Cover Problem in a network G = (V, E), where V + is a set of nodes, E is a set of arcs, is to find a subset V' within + V such that each edge (i,j) in E has at least one its endpoint in V' + and which minimizes the sum of node weights w(i) over V'. + + Reference: + Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: + A guide to the theory of NP-completeness [Graph Theory, Covering and + Partitioning, Minimum Vertex Cover, GT1]. */ + +set E, dimen 2; +/* set of edges */ + +set V := (setof{(i,j) in E} i) union (setof{(i,j) in E} j); +/* set of nodes */ + +param w{i in V}, >= 0, default 1; +/* w[i] is weight of vertex i */ + +var x{i in V}, binary; +/* x[i] = 1 means that node i is included into V' */ + +s.t. cov{(i,j) in E}: x[i] + x[j] >= 1; +/* each edge (i,j) must have node i or j (or both) in V' */ + +minimize z: sum{i in V} w[i] * x[i]; +/* we need to minimize the sum of node weights over V' */ + +data; + +/* These data correspond to an example from [Papadimitriou]. */ + +/* Optimal solution is 6 (greedy heuristic gives 13) */ + +set E := a1 b1, b1 c1, a1 b2, b2 c2, a2 b3, b3 c3, a2 b4, b4 c4, a3 b5, + b5 c5, a3 b6, b6 c6, a4 b1, a4 b2, a4 b3, a5 b4, a5 b5, a5 b6, + a6 b1, a6 b2, a6 b3, a6 b4, a7 b2, a7 b3, a7 b4, a7 b5, a7 b6; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/netgen.c b/resources/3rdparty/glpk-4.53/examples/netgen.c new file mode 100644 index 000000000..eebb2c867 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/netgen.c @@ -0,0 +1,141 @@ +/* netgen.c */ + +/* This main program generates 50 original NETGEN instances of the + minimum cost flow problem and writes them in DIMACS format to the + current directory. */ + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +static int parm[50][15] = +{ {13502460, 101, + 5000, 2500, 2500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{4281922, 102, + 5000, 2500, 2500, 25000, 1, 100, 2500000, 0, 0, 0, 100, 1, 1000, + },{44820113, 103, + 5000, 2500, 2500, 25000, 1, 100, 6250000, 0, 0, 0, 100, 1, 1000, + },{13450451, 104, + 5000, 2500, 2500, 25000, -100, -1, 250000, 0, 0, 0, 100, 1, 1000, + },{14719436, 105, + 5000, 2500, 2500, 25000, 101, 200, 250000, 0, 0, 0, 100, 1, 1000, + },{17365786, 106, + 5000, 2500, 2500, 12500, 1, 100, 125000, 0, 0, 0, 100, 1, 1000, + },{19540113, 107, + 5000, 2500, 2500, 37500, 1, 100, 375000, 0, 0, 0, 100, 1, 1000, + },{19560313, 108, + 5000, 2500, 2500, 50000, 1, 100, 500000, 0, 0, 0, 100, 1, 1000, + },{2403509, 109, + 5000, 2500, 2500, 75000, 1, 100, 750000, 0, 0, 0, 100, 1, 1000, + },{92480414, 110, + 5000, 2500, 2500, 12500, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{4230140, 111, + 5000, 2500, 2500, 37500, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{10032490, 112, + 5000, 2500, 2500, 50000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{17307474, 113, + 5000, 2500, 2500, 75000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{4925114, 114, + 5000, 500, 4500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{19842704, 115, + 5000, 1500, 3500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{88392060, 116, + 5000, 2500, 2500, 25000, 1, 100, 250000, 0, 0, 0, 0, 1, 1000, + },{12904407, 117, + 5000, 2500, 2500, 12500, 1, 100, 125000, 0, 0, 0, 0, 1, 1000, + },{11811811, 118, + 5000, 2500, 2500, 37500, 1, 100, 375000, 0, 0, 0, 0, 1, 1000, + },{90023593, 119, + 5000, 2500, 2500, 50000, 1, 100, 500000, 0, 0, 0, 0, 1, 1000, + },{93028922, 120, + 5000, 2500, 2500, 75000, 1, 100, 750000, 0, 0, 0, 0, 1, 1000, + },{72707401, 121, + 5000, 50, 50, 25000, 1, 100, 250000, 50, 50, 0, 100, 1, 1000, + },{93040771, 122, + 5000, 250, 250, 25000, 1, 100, 250000, 250, 250, 0, 100, 1, 1000, + },{70220611, 123, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{52774811, 124, + 5000, 1000, 1000, 25000, 1, 100, 250000, 1000, 1000, 0, 100, 1, + 1000, + },{22492311, 125, + 5000, 1500, 1500, 25000, 1, 100, 250000, 1500, 1500, 0, 100, 1, + 1000, + },{35269337, 126, + 5000, 500, 500, 12500, 1, 100, 125000, 500, 500, 0, 100, 1, 1000, + },{30140502, 127, + 5000, 500, 500, 37500, 1, 100, 375000, 500, 500, 0, 100, 1, 1000, + },{49205455, 128, + 5000, 500, 500, 50000, 1, 100, 500000, 500, 500, 0, 100, 1, 1000, + },{42958341, 129, + 5000, 500, 500, 75000, 1, 100, 750000, 500, 500, 0, 100, 1, 1000, + },{25440925, 130, + 5000, 500, 500, 12500, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{75294924, 131, + 5000, 500, 500, 37500, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{4463965, 132, + 5000, 500, 500, 50000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{13390427, 133, + 5000, 500, 500, 75000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{95250971, 134, + 1000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{54830522, 135, + 2500, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{520593, 136, + 7500, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{52900925, 137, + 10000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{22603395, 138, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 50, + },{55253099, 139, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 250, + },{75357001, 140, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 500, + },{10072459, 141, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 2500, + },{55728492, 142, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 5000, + },{593043, 143, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 0, 1, 1000, + },{94236572, 144, + 5000, 500, 500, 25000, 1, 10, 250000, 500, 500, 0, 100, 1, 1000, + },{94882955, 145, + 5000, 500, 500, 25000, 1, 1000, 250000, 500, 500, 0, 100, 1, 1000, + },{48489922, 146, + 5000, 500, 500, 25000, 1, 10000, 250000, 500, 500, 0, 100, 1, + 1000, + },{75578374, 147, + 5000, 500, 500, 25000, -100, -1, 250000, 500, 500, 0, 100, 1, + 1000, + },{44821152, 148, + 5000, 500, 500, 25000, -50, 49, 250000, 500, 500, 0, 100, 1, 1000, + },{45224103, 149, + 5000, 500, 500, 25000, 101, 200, 250000, 500, 500, 0, 100, 1, + 1000, + },{63491741, 150, + 5000, 500, 500, 25000, 1001, 1100, 250000, 500, 500, 0, 100, 1, + 1000, + } +}; + +typedef struct { double rhs; } v_data; +typedef struct { double cap, cost; } a_data; + +int main(void) +{ glp_graph *G; + int k; + char fname[100+1]; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + for (k = 1; k <= 50; k++) + { sprintf(fname, "netgn%03d.min", parm[k-1][1]); + glp_netgen(G, offsetof(v_data, rhs), offsetof(a_data, cap), + offsetof(a_data, cost), &parm[k-1][-1]); + glp_write_mincost(G, offsetof(v_data, rhs), -1, + offsetof(a_data, cap), offsetof(a_data, cost), fname); + } + glp_delete_graph(G); + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/numbrix.mod b/resources/3rdparty/glpk-4.53/examples/numbrix.mod new file mode 100644 index 000000000..b36fbfd04 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/numbrix.mod @@ -0,0 +1,84 @@ +/* Numbrix, Number Placement Puzzle */ + +/* Written in GNU MathProg by Robert Wood <rwood@targus.com> */ + +/* Numbrix is a logic-based number-placement puzzle.[1] + * The objective is to fill the grid so that each cell contains + * digits in sequential order taking a horizontal or vertical + * path; diagonal paths are not allowed. The puzzle setter + * provides a grid often with the outer most cells completed. + * + * Completed Numbrix puzzles are usually a square of numbers + * in order from 1 to 64 (8x8 grid) or from 1 to 81 (9x9 grid), + * following a continuous path in sequence. + * + * The modern puzzle was invented by Marilyn vos Savant in 2008 + * and published by Parade Magazine under the name "Numbrix", + * near her weekly Ask Marilyn article. + * + * http://en.wikipedia.org/wiki/Numbrix */ + +set I := {1..9}; +set J := {1..9}; +set VALS := {1..81}; + +param givens{I, J}, integer, >= 0, <= 81, default 0; +/* the "givens" */ + +param neighbors{i in I,j in J, i2 in I, j2 in J} , binary := +(if abs(i - i2) + abs(j -j2) == 1 then + 1 + else + 0 +); +/* defines which spots are the boards are neighbors */ + +var x{i in I, j in J, k in VALS}, binary; +/* x[i,j,k] = 1 means cell [i,j] is assigned number k */ + +s.t. fa{i in I, j in J, k in VALS: givens[i,j] != 0}: + x[i,j,k] = (if givens[i,j] = k then 1 else 0); +/* assign pre-defined numbers using the "givens" */ + +s.t. fb{i in I, j in J}: sum{k in VALS} x[i,j,k] = 1; +/* each cell must be assigned exactly one number */ + +s.t. singleNum {k in VALS}: sum{i in I, j in J} x[i,j,k] = 1; +/* a value can only occur once */ + +s.t. neighborContraint {i in I, j in J, k in 1..80}: + x[i,j,k] <= sum{i2 in I, j2 in J} x[i2,j2,k+1] * neighbors[i,j,i2,j2]; +/* each cell must have a neighbor with the next higher value */ + + +/* there is no need for an objective function here */ + + +solve; + +for {i in I} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +----------+----------+----------+\n"; + for {j in J} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %2d", sum{k in VALS} x[i,j,k] * k; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +----------+----------+----------+\n"; +} + +data; + +param givens : 1 2 3 4 5 6 7 8 9 := + 1 . . . . . . . . . + 2 . 11 12 15 18 21 62 61 . + 3 . 6 . . . . . 60 . + 4 . 33 . . . . . 57 . + 5 . 32 . . . . . 56 . + 6 . 37 . . . . . 73 . + 7 . 38 . . . . . 72 . + 8 . 43 44 47 48 51 76 77 . + 9 . . . . . . . . . ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/oldapi/README b/resources/3rdparty/glpk-4.53/examples/oldapi/README new file mode 100644 index 000000000..e52ee2c09 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/oldapi/README @@ -0,0 +1,11 @@ +The program module in this subdirectory contains an implementation of +the old GLPK API as it was defined in GLPK 4.48. + +To compile an existing project using the old GLPK API you need to add +to the project two files lpx.h and lpx.c. + +Please note that you may mix calls to old and new GLPK API routines in +the same project (except calls to glp_create_prob and glp_delete_prob). + +The file lpxsamp.c is an example that illustrates using the old GLPK +API routines. diff --git a/resources/3rdparty/glpk-4.53/examples/oldapi/lpx.c b/resources/3rdparty/glpk-4.53/examples/oldapi/lpx.c new file mode 100644 index 000000000..c508306b0 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/oldapi/lpx.c @@ -0,0 +1,1505 @@ +/* lpx.c (old GLPK API) */ + +/* Written by Andrew Makhorin <mao@gnu.org>, August 2013. */ + +/* This file contains routines that implement the old GLPK API as it +* was defined in GLPK 4.48. +* +* To compile an existing project using these routines you need to add +* to the project this file and the header lpx.h. +* +* Please note that you may mix calls to old and new GLPK API routines +* (except calls to glp_create_prob and glp_delete_prob). */ + +#include <float.h> +#include <limits.h> +#include "lpx.h" + +#define xassert glp_assert +#define xerror glp_error + +struct CPS +{ /* control parameters */ + LPX *lp; + /* pointer to corresponding problem object */ + int msg_lev; + /* level of messages output by the solver: + 0 - no output + 1 - error messages only + 2 - normal output + 3 - full output (includes informational messages) */ + int scale; + /* scaling option: + 0 - no scaling + 1 - equilibration scaling + 2 - geometric mean scaling + 3 - geometric mean scaling, then equilibration scaling */ + int dual; + /* dual simplex option: + 0 - use primal simplex + 1 - use dual simplex */ + int price; + /* pricing option (for both primal and dual simplex): + 0 - textbook pricing + 1 - steepest edge pricing */ + double relax; + /* relaxation parameter used in the ratio test; if it is zero, + the textbook ratio test is used; if it is non-zero (should be + positive), Harris' two-pass ratio test is used; in the latter + case on the first pass basic variables (in the case of primal + simplex) or reduced costs of non-basic variables (in the case + of dual simplex) are allowed to slightly violate their bounds, + but not more than (relax * tol_bnd) or (relax * tol_dj) (thus, + relax is a percentage of tol_bnd or tol_dj) */ + double tol_bnd; + /* relative tolerance used to check if the current basic solution + is primal feasible */ + double tol_dj; + /* absolute tolerance used to check if the current basic solution + is dual feasible */ + double tol_piv; + /* relative tolerance used to choose eligible pivotal elements of + the simplex table in the ratio test */ + int round; + /* solution rounding option: + 0 - report all computed values and reduced costs "as is" + 1 - if possible (allowed by the tolerances), replace computed + values and reduced costs which are close to zero by exact + zeros */ + double obj_ll; + /* lower limit of the objective function; if on the phase II the + objective function reaches this limit and continues decreasing, + the solver stops the search */ + double obj_ul; + /* upper limit of the objective function; if on the phase II the + objective function reaches this limit and continues increasing, + the solver stops the search */ + int it_lim; + /* simplex iterations limit; if this value is positive, it is + decreased by one each time when one simplex iteration has been + performed, and reaching zero value signals the solver to stop + the search; negative value means no iterations limit */ + double tm_lim; + /* searching time limit, in seconds; if this value is positive, + it is decreased each time when one simplex iteration has been + performed by the amount of time spent for the iteration, and + reaching zero value signals the solver to stop the search; + negative value means no time limit */ + int out_frq; + /* output frequency, in iterations; this parameter specifies how + frequently the solver sends information about the solution to + the standard output */ + double out_dly; + /* output delay, in seconds; this parameter specifies how long + the solver should delay sending information about the solution + to the standard output; zero value means no delay */ + int branch; /* MIP */ + /* branching heuristic: + 0 - branch on first variable + 1 - branch on last variable + 2 - branch using heuristic by Driebeck and Tomlin + 3 - branch on most fractional variable */ + int btrack; /* MIP */ + /* backtracking heuristic: + 0 - select most recent node (depth first search) + 1 - select earliest node (breadth first search) + 2 - select node using the best projection heuristic + 3 - select node with best local bound */ + double tol_int; /* MIP */ + /* absolute tolerance used to check if the current basic solution + is integer feasible */ + double tol_obj; /* MIP */ + /* relative tolerance used to check if the value of the objective + function is not better than in the best known integer feasible + solution */ + int mps_info; /* lpx_write_mps */ + /* if this flag is set, the routine lpx_write_mps outputs several + comment cards that contains some information about the problem; + otherwise the routine outputs no comment cards */ + int mps_obj; /* lpx_write_mps */ + /* this parameter tells the routine lpx_write_mps how to output + the objective function row: + 0 - never output objective function row + 1 - always output objective function row + 2 - output objective function row if and only if the problem + has no free rows */ + int mps_orig; /* lpx_write_mps */ + /* if this flag is set, the routine lpx_write_mps uses original + row and column symbolic names; otherwise the routine generates + plain names using ordinal numbers of rows and columns */ + int mps_wide; /* lpx_write_mps */ + /* if this flag is set, the routine lpx_write_mps uses all data + fields; otherwise the routine keeps fields 5 and 6 empty */ + int mps_free; /* lpx_write_mps */ + /* if this flag is set, the routine lpx_write_mps omits column + and vector names everytime if possible (free style); otherwise + the routine never omits these names (pedantic style) */ + int mps_skip; /* lpx_write_mps */ + /* if this flag is set, the routine lpx_write_mps skips empty + columns (i.e. which has no constraint coefficients); otherwise + the routine outputs all columns */ + int lpt_orig; /* lpx_write_lpt */ + /* if this flag is set, the routine lpx_write_lpt uses original + row and column symbolic names; otherwise the routine generates + plain names using ordinal numbers of rows and columns */ + int presol; /* lpx_simplex */ + /* LP presolver option: + 0 - do not use LP presolver + 1 - use LP presolver */ + int binarize; /* lpx_intopt */ + /* if this flag is set, the routine lpx_intopt replaces integer + columns by binary ones */ + int use_cuts; /* lpx_intopt */ + /* if this flag is set, the routine lpx_intopt tries generating + cutting planes: + LPX_C_COVER - mixed cover cuts + LPX_C_CLIQUE - clique cuts + LPX_C_GOMORY - Gomory's mixed integer cuts + LPX_C_ALL - all cuts */ + double mip_gap; /* MIP */ + /* relative MIP gap tolerance */ + struct CPS *link; + /* pointer to CPS for another problem object */ +}; + +static struct CPS *cps_ptr = NULL; +/* initial pointer to CPS linked list */ + +static struct CPS *find_cps(LPX *lp) +{ /* find CPS for specified problem object */ + struct CPS *cps; + for (cps = cps_ptr; cps != NULL; cps = cps->link) + if (cps->lp == lp) break; + /* if cps is NULL (not found), the problem object was created + with glp_create_prob rather than with lpx_create_prob */ + xassert(cps != NULL); + return cps; +} + +static void reset_cps(struct CPS *cps) +{ /* reset control parameters to default values */ + cps->msg_lev = 3; + cps->scale = 1; + cps->dual = 0; + cps->price = 1; + cps->relax = 0.07; + cps->tol_bnd = 1e-7; + cps->tol_dj = 1e-7; + cps->tol_piv = 1e-9; + cps->round = 0; + cps->obj_ll = -DBL_MAX; + cps->obj_ul = +DBL_MAX; + cps->it_lim = -1; + cps->tm_lim = -1.0; + cps->out_frq = 200; + cps->out_dly = 0.0; + cps->branch = 2; + cps->btrack = 3; + cps->tol_int = 1e-5; + cps->tol_obj = 1e-7; + cps->mps_info = 1; + cps->mps_obj = 2; + cps->mps_orig = 0; + cps->mps_wide = 1; + cps->mps_free = 0; + cps->mps_skip = 0; + cps->lpt_orig = 0; + cps->presol = 0; + cps->binarize = 0; + cps->use_cuts = 0; + cps->mip_gap = 0.0; + return; +} + +LPX *lpx_create_prob(void) +{ /* create problem object */ + LPX *lp; + struct CPS *cps; + lp = glp_create_prob(); + cps = glp_alloc(1, sizeof(struct CPS)); + cps->lp = lp; + reset_cps(cps); + cps->link = cps_ptr; + cps_ptr = cps; + return lp; +} + +void lpx_set_prob_name(LPX *lp, const char *name) +{ /* assign (change) problem name */ + glp_set_prob_name(lp, name); + return; +} + +void lpx_set_obj_name(LPX *lp, const char *name) +{ /* assign (change) objective function name */ + glp_set_obj_name(lp, name); + return; +} + +void lpx_set_obj_dir(LPX *lp, int dir) +{ /* set (change) optimization direction flag */ + glp_set_obj_dir(lp, dir - LPX_MIN + GLP_MIN); + return; +} + +int lpx_add_rows(LPX *lp, int nrs) +{ /* add new rows to problem object */ + return glp_add_rows(lp, nrs); +} + +int lpx_add_cols(LPX *lp, int ncs) +{ /* add new columns to problem object */ + return glp_add_cols(lp, ncs); +} + +void lpx_set_row_name(LPX *lp, int i, const char *name) +{ /* assign (change) row name */ + glp_set_row_name(lp, i, name); + return; +} + +void lpx_set_col_name(LPX *lp, int j, const char *name) +{ /* assign (change) column name */ + glp_set_col_name(lp, j, name); + return; +} + +void lpx_set_row_bnds(LPX *lp, int i, int type, double lb, double ub) +{ /* set (change) row bounds */ + glp_set_row_bnds(lp, i, type - LPX_FR + GLP_FR, lb, ub); + return; +} + +void lpx_set_col_bnds(LPX *lp, int j, int type, double lb, double ub) +{ /* set (change) column bounds */ + glp_set_col_bnds(lp, j, type - LPX_FR + GLP_FR, lb, ub); + return; +} + +void lpx_set_obj_coef(glp_prob *lp, int j, double coef) +{ /* set (change) obj. coefficient or constant term */ + glp_set_obj_coef(lp, j, coef); + return; +} + +void lpx_set_mat_row(LPX *lp, int i, int len, const int ind[], + const double val[]) +{ /* set (replace) row of the constraint matrix */ + glp_set_mat_row(lp, i, len, ind, val); + return; +} + +void lpx_set_mat_col(LPX *lp, int j, int len, const int ind[], + const double val[]) +{ /* set (replace) column of the constraint matrix */ + glp_set_mat_col(lp, j, len, ind, val); + return; +} + +void lpx_load_matrix(LPX *lp, int ne, const int ia[], const int ja[], + const double ar[]) +{ /* load (replace) the whole constraint matrix */ + glp_load_matrix(lp, ne, ia, ja, ar); + return; +} + +void lpx_del_rows(LPX *lp, int nrs, const int num[]) +{ /* delete specified rows from problem object */ + glp_del_rows(lp, nrs, num); + return; +} + +void lpx_del_cols(LPX *lp, int ncs, const int num[]) +{ /* delete specified columns from problem object */ + glp_del_cols(lp, ncs, num); + return; +} + +void lpx_delete_prob(LPX *lp) +{ /* delete problem object */ + struct CPS *cps = find_cps(lp); + if (cps_ptr == cps) + cps_ptr = cps->link; + else + { struct CPS *prev; + for (prev = cps_ptr; prev != NULL; prev = prev->link) + if (prev->link == cps) break; + xassert(prev != NULL); + prev->link = cps->link; + } + glp_free(cps); + glp_delete_prob(lp); + return; +} + +const char *lpx_get_prob_name(LPX *lp) +{ /* retrieve problem name */ + return glp_get_prob_name(lp); +} + +const char *lpx_get_obj_name(LPX *lp) +{ /* retrieve objective function name */ + return glp_get_obj_name(lp); +} + +int lpx_get_obj_dir(LPX *lp) +{ /* retrieve optimization direction flag */ + return glp_get_obj_dir(lp) - GLP_MIN + LPX_MIN; +} + +int lpx_get_num_rows(LPX *lp) +{ /* retrieve number of rows */ + return glp_get_num_rows(lp); +} + +int lpx_get_num_cols(LPX *lp) +{ /* retrieve number of columns */ + return glp_get_num_cols(lp); +} + +const char *lpx_get_row_name(LPX *lp, int i) +{ /* retrieve row name */ + return glp_get_row_name(lp, i); +} + +const char *lpx_get_col_name(LPX *lp, int j) +{ /* retrieve column name */ + return glp_get_col_name(lp, j); +} + +int lpx_get_row_type(LPX *lp, int i) +{ /* retrieve row type */ + return glp_get_row_type(lp, i) - GLP_FR + LPX_FR; +} + +double lpx_get_row_lb(glp_prob *lp, int i) +{ /* retrieve row lower bound */ + double lb; + lb = glp_get_row_lb(lp, i); + if (lb == -DBL_MAX) lb = 0.0; + return lb; +} + +double lpx_get_row_ub(glp_prob *lp, int i) +{ /* retrieve row upper bound */ + double ub; + ub = glp_get_row_ub(lp, i); + if (ub == +DBL_MAX) ub = 0.0; + return ub; +} + +void lpx_get_row_bnds(glp_prob *lp, int i, int *typx, double *lb, + double *ub) +{ /* retrieve row bounds */ + if (typx != NULL) *typx = lpx_get_row_type(lp, i); + if (lb != NULL) *lb = lpx_get_row_lb(lp, i); + if (ub != NULL) *ub = lpx_get_row_ub(lp, i); + return; +} + +int lpx_get_col_type(LPX *lp, int j) +{ /* retrieve column type */ + return glp_get_col_type(lp, j) - GLP_FR + LPX_FR; +} + +double lpx_get_col_lb(glp_prob *lp, int j) +{ /* retrieve column lower bound */ + double lb; + lb = glp_get_col_lb(lp, j); + if (lb == -DBL_MAX) lb = 0.0; + return lb; +} + +double lpx_get_col_ub(glp_prob *lp, int j) +{ /* retrieve column upper bound */ + double ub; + ub = glp_get_col_ub(lp, j); + if (ub == +DBL_MAX) ub = 0.0; + return ub; +} + +void lpx_get_col_bnds(glp_prob *lp, int j, int *typx, double *lb, + double *ub) +{ /* retrieve column bounds */ + if (typx != NULL) *typx = lpx_get_col_type(lp, j); + if (lb != NULL) *lb = lpx_get_col_lb(lp, j); + if (ub != NULL) *ub = lpx_get_col_ub(lp, j); + return; +} + +double lpx_get_obj_coef(LPX *lp, int j) +{ /* retrieve obj. coefficient or constant term */ + return glp_get_obj_coef(lp, j); +} + +int lpx_get_num_nz(LPX *lp) +{ /* retrieve number of constraint coefficients */ + return glp_get_num_nz(lp); +} + +int lpx_get_mat_row(LPX *lp, int i, int ind[], double val[]) +{ /* retrieve row of the constraint matrix */ + return glp_get_mat_row(lp, i, ind, val); +} + +int lpx_get_mat_col(LPX *lp, int j, int ind[], double val[]) +{ /* retrieve column of the constraint matrix */ + return glp_get_mat_col(lp, j, ind, val); +} + +void lpx_create_index(LPX *lp) +{ /* create the name index */ + glp_create_index(lp); + return; +} + +int lpx_find_row(LPX *lp, const char *name) +{ /* find row by its name */ + return glp_find_row(lp, name); +} + +int lpx_find_col(LPX *lp, const char *name) +{ /* find column by its name */ + return glp_find_col(lp, name); +} + +void lpx_delete_index(LPX *lp) +{ /* delete the name index */ + glp_delete_index(lp); + return; +} + +void lpx_scale_prob(LPX *lp) +{ /* scale problem data */ + switch (lpx_get_int_parm(lp, LPX_K_SCALE)) + { case 0: + /* no scaling */ + glp_unscale_prob(lp); + break; + case 1: + /* equilibration scaling */ + glp_scale_prob(lp, GLP_SF_EQ); + break; + case 2: + /* geometric mean scaling */ + glp_scale_prob(lp, GLP_SF_GM); + break; + case 3: + /* geometric mean scaling, then equilibration scaling */ + glp_scale_prob(lp, GLP_SF_GM | GLP_SF_EQ); + break; + default: + xassert(lp != lp); + } + return; +} + +void lpx_unscale_prob(LPX *lp) +{ /* unscale problem data */ + glp_unscale_prob(lp); + return; +} + +void lpx_set_row_stat(LPX *lp, int i, int stat) +{ /* set (change) row status */ + glp_set_row_stat(lp, i, stat - LPX_BS + GLP_BS); + return; +} + +void lpx_set_col_stat(LPX *lp, int j, int stat) +{ /* set (change) column status */ + glp_set_col_stat(lp, j, stat - LPX_BS + GLP_BS); + return; +} + +void lpx_std_basis(LPX *lp) +{ /* construct standard initial LP basis */ + glp_std_basis(lp); + return; +} + +void lpx_adv_basis(LPX *lp) +{ /* construct advanced initial LP basis */ + glp_adv_basis(lp, 0); + return; +} + +void lpx_cpx_basis(LPX *lp) +{ /* construct Bixby's initial LP basis */ + glp_cpx_basis(lp); + return; +} + +static void fill_smcp(LPX *lp, glp_smcp *parm) +{ glp_init_smcp(parm); + switch (lpx_get_int_parm(lp, LPX_K_MSGLEV)) + { case 0: parm->msg_lev = GLP_MSG_OFF; break; + case 1: parm->msg_lev = GLP_MSG_ERR; break; + case 2: parm->msg_lev = GLP_MSG_ON; break; + case 3: parm->msg_lev = GLP_MSG_ALL; break; + default: xassert(lp != lp); + } + switch (lpx_get_int_parm(lp, LPX_K_DUAL)) + { case 0: parm->meth = GLP_PRIMAL; break; + case 1: parm->meth = GLP_DUAL; break; + default: xassert(lp != lp); + } + switch (lpx_get_int_parm(lp, LPX_K_PRICE)) + { case 0: parm->pricing = GLP_PT_STD; break; + case 1: parm->pricing = GLP_PT_PSE; break; + default: xassert(lp != lp); + } + if (lpx_get_real_parm(lp, LPX_K_RELAX) == 0.0) + parm->r_test = GLP_RT_STD; + else + parm->r_test = GLP_RT_HAR; + parm->tol_bnd = lpx_get_real_parm(lp, LPX_K_TOLBND); + parm->tol_dj = lpx_get_real_parm(lp, LPX_K_TOLDJ); + parm->tol_piv = lpx_get_real_parm(lp, LPX_K_TOLPIV); + parm->obj_ll = lpx_get_real_parm(lp, LPX_K_OBJLL); + parm->obj_ul = lpx_get_real_parm(lp, LPX_K_OBJUL); + if (lpx_get_int_parm(lp, LPX_K_ITLIM) < 0) + parm->it_lim = INT_MAX; + else + parm->it_lim = lpx_get_int_parm(lp, LPX_K_ITLIM); + if (lpx_get_real_parm(lp, LPX_K_TMLIM) < 0.0) + parm->tm_lim = INT_MAX; + else + parm->tm_lim = + (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_TMLIM)); + parm->out_frq = lpx_get_int_parm(lp, LPX_K_OUTFRQ); + parm->out_dly = + (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_OUTDLY)); + switch (lpx_get_int_parm(lp, LPX_K_PRESOL)) + { case 0: parm->presolve = GLP_OFF; break; + case 1: parm->presolve = GLP_ON; break; + default: xassert(lp != lp); + } + return; +} + +int lpx_simplex(LPX *lp) +{ /* easy-to-use driver to the simplex method */ + glp_smcp parm; + int ret; + fill_smcp(lp, &parm); + ret = glp_simplex(lp, &parm); + switch (ret) + { case 0: ret = LPX_E_OK; break; + case GLP_EBADB: + case GLP_ESING: + case GLP_ECOND: + case GLP_EBOUND: ret = LPX_E_FAULT; break; + case GLP_EFAIL: ret = LPX_E_SING; break; + case GLP_EOBJLL: ret = LPX_E_OBJLL; break; + case GLP_EOBJUL: ret = LPX_E_OBJUL; break; + case GLP_EITLIM: ret = LPX_E_ITLIM; break; + case GLP_ETMLIM: ret = LPX_E_TMLIM; break; + case GLP_ENOPFS: ret = LPX_E_NOPFS; break; + case GLP_ENODFS: ret = LPX_E_NODFS; break; + default: xassert(ret != ret); + } + return ret; +} + +int lpx_exact(LPX *lp) +{ /* easy-to-use driver to the exact simplex method */ + glp_smcp parm; + int ret; + fill_smcp(lp, &parm); + ret = glp_exact(lp, &parm); + switch (ret) + { case 0: ret = LPX_E_OK; break; + case GLP_EBADB: + case GLP_ESING: + case GLP_EBOUND: + case GLP_EFAIL: ret = LPX_E_FAULT; break; + case GLP_EITLIM: ret = LPX_E_ITLIM; break; + case GLP_ETMLIM: ret = LPX_E_TMLIM; break; + default: xassert(ret != ret); + } + return ret; +} + +int lpx_get_status(glp_prob *lp) +{ /* retrieve generic status of basic solution */ + int status; + switch (glp_get_status(lp)) + { case GLP_OPT: status = LPX_OPT; break; + case GLP_FEAS: status = LPX_FEAS; break; + case GLP_INFEAS: status = LPX_INFEAS; break; + case GLP_NOFEAS: status = LPX_NOFEAS; break; + case GLP_UNBND: status = LPX_UNBND; break; + case GLP_UNDEF: status = LPX_UNDEF; break; + default: xassert(lp != lp); + } + return status; +} + +int lpx_get_prim_stat(glp_prob *lp) +{ /* retrieve status of primal basic solution */ + return glp_get_prim_stat(lp) - GLP_UNDEF + LPX_P_UNDEF; +} + +int lpx_get_dual_stat(glp_prob *lp) +{ /* retrieve status of dual basic solution */ + return glp_get_dual_stat(lp) - GLP_UNDEF + LPX_D_UNDEF; +} + +double lpx_get_obj_val(LPX *lp) +{ /* retrieve objective value (basic solution) */ + return glp_get_obj_val(lp); +} + +int lpx_get_row_stat(LPX *lp, int i) +{ /* retrieve row status (basic solution) */ + return glp_get_row_stat(lp, i) - GLP_BS + LPX_BS; +} + +double lpx_get_row_prim(LPX *lp, int i) +{ /* retrieve row primal value (basic solution) */ + return glp_get_row_prim(lp, i); +} + +double lpx_get_row_dual(LPX *lp, int i) +{ /* retrieve row dual value (basic solution) */ + return glp_get_row_dual(lp, i); +} + +void lpx_get_row_info(glp_prob *lp, int i, int *tagx, double *vx, + double *dx) +{ /* obtain row solution information */ + if (tagx != NULL) *tagx = lpx_get_row_stat(lp, i); + if (vx != NULL) *vx = lpx_get_row_prim(lp, i); + if (dx != NULL) *dx = lpx_get_row_dual(lp, i); + return; +} + +int lpx_get_col_stat(LPX *lp, int j) +{ /* retrieve column status (basic solution) */ + return glp_get_col_stat(lp, j) - GLP_BS + LPX_BS; +} + +double lpx_get_col_prim(LPX *lp, int j) +{ /* retrieve column primal value (basic solution) */ + return glp_get_col_prim(lp, j); +} + +double lpx_get_col_dual(glp_prob *lp, int j) +{ /* retrieve column dual value (basic solution) */ + return glp_get_col_dual(lp, j); +} + +void lpx_get_col_info(glp_prob *lp, int j, int *tagx, double *vx, + double *dx) +{ /* obtain column solution information */ + if (tagx != NULL) *tagx = lpx_get_col_stat(lp, j); + if (vx != NULL) *vx = lpx_get_col_prim(lp, j); + if (dx != NULL) *dx = lpx_get_col_dual(lp, j); + return; +} + +int lpx_get_ray_info(LPX *lp) +{ /* determine what causes primal unboundness */ + return glp_get_unbnd_ray(lp); +} + +void lpx_check_kkt(LPX *lp, int scaled, LPXKKT *kkt) +{ /* check Karush-Kuhn-Tucker conditions */ + int m = glp_get_num_rows(lp); + int ae_ind, re_ind; + double ae_max, re_max; + xassert(scaled == scaled); + glp_check_kkt(lp, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->pe_ae_max = ae_max; + kkt->pe_ae_row = ae_ind; + kkt->pe_re_max = re_max; + kkt->pe_re_row = re_ind; + if (re_max <= 1e-9) + kkt->pe_quality = 'H'; + else if (re_max <= 1e-6) + kkt->pe_quality = 'M'; + else if (re_max <= 1e-3) + kkt->pe_quality = 'L'; + else + kkt->pe_quality = '?'; + glp_check_kkt(lp, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->pb_ae_max = ae_max; + kkt->pb_ae_ind = ae_ind; + kkt->pb_re_max = re_max; + kkt->pb_re_ind = re_ind; + if (re_max <= 1e-9) + kkt->pb_quality = 'H'; + else if (re_max <= 1e-6) + kkt->pb_quality = 'M'; + else if (re_max <= 1e-3) + kkt->pb_quality = 'L'; + else + kkt->pb_quality = '?'; + glp_check_kkt(lp, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->de_ae_max = ae_max; + if (ae_ind == 0) + kkt->de_ae_col = 0; + else + kkt->de_ae_col = ae_ind - m; + kkt->de_re_max = re_max; + if (re_ind == 0) + kkt->de_re_col = 0; + else + kkt->de_re_col = ae_ind - m; + if (re_max <= 1e-9) + kkt->de_quality = 'H'; + else if (re_max <= 1e-6) + kkt->de_quality = 'M'; + else if (re_max <= 1e-3) + kkt->de_quality = 'L'; + else + kkt->de_quality = '?'; + glp_check_kkt(lp, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->db_ae_max = ae_max; + kkt->db_ae_ind = ae_ind; + kkt->db_re_max = re_max; + kkt->db_re_ind = re_ind; + if (re_max <= 1e-9) + kkt->db_quality = 'H'; + else if (re_max <= 1e-6) + kkt->db_quality = 'M'; + else if (re_max <= 1e-3) + kkt->db_quality = 'L'; + else + kkt->db_quality = '?'; + kkt->cs_ae_max = 0.0, kkt->cs_ae_ind = 0; + kkt->cs_re_max = 0.0, kkt->cs_re_ind = 0; + kkt->cs_quality = 'H'; + return; +} + +int lpx_warm_up(LPX *lp) +{ /* "warm up" LP basis */ + int ret; + ret = glp_warm_up(lp); + if (ret == 0) + ret = LPX_E_OK; + else if (ret == GLP_EBADB) + ret = LPX_E_BADB; + else if (ret == GLP_ESING) + ret = LPX_E_SING; + else if (ret == GLP_ECOND) + ret = LPX_E_SING; + else + xassert(ret != ret); + return ret; +} + +int lpx_eval_tab_row(LPX *lp, int k, int ind[], double val[]) +{ /* compute row of the simplex tableau */ + return glp_eval_tab_row(lp, k, ind, val); +} + +int lpx_eval_tab_col(LPX *lp, int k, int ind[], double val[]) +{ /* compute column of the simplex tableau */ + return glp_eval_tab_col(lp, k, ind, val); +} + +int lpx_transform_row(LPX *lp, int len, int ind[], double val[]) +{ /* transform explicitly specified row */ + return glp_transform_row(lp, len, ind, val); +} + +int lpx_transform_col(LPX *lp, int len, int ind[], double val[]) +{ /* transform explicitly specified column */ + return glp_transform_col(lp, len, ind, val); +} + +int lpx_prim_ratio_test(LPX *lp, int len, const int ind[], + const double val[], int how, double tol) +{ /* perform primal ratio test */ + int piv; + piv = glp_prim_rtest(lp, len, ind, val, how, tol); + xassert(0 <= piv && piv <= len); + return piv == 0 ? 0 : ind[piv]; +} + +int lpx_dual_ratio_test(LPX *lp, int len, const int ind[], + const double val[], int how, double tol) +{ /* perform dual ratio test */ + int piv; + piv = glp_dual_rtest(lp, len, ind, val, how, tol); + xassert(0 <= piv && piv <= len); + return piv == 0 ? 0 : ind[piv]; +} + +int lpx_interior(LPX *lp) +{ /* easy-to-use driver to the interior-point method */ + int ret; + ret = glp_interior(lp, NULL); + switch (ret) + { case 0: ret = LPX_E_OK; break; + case GLP_EFAIL: ret = LPX_E_FAULT; break; + case GLP_ENOFEAS: ret = LPX_E_NOFEAS; break; + case GLP_ENOCVG: ret = LPX_E_NOCONV; break; + case GLP_EITLIM: ret = LPX_E_ITLIM; break; + case GLP_EINSTAB: ret = LPX_E_INSTAB; break; + default: xassert(ret != ret); + } + return ret; +} + +int lpx_ipt_status(glp_prob *lp) +{ /* retrieve status of interior-point solution */ + int status; + switch (glp_ipt_status(lp)) + { case GLP_UNDEF: status = LPX_T_UNDEF; break; + case GLP_OPT: status = LPX_T_OPT; break; + default: xassert(lp != lp); + } + return status; +} + +double lpx_ipt_obj_val(LPX *lp) +{ /* retrieve objective value (interior point) */ + return glp_ipt_obj_val(lp); +} + +double lpx_ipt_row_prim(LPX *lp, int i) +{ /* retrieve row primal value (interior point) */ + return glp_ipt_row_prim(lp, i); +} + +double lpx_ipt_row_dual(LPX *lp, int i) +{ /* retrieve row dual value (interior point) */ + return glp_ipt_row_dual(lp, i); +} + +double lpx_ipt_col_prim(LPX *lp, int j) +{ /* retrieve column primal value (interior point) */ + return glp_ipt_col_prim(lp, j); +} + +double lpx_ipt_col_dual(LPX *lp, int j) +{ /* retrieve column dual value (interior point) */ + return glp_ipt_col_dual(lp, j); +} + +void lpx_set_class(LPX *lp, int klass) +{ /* set problem class */ + xassert(lp == lp); + if (!(klass == LPX_LP || klass == LPX_MIP)) + xerror("lpx_set_class: invalid problem class\n"); + return; +} + +int lpx_get_class(LPX *lp) +{ /* determine problem klass */ + return glp_get_num_int(lp) == 0 ? LPX_LP : LPX_MIP; +} + +void lpx_set_col_kind(LPX *lp, int j, int kind) +{ /* set (change) column kind */ + glp_set_col_kind(lp, j, kind - LPX_CV + GLP_CV); + return; +} + +int lpx_get_col_kind(LPX *lp, int j) +{ /* retrieve column kind */ + return glp_get_col_kind(lp, j) == GLP_CV ? LPX_CV : LPX_IV; +} + +int lpx_get_num_int(LPX *lp) +{ /* retrieve number of integer columns */ + return glp_get_num_int(lp); +} + +int lpx_get_num_bin(LPX *lp) +{ /* retrieve number of binary columns */ + return glp_get_num_bin(lp); +} + +static int solve_mip(LPX *lp, int presolve) +{ glp_iocp parm; + int ret; + glp_init_iocp(&parm); + switch (lpx_get_int_parm(lp, LPX_K_MSGLEV)) + { case 0: parm.msg_lev = GLP_MSG_OFF; break; + case 1: parm.msg_lev = GLP_MSG_ERR; break; + case 2: parm.msg_lev = GLP_MSG_ON; break; + case 3: parm.msg_lev = GLP_MSG_ALL; break; + default: xassert(lp != lp); + } + switch (lpx_get_int_parm(lp, LPX_K_BRANCH)) + { case 0: parm.br_tech = GLP_BR_FFV; break; + case 1: parm.br_tech = GLP_BR_LFV; break; + case 2: parm.br_tech = GLP_BR_DTH; break; + case 3: parm.br_tech = GLP_BR_MFV; break; + default: xassert(lp != lp); + } + switch (lpx_get_int_parm(lp, LPX_K_BTRACK)) + { case 0: parm.bt_tech = GLP_BT_DFS; break; + case 1: parm.bt_tech = GLP_BT_BFS; break; + case 2: parm.bt_tech = GLP_BT_BPH; break; + case 3: parm.bt_tech = GLP_BT_BLB; break; + default: xassert(lp != lp); + } + parm.tol_int = lpx_get_real_parm(lp, LPX_K_TOLINT); + parm.tol_obj = lpx_get_real_parm(lp, LPX_K_TOLOBJ); + if (lpx_get_real_parm(lp, LPX_K_TMLIM) < 0.0 || + lpx_get_real_parm(lp, LPX_K_TMLIM) > 1e6) + parm.tm_lim = INT_MAX; + else + parm.tm_lim = + (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_TMLIM)); + parm.mip_gap = lpx_get_real_parm(lp, LPX_K_MIPGAP); + if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_GOMORY) + parm.gmi_cuts = GLP_ON; + else + parm.gmi_cuts = GLP_OFF; + if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_MIR) + parm.mir_cuts = GLP_ON; + else + parm.mir_cuts = GLP_OFF; + if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_COVER) + parm.cov_cuts = GLP_ON; + else + parm.cov_cuts = GLP_OFF; + if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_CLIQUE) + parm.clq_cuts = GLP_ON; + else + parm.clq_cuts = GLP_OFF; + parm.presolve = presolve; + if (lpx_get_int_parm(lp, LPX_K_BINARIZE)) + parm.binarize = GLP_ON; + ret = glp_intopt(lp, &parm); + switch (ret) + { case 0: ret = LPX_E_OK; break; + case GLP_ENOPFS: ret = LPX_E_NOPFS; break; + case GLP_ENODFS: ret = LPX_E_NODFS; break; + case GLP_EBOUND: + case GLP_EROOT: ret = LPX_E_FAULT; break; + case GLP_EFAIL: ret = LPX_E_SING; break; + case GLP_EMIPGAP: ret = LPX_E_MIPGAP; break; + case GLP_ETMLIM: ret = LPX_E_TMLIM; break; + default: xassert(ret != ret); + } + return ret; +} + +int lpx_integer(LPX *lp) +{ /* easy-to-use driver to the branch-and-bound method */ + return solve_mip(lp, GLP_OFF); +} + +int lpx_intopt(LPX *lp) +{ /* easy-to-use driver to the branch-and-bound method */ + return solve_mip(lp, GLP_ON); +} + +int lpx_mip_status(glp_prob *lp) +{ /* retrieve status of MIP solution */ + int status; + switch (glp_mip_status(lp)) + { case GLP_UNDEF: status = LPX_I_UNDEF; break; + case GLP_OPT: status = LPX_I_OPT; break; + case GLP_FEAS: status = LPX_I_FEAS; break; + case GLP_NOFEAS: status = LPX_I_NOFEAS; break; + default: xassert(lp != lp); + } + return status; +} + +double lpx_mip_obj_val(LPX *lp) +{ /* retrieve objective value (MIP solution) */ + return glp_mip_obj_val(lp); +} + +double lpx_mip_row_val(LPX *lp, int i) +{ /* retrieve row value (MIP solution) */ + return glp_mip_row_val(lp, i); +} + +double lpx_mip_col_val(LPX *lp, int j) +{ /* retrieve column value (MIP solution) */ + return glp_mip_col_val(lp, j); +} + +void lpx_check_int(LPX *lp, LPXKKT *kkt) +{ /* check integer feasibility conditions */ + int ae_ind, re_ind; + double ae_max, re_max; + glp_check_kkt(lp, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->pe_ae_max = ae_max; + kkt->pe_ae_row = ae_ind; + kkt->pe_re_max = re_max; + kkt->pe_re_row = re_ind; + if (re_max <= 1e-9) + kkt->pe_quality = 'H'; + else if (re_max <= 1e-6) + kkt->pe_quality = 'M'; + else if (re_max <= 1e-3) + kkt->pe_quality = 'L'; + else + kkt->pe_quality = '?'; + glp_check_kkt(lp, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->pb_ae_max = ae_max; + kkt->pb_ae_ind = ae_ind; + kkt->pb_re_max = re_max; + kkt->pb_re_ind = re_ind; + if (re_max <= 1e-9) + kkt->pb_quality = 'H'; + else if (re_max <= 1e-6) + kkt->pb_quality = 'M'; + else if (re_max <= 1e-3) + kkt->pb_quality = 'L'; + else + kkt->pb_quality = '?'; + return; +} + +void lpx_reset_parms(LPX *lp) +{ /* reset control parameters to default values */ + struct CPS *cps = find_cps(lp); + reset_cps(cps); + return; +} + +void lpx_set_int_parm(LPX *lp, int parm, int val) +{ /* set (change) integer control parameter */ + struct CPS *cps = find_cps(lp); + switch (parm) + { case LPX_K_MSGLEV: + if (!(0 <= val && val <= 3)) + xerror("lpx_set_int_parm: MSGLEV = %d; invalid value\n", + val); + cps->msg_lev = val; + break; + case LPX_K_SCALE: + if (!(0 <= val && val <= 3)) + xerror("lpx_set_int_parm: SCALE = %d; invalid value\n", + val); + cps->scale = val; + break; + case LPX_K_DUAL: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: DUAL = %d; invalid value\n", + val); + cps->dual = val; + break; + case LPX_K_PRICE: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: PRICE = %d; invalid value\n", + val); + cps->price = val; + break; + case LPX_K_ROUND: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: ROUND = %d; invalid value\n", + val); + cps->round = val; + break; + case LPX_K_ITLIM: + cps->it_lim = val; + break; + case LPX_K_ITCNT: + glp_set_it_cnt(lp, val); + break; + case LPX_K_OUTFRQ: + if (!(val > 0)) + xerror("lpx_set_int_parm: OUTFRQ = %d; invalid value\n", + val); + cps->out_frq = val; + break; + case LPX_K_BRANCH: + if (!(val == 0 || val == 1 || val == 2 || val == 3)) + xerror("lpx_set_int_parm: BRANCH = %d; invalid value\n", + val); + cps->branch = val; + break; + case LPX_K_BTRACK: + if (!(val == 0 || val == 1 || val == 2 || val == 3)) + xerror("lpx_set_int_parm: BTRACK = %d; invalid value\n", + val); + cps->btrack = val; + break; + case LPX_K_MPSINFO: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: MPSINFO = %d; invalid value\n", + val); + cps->mps_info = val; + break; + case LPX_K_MPSOBJ: + if (!(val == 0 || val == 1 || val == 2)) + xerror("lpx_set_int_parm: MPSOBJ = %d; invalid value\n", + val); + cps->mps_obj = val; + break; + case LPX_K_MPSORIG: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: MPSORIG = %d; invalid value\n", + val); + cps->mps_orig = val; + break; + case LPX_K_MPSWIDE: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: MPSWIDE = %d; invalid value\n", + val); + cps->mps_wide = val; + break; + case LPX_K_MPSFREE: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: MPSFREE = %d; invalid value\n", + val); + cps->mps_free = val; + break; + case LPX_K_MPSSKIP: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: MPSSKIP = %d; invalid value\n", + val); + cps->mps_skip = val; + break; + case LPX_K_LPTORIG: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: LPTORIG = %d; invalid value\n", + val); + cps->lpt_orig = val; + break; + case LPX_K_PRESOL: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: PRESOL = %d; invalid value\n", + val); + cps->presol = val; + break; + case LPX_K_BINARIZE: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: BINARIZE = %d; invalid value\n" + , val); + cps->binarize = val; + break; + case LPX_K_USECUTS: + if (val & ~LPX_C_ALL) + xerror("lpx_set_int_parm: USECUTS = 0x%X; invalid value\n", + val); + cps->use_cuts = val; + break; + case LPX_K_BFTYPE: + { glp_bfcp parm; + glp_get_bfcp(lp, &parm); + switch (val) + { case 1: + parm.type = GLP_BF_FT; break; + case 2: + parm.type = GLP_BF_BG; break; + case 3: + parm.type = GLP_BF_GR; break; + default: + xerror("lpx_set_int_parm: BFTYPE = %d; invalid val" + "ue\n", val); + } + glp_set_bfcp(lp, &parm); + } + break; + default: + xerror("lpx_set_int_parm: parm = %d; invalid parameter\n", + parm); + } + return; +} + +int lpx_get_int_parm(LPX *lp, int parm) +{ /* query integer control parameter */ + struct CPS *cps = find_cps(lp); + int val = 0; + switch (parm) + { case LPX_K_MSGLEV: + val = cps->msg_lev; break; + case LPX_K_SCALE: + val = cps->scale; break; + case LPX_K_DUAL: + val = cps->dual; break; + case LPX_K_PRICE: + val = cps->price; break; + case LPX_K_ROUND: + val = cps->round; break; + case LPX_K_ITLIM: + val = cps->it_lim; break; + case LPX_K_ITCNT: + val = glp_get_it_cnt(lp); break; + case LPX_K_OUTFRQ: + val = cps->out_frq; break; + case LPX_K_BRANCH: + val = cps->branch; break; + case LPX_K_BTRACK: + val = cps->btrack; break; + case LPX_K_MPSINFO: + val = cps->mps_info; break; + case LPX_K_MPSOBJ: + val = cps->mps_obj; break; + case LPX_K_MPSORIG: + val = cps->mps_orig; break; + case LPX_K_MPSWIDE: + val = cps->mps_wide; break; + case LPX_K_MPSFREE: + val = cps->mps_free; break; + case LPX_K_MPSSKIP: + val = cps->mps_skip; break; + case LPX_K_LPTORIG: + val = cps->lpt_orig; break; + case LPX_K_PRESOL: + val = cps->presol; break; + case LPX_K_BINARIZE: + val = cps->binarize; break; + case LPX_K_USECUTS: + val = cps->use_cuts; break; + case LPX_K_BFTYPE: + { glp_bfcp parm; + glp_get_bfcp(lp, &parm); + switch (parm.type) + { case GLP_BF_FT: + val = 1; break; + case GLP_BF_BG: + val = 2; break; + case GLP_BF_GR: + val = 3; break; + default: + xassert(lp != lp); + } + } + break; + default: + xerror("lpx_get_int_parm: parm = %d; invalid parameter\n", + parm); + } + return val; +} + +void lpx_set_real_parm(LPX *lp, int parm, double val) +{ /* set (change) real control parameter */ + struct CPS *cps = find_cps(lp); + switch (parm) + { case LPX_K_RELAX: + if (!(0.0 <= val && val <= 1.0)) + xerror("lpx_set_real_parm: RELAX = %g; invalid value\n", + val); + cps->relax = val; + break; + case LPX_K_TOLBND: + if (!(DBL_EPSILON <= val && val <= 0.001)) + xerror("lpx_set_real_parm: TOLBND = %g; invalid value\n", + val); + cps->tol_bnd = val; + break; + case LPX_K_TOLDJ: + if (!(DBL_EPSILON <= val && val <= 0.001)) + xerror("lpx_set_real_parm: TOLDJ = %g; invalid value\n", + val); + cps->tol_dj = val; + break; + case LPX_K_TOLPIV: + if (!(DBL_EPSILON <= val && val <= 0.001)) + xerror("lpx_set_real_parm: TOLPIV = %g; invalid value\n", + val); + cps->tol_piv = val; + break; + case LPX_K_OBJLL: + cps->obj_ll = val; + break; + case LPX_K_OBJUL: + cps->obj_ul = val; + break; + case LPX_K_TMLIM: + cps->tm_lim = val; + break; + case LPX_K_OUTDLY: + cps->out_dly = val; + break; + case LPX_K_TOLINT: + if (!(DBL_EPSILON <= val && val <= 0.001)) + xerror("lpx_set_real_parm: TOLINT = %g; invalid value\n", + val); + cps->tol_int = val; + break; + case LPX_K_TOLOBJ: + if (!(DBL_EPSILON <= val && val <= 0.001)) + xerror("lpx_set_real_parm: TOLOBJ = %g; invalid value\n", + val); + cps->tol_obj = val; + break; + case LPX_K_MIPGAP: + if (val < 0.0) + xerror("lpx_set_real_parm: MIPGAP = %g; invalid value\n", + val); + cps->mip_gap = val; + break; + default: + xerror("lpx_set_real_parm: parm = %d; invalid parameter\n", + parm); + } + return; +} + +double lpx_get_real_parm(LPX *lp, int parm) +{ /* query real control parameter */ + struct CPS *cps = find_cps(lp); + double val = 0.0; + switch (parm) + { case LPX_K_RELAX: + val = cps->relax; + break; + case LPX_K_TOLBND: + val = cps->tol_bnd; + break; + case LPX_K_TOLDJ: + val = cps->tol_dj; + break; + case LPX_K_TOLPIV: + val = cps->tol_piv; + break; + case LPX_K_OBJLL: + val = cps->obj_ll; + break; + case LPX_K_OBJUL: + val = cps->obj_ul; + break; + case LPX_K_TMLIM: + val = cps->tm_lim; + break; + case LPX_K_OUTDLY: + val = cps->out_dly; + break; + case LPX_K_TOLINT: + val = cps->tol_int; + break; + case LPX_K_TOLOBJ: + val = cps->tol_obj; + break; + case LPX_K_MIPGAP: + val = cps->mip_gap; + break; + default: + xerror("lpx_get_real_parm: parm = %d; invalid parameter\n", + parm); + } + return val; +} + +LPX *lpx_read_mps(const char *fname) +{ /* read problem data in fixed MPS format */ + LPX *lp = lpx_create_prob(); + if (glp_read_mps(lp, GLP_MPS_DECK, NULL, fname)) + lpx_delete_prob(lp), lp = NULL; + return lp; +} + +int lpx_write_mps(LPX *lp, const char *fname) +{ /* write problem data in fixed MPS format */ + return glp_write_mps(lp, GLP_MPS_DECK, NULL, fname); +} + +int lpx_read_bas(LPX *lp, const char *fname) +{ /* read LP basis in fixed MPS format */ + xassert(lp == lp); + xassert(fname == fname); + xerror("lpx_read_bas: operation not supported\n"); + return 0; +} + +int lpx_write_bas(LPX *lp, const char *fname) +{ /* write LP basis in fixed MPS format */ + xassert(lp == lp); + xassert(fname == fname); + xerror("lpx_write_bas: operation not supported\n"); + return 0; +} + +LPX *lpx_read_freemps(const char *fname) +{ /* read problem data in free MPS format */ + LPX *lp = lpx_create_prob(); + if (glp_read_mps(lp, GLP_MPS_FILE, NULL, fname)) + lpx_delete_prob(lp), lp = NULL; + return lp; +} + +int lpx_write_freemps(LPX *lp, const char *fname) +{ /* write problem data in free MPS format */ + return glp_write_mps(lp, GLP_MPS_FILE, NULL, fname); +} + +LPX *lpx_read_cpxlp(const char *fname) +{ /* read problem data in CPLEX LP format */ + LPX *lp; + lp = lpx_create_prob(); + if (glp_read_lp(lp, NULL, fname)) + lpx_delete_prob(lp), lp = NULL; + return lp; +} + +int lpx_write_cpxlp(LPX *lp, const char *fname) +{ /* write problem data in CPLEX LP format */ + return glp_write_lp(lp, NULL, fname); +} + +LPX *lpx_read_model(const char *model, const char *data, const char + *output) +{ /* read LP/MIP model written in GNU MathProg language */ + LPX *lp = NULL; + glp_tran *tran; + /* allocate the translator workspace */ + tran = glp_mpl_alloc_wksp(); + /* read model section and optional data section */ + if (glp_mpl_read_model(tran, model, data != NULL)) goto done; + /* read separate data section, if required */ + if (data != NULL) + if (glp_mpl_read_data(tran, data)) goto done; + /* generate the model */ + if (glp_mpl_generate(tran, output)) goto done; + /* build the problem instance from the model */ + lp = lpx_create_prob(); + glp_mpl_build_prob(tran, lp); +done: /* free the translator workspace */ + glp_mpl_free_wksp(tran); + /* bring the problem object to the calling program */ + return lp; +} + +int lpx_print_prob(LPX *lp, const char *fname) +{ /* write problem data in plain text format */ + return glp_write_lp(lp, NULL, fname); +} + +int lpx_print_sol(LPX *lp, const char *fname) +{ /* write LP problem solution in printable format */ + return glp_print_sol(lp, fname); +} + +int lpx_print_sens_bnds(LPX *lp, const char *fname) +{ /* write bounds sensitivity information */ + if (glp_get_status(lp) == GLP_OPT && !glp_bf_exists(lp)) + glp_factorize(lp); + return glp_print_ranges(lp, 0, NULL, 0, fname); +} + +int lpx_print_ips(LPX *lp, const char *fname) +{ /* write interior point solution in printable format */ + return glp_print_ipt(lp, fname); +} + +int lpx_print_mip(LPX *lp, const char *fname) +{ /* write MIP problem solution in printable format */ + return glp_print_mip(lp, fname); +} + +int lpx_is_b_avail(glp_prob *lp) +{ /* check if LP basis is available */ + return glp_bf_exists(lp); +} + +int lpx_main(int argc, const char *argv[]) +{ /* stand-alone LP/MIP solver */ + return glp_main(argc, argv); +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/oldapi/lpx.h b/resources/3rdparty/glpk-4.53/examples/oldapi/lpx.h new file mode 100644 index 000000000..54af27eec --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/oldapi/lpx.h @@ -0,0 +1,565 @@ +/* lpx.h (old GLPK API) */ + +/* Written by Andrew Makhorin <mao@gnu.org>, August 2013. */ + +#ifndef LPX_H +#define LPX_H + +#include <glpk.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define LPX glp_prob + +/* problem class: */ +#define LPX_LP 100 /* linear programming (LP) */ +#define LPX_MIP 101 /* mixed integer programming (MIP) */ + +/* type of auxiliary/structural variable: */ +#define LPX_FR 110 /* free variable */ +#define LPX_LO 111 /* variable with lower bound */ +#define LPX_UP 112 /* variable with upper bound */ +#define LPX_DB 113 /* double-bounded variable */ +#define LPX_FX 114 /* fixed variable */ + +/* optimization direction flag: */ +#define LPX_MIN 120 /* minimization */ +#define LPX_MAX 121 /* maximization */ + +/* status of primal basic solution: */ +#define LPX_P_UNDEF 132 /* primal solution is undefined */ +#define LPX_P_FEAS 133 /* solution is primal feasible */ +#define LPX_P_INFEAS 134 /* solution is primal infeasible */ +#define LPX_P_NOFEAS 135 /* no primal feasible solution exists */ + +/* status of dual basic solution: */ +#define LPX_D_UNDEF 136 /* dual solution is undefined */ +#define LPX_D_FEAS 137 /* solution is dual feasible */ +#define LPX_D_INFEAS 138 /* solution is dual infeasible */ +#define LPX_D_NOFEAS 139 /* no dual feasible solution exists */ + +/* status of auxiliary/structural variable: */ +#define LPX_BS 140 /* basic variable */ +#define LPX_NL 141 /* non-basic variable on lower bound */ +#define LPX_NU 142 /* non-basic variable on upper bound */ +#define LPX_NF 143 /* non-basic free variable */ +#define LPX_NS 144 /* non-basic fixed variable */ + +/* status of interior-point solution: */ +#define LPX_T_UNDEF 150 /* interior solution is undefined */ +#define LPX_T_OPT 151 /* interior solution is optimal */ + +/* kind of structural variable: */ +#define LPX_CV 160 /* continuous variable */ +#define LPX_IV 161 /* integer variable */ + +/* status of integer solution: */ +#define LPX_I_UNDEF 170 /* integer solution is undefined */ +#define LPX_I_OPT 171 /* integer solution is optimal */ +#define LPX_I_FEAS 172 /* integer solution is feasible */ +#define LPX_I_NOFEAS 173 /* no integer solution exists */ + +/* status codes reported by the routine lpx_get_status: */ +#define LPX_OPT 180 /* optimal */ +#define LPX_FEAS 181 /* feasible */ +#define LPX_INFEAS 182 /* infeasible */ +#define LPX_NOFEAS 183 /* no feasible */ +#define LPX_UNBND 184 /* unbounded */ +#define LPX_UNDEF 185 /* undefined */ + +/* exit codes returned by solver routines: */ +#define LPX_E_OK 200 /* success */ +#define LPX_E_EMPTY 201 /* empty problem */ +#define LPX_E_BADB 202 /* invalid initial basis */ +#define LPX_E_INFEAS 203 /* infeasible initial solution */ +#define LPX_E_FAULT 204 /* unable to start the search */ +#define LPX_E_OBJLL 205 /* objective lower limit reached */ +#define LPX_E_OBJUL 206 /* objective upper limit reached */ +#define LPX_E_ITLIM 207 /* iterations limit exhausted */ +#define LPX_E_TMLIM 208 /* time limit exhausted */ +#define LPX_E_NOFEAS 209 /* no feasible solution */ +#define LPX_E_INSTAB 210 /* numerical instability */ +#define LPX_E_SING 211 /* problems with basis matrix */ +#define LPX_E_NOCONV 212 /* no convergence (interior) */ +#define LPX_E_NOPFS 213 /* no primal feas. sol. (LP presolver) */ +#define LPX_E_NODFS 214 /* no dual feas. sol. (LP presolver) */ +#define LPX_E_MIPGAP 215 /* relative mip gap tolerance reached */ + +/* control parameter identifiers: */ +#define LPX_K_MSGLEV 300 /* lp->msg_lev */ +#define LPX_K_SCALE 301 /* lp->scale */ +#define LPX_K_DUAL 302 /* lp->dual */ +#define LPX_K_PRICE 303 /* lp->price */ +#define LPX_K_RELAX 304 /* lp->relax */ +#define LPX_K_TOLBND 305 /* lp->tol_bnd */ +#define LPX_K_TOLDJ 306 /* lp->tol_dj */ +#define LPX_K_TOLPIV 307 /* lp->tol_piv */ +#define LPX_K_ROUND 308 /* lp->round */ +#define LPX_K_OBJLL 309 /* lp->obj_ll */ +#define LPX_K_OBJUL 310 /* lp->obj_ul */ +#define LPX_K_ITLIM 311 /* lp->it_lim */ +#define LPX_K_ITCNT 312 /* lp->it_cnt */ +#define LPX_K_TMLIM 313 /* lp->tm_lim */ +#define LPX_K_OUTFRQ 314 /* lp->out_frq */ +#define LPX_K_OUTDLY 315 /* lp->out_dly */ +#define LPX_K_BRANCH 316 /* lp->branch */ +#define LPX_K_BTRACK 317 /* lp->btrack */ +#define LPX_K_TOLINT 318 /* lp->tol_int */ +#define LPX_K_TOLOBJ 319 /* lp->tol_obj */ +#define LPX_K_MPSINFO 320 /* lp->mps_info */ +#define LPX_K_MPSOBJ 321 /* lp->mps_obj */ +#define LPX_K_MPSORIG 322 /* lp->mps_orig */ +#define LPX_K_MPSWIDE 323 /* lp->mps_wide */ +#define LPX_K_MPSFREE 324 /* lp->mps_free */ +#define LPX_K_MPSSKIP 325 /* lp->mps_skip */ +#define LPX_K_LPTORIG 326 /* lp->lpt_orig */ +#define LPX_K_PRESOL 327 /* lp->presol */ +#define LPX_K_BINARIZE 328 /* lp->binarize */ +#define LPX_K_USECUTS 329 /* lp->use_cuts */ +#define LPX_K_BFTYPE 330 /* lp->bfcp->type */ +#define LPX_K_MIPGAP 331 /* lp->mip_gap */ + +#define LPX_C_COVER 0x01 /* mixed cover cuts */ +#define LPX_C_CLIQUE 0x02 /* clique cuts */ +#define LPX_C_GOMORY 0x04 /* Gomory's mixed integer cuts */ +#define LPX_C_MIR 0x08 /* mixed integer rounding cuts */ +#define LPX_C_ALL 0xFF /* all cuts */ + +typedef struct +{ /* this structure contains results reported by the routines which + checks Karush-Kuhn-Tucker conditions (for details see comments + to those routines) */ + /*--------------------------------------------------------------*/ + /* xR - A * xS = 0 (KKT.PE) */ + double pe_ae_max; + /* largest absolute error */ + int pe_ae_row; + /* number of row with largest absolute error */ + double pe_re_max; + /* largest relative error */ + int pe_re_row; + /* number of row with largest relative error */ + int pe_quality; + /* quality of primal solution: + 'H' - high + 'M' - medium + 'L' - low + '?' - primal solution is wrong */ + /*--------------------------------------------------------------*/ + /* l[k] <= x[k] <= u[k] (KKT.PB) */ + double pb_ae_max; + /* largest absolute error */ + int pb_ae_ind; + /* number of variable with largest absolute error */ + double pb_re_max; + /* largest relative error */ + int pb_re_ind; + /* number of variable with largest relative error */ + int pb_quality; + /* quality of primal feasibility: + 'H' - high + 'M' - medium + 'L' - low + '?' - primal solution is infeasible */ + /*--------------------------------------------------------------*/ + /* A' * (dR - cR) + (dS - cS) = 0 (KKT.DE) */ + double de_ae_max; + /* largest absolute error */ + int de_ae_col; + /* number of column with largest absolute error */ + double de_re_max; + /* largest relative error */ + int de_re_col; + /* number of column with largest relative error */ + int de_quality; + /* quality of dual solution: + 'H' - high + 'M' - medium + 'L' - low + '?' - dual solution is wrong */ + /*--------------------------------------------------------------*/ + /* d[k] >= 0 or d[k] <= 0 (KKT.DB) */ + double db_ae_max; + /* largest absolute error */ + int db_ae_ind; + /* number of variable with largest absolute error */ + double db_re_max; + /* largest relative error */ + int db_re_ind; + /* number of variable with largest relative error */ + int db_quality; + /* quality of dual feasibility: + 'H' - high + 'M' - medium + 'L' - low + '?' - dual solution is infeasible */ + /*--------------------------------------------------------------*/ + /* (x[k] - bound of x[k]) * d[k] = 0 (KKT.CS) */ + double cs_ae_max; + /* largest absolute error */ + int cs_ae_ind; + /* number of variable with largest absolute error */ + double cs_re_max; + /* largest relative error */ + int cs_re_ind; + /* number of variable with largest relative error */ + int cs_quality; + /* quality of complementary slackness: + 'H' - high + 'M' - medium + 'L' - low + '?' - primal and dual solutions are not complementary */ +} LPXKKT; + +LPX *lpx_create_prob(void); +/* create problem object */ + +void lpx_set_prob_name(LPX *lp, const char *name); +/* assign (change) problem name */ + +void lpx_set_obj_name(LPX *lp, const char *name); +/* assign (change) objective function name */ + +void lpx_set_obj_dir(LPX *lp, int dir); +/* set (change) optimization direction flag */ + +int lpx_add_rows(LPX *lp, int nrs); +/* add new rows to problem object */ + +int lpx_add_cols(LPX *lp, int ncs); +/* add new columns to problem object */ + +void lpx_set_row_name(LPX *lp, int i, const char *name); +/* assign (change) row name */ + +void lpx_set_col_name(LPX *lp, int j, const char *name); +/* assign (change) column name */ + +void lpx_set_row_bnds(LPX *lp, int i, int type, double lb, double ub); +/* set (change) row bounds */ + +void lpx_set_col_bnds(LPX *lp, int j, int type, double lb, double ub); +/* set (change) column bounds */ + +void lpx_set_obj_coef(glp_prob *lp, int j, double coef); +/* set (change) obj. coefficient or constant term */ + +void lpx_set_mat_row(LPX *lp, int i, int len, const int ind[], + const double val[]); +/* set (replace) row of the constraint matrix */ + +void lpx_set_mat_col(LPX *lp, int j, int len, const int ind[], + const double val[]); +/* set (replace) column of the constraint matrix */ + +void lpx_load_matrix(LPX *lp, int ne, const int ia[], const int ja[], + const double ar[]); +/* load (replace) the whole constraint matrix */ + +void lpx_del_rows(LPX *lp, int nrs, const int num[]); +/* delete specified rows from problem object */ + +void lpx_del_cols(LPX *lp, int ncs, const int num[]); +/* delete specified columns from problem object */ + +void lpx_delete_prob(LPX *lp); +/* delete problem object */ + +const char *lpx_get_prob_name(LPX *lp); +/* retrieve problem name */ + +const char *lpx_get_obj_name(LPX *lp); +/* retrieve objective function name */ + +int lpx_get_obj_dir(LPX *lp); +/* retrieve optimization direction flag */ + +int lpx_get_num_rows(LPX *lp); +/* retrieve number of rows */ + +int lpx_get_num_cols(LPX *lp); +/* retrieve number of columns */ + +const char *lpx_get_row_name(LPX *lp, int i); +/* retrieve row name */ + +const char *lpx_get_col_name(LPX *lp, int j); +/* retrieve column name */ + +int lpx_get_row_type(LPX *lp, int i); +/* retrieve row type */ + +double lpx_get_row_lb(LPX *lp, int i); +/* retrieve row lower bound */ + +double lpx_get_row_ub(LPX *lp, int i); +/* retrieve row upper bound */ + +void lpx_get_row_bnds(LPX *lp, int i, int *typx, double *lb, + double *ub); +/* retrieve row bounds */ + +int lpx_get_col_type(LPX *lp, int j); +/* retrieve column type */ + +double lpx_get_col_lb(LPX *lp, int j); +/* retrieve column lower bound */ + +double lpx_get_col_ub(LPX *lp, int j); +/* retrieve column upper bound */ + +void lpx_get_col_bnds(LPX *lp, int j, int *typx, double *lb, + double *ub); +/* retrieve column bounds */ + +double lpx_get_obj_coef(LPX *lp, int j); +/* retrieve obj. coefficient or constant term */ + +int lpx_get_num_nz(LPX *lp); +/* retrieve number of constraint coefficients */ + +int lpx_get_mat_row(LPX *lp, int i, int ind[], double val[]); +/* retrieve row of the constraint matrix */ + +int lpx_get_mat_col(LPX *lp, int j, int ind[], double val[]); +/* retrieve column of the constraint matrix */ + +void lpx_create_index(LPX *lp); +/* create the name index */ + +int lpx_find_row(LPX *lp, const char *name); +/* find row by its name */ + +int lpx_find_col(LPX *lp, const char *name); +/* find column by its name */ + +void lpx_delete_index(LPX *lp); +/* delete the name index */ + +void lpx_scale_prob(LPX *lp); +/* scale problem data */ + +void lpx_unscale_prob(LPX *lp); +/* unscale problem data */ + +void lpx_set_row_stat(LPX *lp, int i, int stat); +/* set (change) row status */ + +void lpx_set_col_stat(LPX *lp, int j, int stat); +/* set (change) column status */ + +void lpx_std_basis(LPX *lp); +/* construct standard initial LP basis */ + +void lpx_adv_basis(LPX *lp); +/* construct advanced initial LP basis */ + +void lpx_cpx_basis(LPX *lp); +/* construct Bixby's initial LP basis */ + +int lpx_simplex(LPX *lp); +/* easy-to-use driver to the simplex method */ + +int lpx_exact(LPX *lp); +/* easy-to-use driver to the exact simplex method */ + +int lpx_get_status(LPX *lp); +/* retrieve generic status of basic solution */ + +int lpx_get_prim_stat(LPX *lp); +/* retrieve primal status of basic solution */ + +int lpx_get_dual_stat(LPX *lp); +/* retrieve dual status of basic solution */ + +double lpx_get_obj_val(LPX *lp); +/* retrieve objective value (basic solution) */ + +int lpx_get_row_stat(LPX *lp, int i); +/* retrieve row status (basic solution) */ + +double lpx_get_row_prim(LPX *lp, int i); +/* retrieve row primal value (basic solution) */ + +double lpx_get_row_dual(LPX *lp, int i); +/* retrieve row dual value (basic solution) */ + +void lpx_get_row_info(LPX *lp, int i, int *tagx, double *vx, + double *dx); +/* obtain row solution information */ + +int lpx_get_col_stat(LPX *lp, int j); +/* retrieve column status (basic solution) */ + +double lpx_get_col_prim(LPX *lp, int j); +/* retrieve column primal value (basic solution) */ + +double lpx_get_col_dual(glp_prob *lp, int j); +/* retrieve column dual value (basic solution) */ + +void lpx_get_col_info(LPX *lp, int j, int *tagx, double *vx, + double *dx); +/* obtain column solution information (obsolete) */ + +int lpx_get_ray_info(LPX *lp); +/* determine what causes primal unboundness */ + +void lpx_check_kkt(LPX *lp, int scaled, LPXKKT *kkt); +/* check Karush-Kuhn-Tucker conditions */ + +int lpx_warm_up(LPX *lp); +/* "warm up" LP basis */ + +int lpx_eval_tab_row(LPX *lp, int k, int ind[], double val[]); +/* compute row of the simplex table */ + +int lpx_eval_tab_col(LPX *lp, int k, int ind[], double val[]); +/* compute column of the simplex table */ + +int lpx_transform_row(LPX *lp, int len, int ind[], double val[]); +/* transform explicitly specified row */ + +int lpx_transform_col(LPX *lp, int len, int ind[], double val[]); +/* transform explicitly specified column */ + +int lpx_prim_ratio_test(LPX *lp, int len, const int ind[], + const double val[], int how, double tol); +/* perform primal ratio test */ + +int lpx_dual_ratio_test(LPX *lp, int len, const int ind[], + const double val[], int how, double tol); +/* perform dual ratio test */ + +int lpx_interior(LPX *lp); +/* easy-to-use driver to the interior point method */ + +int lpx_ipt_status(LPX *lp); +/* retrieve status of interior-point solution */ + +double lpx_ipt_obj_val(LPX *lp); +/* retrieve objective value (interior point) */ + +double lpx_ipt_row_prim(LPX *lp, int i); +/* retrieve row primal value (interior point) */ + +double lpx_ipt_row_dual(LPX *lp, int i); +/* retrieve row dual value (interior point) */ + +double lpx_ipt_col_prim(LPX *lp, int j); +/* retrieve column primal value (interior point) */ + +double lpx_ipt_col_dual(LPX *lp, int j); +/* retrieve column dual value (interior point) */ + +void lpx_set_class(LPX *lp, int klass); +/* set problem class */ + +int lpx_get_class(LPX *lp); +/* determine problem klass */ + +void lpx_set_col_kind(LPX *lp, int j, int kind); +/* set (change) column kind */ + +int lpx_get_col_kind(LPX *lp, int j); +/* retrieve column kind */ + +int lpx_get_num_int(LPX *lp); +/* retrieve number of integer columns */ + +int lpx_get_num_bin(LPX *lp); +/* retrieve number of binary columns */ + +int lpx_integer(LPX *lp); +/* easy-to-use driver to the branch-and-bound method */ + +int lpx_intopt(LPX *lp); +/* easy-to-use driver to the branch-and-bound method */ + +int lpx_mip_status(LPX *lp); +/* retrieve status of MIP solution */ + +double lpx_mip_obj_val(LPX *lp); +/* retrieve objective value (MIP solution) */ + +double lpx_mip_row_val(LPX *lp, int i); +/* retrieve row value (MIP solution) */ + +double lpx_mip_col_val(LPX *lp, int j); +/* retrieve column value (MIP solution) */ + +void lpx_check_int(LPX *lp, LPXKKT *kkt); +/* check integer feasibility conditions */ + +void lpx_reset_parms(LPX *lp); +/* reset control parameters to default values */ + +void lpx_set_int_parm(LPX *lp, int parm, int val); +/* set (change) integer control parameter */ + +int lpx_get_int_parm(LPX *lp, int parm); +/* query integer control parameter */ + +void lpx_set_real_parm(LPX *lp, int parm, double val); +/* set (change) real control parameter */ + +double lpx_get_real_parm(LPX *lp, int parm); +/* query real control parameter */ + +LPX *lpx_read_mps(const char *fname); +/* read problem data in fixed MPS format */ + +int lpx_write_mps(LPX *lp, const char *fname); +/* write problem data in fixed MPS format */ + +int lpx_read_bas(LPX *lp, const char *fname); +/* read LP basis in fixed MPS format */ + +int lpx_write_bas(LPX *lp, const char *fname); +/* write LP basis in fixed MPS format */ + +LPX *lpx_read_freemps(const char *fname); +/* read problem data in free MPS format */ + +int lpx_write_freemps(LPX *lp, const char *fname); +/* write problem data in free MPS format */ + +LPX *lpx_read_cpxlp(const char *fname); +/* read problem data in CPLEX LP format */ + +int lpx_write_cpxlp(LPX *lp, const char *fname); +/* write problem data in CPLEX LP format */ + +LPX *lpx_read_model(const char *model, const char *data, + const char *output); +/* read LP/MIP model written in GNU MathProg language */ + +int lpx_print_prob(LPX *lp, const char *fname); +/* write problem data in plain text format */ + +int lpx_print_sol(LPX *lp, const char *fname); +/* write LP problem solution in printable format */ + +int lpx_print_sens_bnds(LPX *lp, const char *fname); +/* write bounds sensitivity information */ + +int lpx_print_ips(LPX *lp, const char *fname); +/* write interior point solution in printable format */ + +int lpx_print_mip(LPX *lp, const char *fname); +/* write MIP problem solution in printable format */ + +int lpx_is_b_avail(LPX *lp); +/* check if LP basis is available */ + +int lpx_main(int argc, const char *argv[]); +/* stand-alone LP/MIP solver */ + +#ifdef __cplusplus +} +#endif + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/oldapi/lpxsamp.c b/resources/3rdparty/glpk-4.53/examples/oldapi/lpxsamp.c new file mode 100644 index 000000000..dd081482f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/oldapi/lpxsamp.c @@ -0,0 +1,51 @@ +/* lpxsamp.c */ + +#include <stdio.h> +#include <stdlib.h> +#include "lpx.h" + +int main(void) +{ LPX *lp; + int ia[1+1000], ja[1+1000]; + double ar[1+1000], Z, x1, x2, x3; +s1: lp = lpx_create_prob(); +s2: lpx_set_prob_name(lp, "sample"); +s3: lpx_set_obj_dir(lp, LPX_MAX); +s4: lpx_add_rows(lp, 3); +s5: lpx_set_row_name(lp, 1, "p"); +s6: lpx_set_row_bnds(lp, 1, LPX_UP, 0.0, 100.0); +s7: lpx_set_row_name(lp, 2, "q"); +s8: lpx_set_row_bnds(lp, 2, LPX_UP, 0.0, 600.0); +s9: lpx_set_row_name(lp, 3, "r"); +s10: lpx_set_row_bnds(lp, 3, LPX_UP, 0.0, 300.0); +s11: lpx_add_cols(lp, 3); +s12: lpx_set_col_name(lp, 1, "x1"); +s13: lpx_set_col_bnds(lp, 1, LPX_LO, 0.0, 0.0); +s14: lpx_set_obj_coef(lp, 1, 10.0); +s15: lpx_set_col_name(lp, 2, "x2"); +s16: lpx_set_col_bnds(lp, 2, LPX_LO, 0.0, 0.0); +s17: lpx_set_obj_coef(lp, 2, 6.0); +s18: lpx_set_col_name(lp, 3, "x3"); +s19: lpx_set_col_bnds(lp, 3, LPX_LO, 0.0, 0.0); +s20: lpx_set_obj_coef(lp, 3, 4.0); +s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */ +s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2] = 1 */ +s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3] = 1 */ +s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */ +s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1] = 2 */ +s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2] = 4 */ +s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2] = 2 */ +s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3] = 5 */ +s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3] = 6 */ +s30: lpx_load_matrix(lp, 9, ia, ja, ar); +s31: lpx_simplex(lp); +s32: Z = lpx_get_obj_val(lp); +s33: x1 = lpx_get_col_prim(lp, 1); +s34: x2 = lpx_get_col_prim(lp, 2); +s35: x3 = lpx_get_col_prim(lp, 3); +s36: printf("\nZ = %g; x1 = %g; x2 = %g; x3 = %g\n", Z, x1, x2, x3); +s37: lpx_delete_prob(lp); + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/9dom.dat b/resources/3rdparty/glpk-4.53/examples/pbn/9dom.dat new file mode 100644 index 000000000..80ece7af5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/9dom.dat @@ -0,0 +1,65 @@ +/* 9dom.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #8098 from <www.webpbn.com>. +* Copyright (C) 2010 by Josh Greifer. Used by permission. +* +* Domino Logic III (Abstract pattern) +* +* created by Josh Greifer +* Apr 5, 2010 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 19; + +param n := 19; + +param row : 1 2 := + 1 3 . + 2 1 . + 3 3 1 + 4 1 . + 5 3 1 + 6 1 . + 7 3 1 + 8 1 . + 9 3 1 + 10 1 . + 11 3 1 + 12 1 . + 13 3 1 + 14 1 . + 15 3 1 + 16 1 . + 17 3 1 + 18 1 . + 19 1 . +; + +param col : 1 2 := + 1 1 . + 2 1 . + 3 1 3 + 4 1 . + 5 1 3 + 6 1 . + 7 1 3 + 8 1 . + 9 1 3 + 10 1 . + 11 1 3 + 12 1 . + 13 1 3 + 14 1 . + 15 1 3 + 16 1 . + 17 1 3 + 18 1 . + 19 3 . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/README b/resources/3rdparty/glpk-4.53/examples/pbn/README new file mode 100644 index 000000000..43dc82ce3 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/README @@ -0,0 +1,6 @@ +This subdirectory contains examples, which illustrate how to use +GLPK and the GNU MathProg modeling language for practical solving the +paint-by-numbers puzzle. + +For details please see the document "Solving Paint-By-Numbers Puzzles +with GLPK" included in this subdirectory (file pbn.pdf). diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/bucks.dat b/resources/3rdparty/glpk-4.53/examples/pbn/bucks.dat new file mode 100644 index 000000000..5dfc4f100 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/bucks.dat @@ -0,0 +1,77 @@ +/* bucks.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #27 from <www.webpbn.com>. +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Party at the Right [Political] +* +* created by Jan Wolter +* Apr 6, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 23; + +param n := 27; + +param row : 1 2 3 4 5 6 7 8 := + 1 11 . . . . . . . + 2 17 . . . . . . . + 3 3 5 5 3 . . . . + 4 2 2 2 1 . . . . + 5 2 1 3 1 3 1 4 . + 6 3 3 3 3 . . . . + 7 5 1 3 1 3 1 3 . + 8 3 2 2 4 . . . . + 9 5 5 5 5 . . . . + 10 23 . . . . . . . + 11 . . . . . . . . + 12 23 . . . . . . . + 13 1 1 . . . . . . + 14 1 1 . . . . . . + 15 1 2 1 . . . . . + 16 1 1 1 1 . . . . + 17 1 1 1 1 . . . . + 18 1 10 1 2 1 . . . + 19 1 1 1 1 1 1 3 . + 20 1 1 1 1 1 1 1 1 + 21 1 1 1 1 1 1 1 . + 22 1 1 1 1 2 2 . . + 23 5 5 3 . . . . . +; + +param col : 1 2 3 4 5 6 := + 1 4 12 . . . . + 2 6 1 1 . . . + 3 8 1 1 . . . + 4 3 2 2 1 1 . + 5 2 1 1 2 1 6 + 6 1 1 1 1 . . + 7 3 1 1 2 1 1 + 8 3 2 3 1 1 . + 9 10 1 1 . . . + 10 4 2 2 1 1 . + 11 3 1 1 2 1 1 + 12 2 1 1 1 . . + 13 3 1 1 2 1 1 + 14 3 2 3 1 6 . + 15 10 1 1 . . . + 16 4 2 2 1 1 . + 17 3 1 1 2 1 1 + 18 1 1 1 9 . . + 19 2 1 1 2 1 1 + 20 2 2 3 1 3 . + 21 8 1 5 . . . + 22 6 1 1 . . . + 23 4 9 1 . . . + 24 1 1 . . . . + 25 2 1 . . . . + 26 1 1 . . . . + 27 4 . . . . . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/cat.dat b/resources/3rdparty/glpk-4.53/examples/pbn/cat.dat new file mode 100644 index 000000000..a6554117d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/cat.dat @@ -0,0 +1,67 @@ +/* cat.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #6 from <www.webpbn.com>. +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Scardy Cat +* +* created by Jan Wolter +* Mar 24, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 20; + +param n := 20; + +param row : 1 2 3 4 := + 1 2 . . . + 2 2 . . . + 3 1 . . . + 4 1 . . . + 5 1 3 . . + 6 2 5 . . + 7 1 7 1 1 + 8 1 8 2 2 + 9 1 9 5 . + 10 2 16 . . + 11 1 17 . . + 12 7 11 . . + 13 5 5 3 . + 14 5 4 . . + 15 3 3 . . + 16 2 2 . . + 17 2 1 . . + 18 1 1 . . + 19 2 2 . . + 20 2 2 . . +; + +param col : 1 2 3 := + 1 5 . . + 2 5 3 . + 3 2 3 4 + 4 1 7 2 + 5 8 . . + 6 9 . . + 7 9 . . + 8 8 . . + 9 7 . . + 10 8 . . + 11 9 . . + 12 10 . . + 13 13 . . + 14 6 2 . + 15 4 . . + 16 6 . . + 17 6 . . + 18 5 . . + 19 6 . . + 20 6 . . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/dancer.dat b/resources/3rdparty/glpk-4.53/examples/pbn/dancer.dat new file mode 100644 index 000000000..42e3057a4 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/dancer.dat @@ -0,0 +1,42 @@ +/* dancer.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #1 from <www.webpbn.com>. +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Demo Puzzle from Front Page +* +* created by Jan Wolter +* Mar 24, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 10; + +param n := 5; + +param row : 1 2 3 := + 1 2 . . + 2 2 1 . + 3 1 1 . + 4 3 . . + 5 1 1 . + 6 1 1 . + 7 2 . . + 8 1 1 . + 9 1 2 . + 10 2 . . +; + +param col : 1 2 3 := + 1 2 1 . + 2 2 1 3 + 3 7 . . + 4 1 3 . + 5 2 1 . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/dragon.dat b/resources/3rdparty/glpk-4.53/examples/pbn/dragon.dat new file mode 100644 index 000000000..d2b8b14de --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/dragon.dat @@ -0,0 +1,61 @@ +/* dragon.dat */ + +/*********************************************************************** +* Hard 20x20 paint-by-numbers puzzle designed by Won Yoon Jo +* from the article "Painting by Numbers" by Robert A. Bosch (2000), +* <http://www.oberlin.edu/~math/faculty/bosch/pbn-page.html>. +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 20; + +param n := 20; + +param row : 1 2 3 4 5 := + 1 7 1 . . . + 2 1 1 2 . . + 3 2 1 2 . . + 4 1 2 2 . . + 5 4 2 3 . . + 6 3 1 4 . . + 7 3 1 3 . . + 8 2 1 4 . . + 9 2 9 . . . + 10 2 1 5 . . + 11 2 7 . . . + 12 14 . . . . + 13 8 2 . . . + 14 6 2 2 . . + 15 2 8 1 3 . + 16 1 5 5 2 . + 17 1 3 2 4 1 + 18 3 1 2 4 1 + 19 1 1 3 1 3 + 20 2 1 1 2 . ; + +param col : 1 2 3 4 5 := + 1 1 1 1 2 . + 2 3 1 2 1 1 + 3 1 4 2 1 1 + 4 1 3 2 4 . + 5 1 4 6 1 . + 6 1 11 1 . . + 7 5 1 6 2 . + 8 14 . . . . + 9 7 2 . . . + 10 7 2 . . . + 11 6 1 1 . . + 12 9 2 . . . + 13 3 1 1 1 . + 14 3 1 3 . . + 15 2 1 3 . . + 16 2 1 5 . . + 17 3 2 2 . . + 18 3 3 2 . . + 19 2 3 2 . . + 20 2 6 . . . ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/edge.dat b/resources/3rdparty/glpk-4.53/examples/pbn/edge.dat new file mode 100644 index 000000000..cdd1864e9 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/edge.dat @@ -0,0 +1,48 @@ +/* edge.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #23 from <www.webpbn.com>. +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Nonrepresentational Test Pattern +* +* created by Jan Wolter +* Apr 5, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 11; + +param n := 10; + +param row : 1 := + 1 1 + 2 3 + 3 1 + 4 2 + 5 1 + 6 3 + 7 3 + 8 1 + 9 2 + 10 2 + 11 4 +; + +param col : 1 2 := + 1 1 . + 2 3 . + 3 1 . + 4 2 2 + 5 2 . + 6 4 . + 7 1 . + 8 3 . + 9 3 . + 10 1 . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/forever.dat b/resources/3rdparty/glpk-4.53/examples/pbn/forever.dat new file mode 100644 index 000000000..e3bebf75f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/forever.dat @@ -0,0 +1,77 @@ +/* forever.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #6574 from <www.webpbn.com>. +* Copyright (C) 2009 by Gator. Used by permission. +* +* Lasts Forever +* +* created by Gator +* Aug 24, 2009 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 25; + +param n := 25; + +param row : 1 2 3 4 5 6 7 8 := + 1 1 2 2 2 2 2 1 . + 2 1 2 2 2 2 2 1 1 + 3 1 1 . . . . . . + 4 1 1 . . . . . . + 5 1 3 1 . . . . . + 6 1 13 1 . . . . . + 7 1 13 1 . . . . . + 8 1 13 1 . . . . . + 9 1 4 4 1 . . . . + 10 1 4 3 4 1 . . . + 11 1 4 5 4 1 . . . + 12 1 7 1 . . . . . + 13 1 7 1 . . . . . + 14 1 7 1 . . . . . + 15 1 7 1 . . . . . + 16 1 1 5 1 . . . . + 17 1 2 6 1 . . . . + 18 1 4 6 1 . . . . + 19 1 6 6 1 . . . . + 20 1 3 1 . . . . . + 21 1 1 1 . . . . . + 22 1 1 . . . . . . + 23 1 1 . . . . . . + 24 1 1 2 2 2 2 2 1 + 25 1 2 2 2 2 2 1 . +; + +param col : 1 2 3 4 5 6 7 8 := + 1 1 2 2 2 2 2 1 . + 2 1 1 2 2 2 2 2 1 + 3 1 1 . . . . . . + 4 1 1 . . . . . . + 5 1 1 . . . . . . + 6 1 2 1 . . . . . + 7 1 6 1 1 . . . . + 8 1 6 2 1 . . . . + 9 1 6 3 1 . . . . + 10 1 4 8 1 . . . . + 11 1 3 5 2 1 . . . + 12 1 4 8 2 1 . . . + 13 1 4 9 2 1 . . . + 14 1 4 11 1 . . . . + 15 1 3 9 1 . . . . + 16 1 4 8 1 . . . . + 17 1 6 3 1 . . . . + 18 1 6 2 1 . . . . + 19 1 6 1 1 . . . . + 20 1 2 1 . . . . . + 21 1 1 . . . . . . + 22 1 1 . . . . . . + 23 1 1 . . . . . . + 24 1 2 2 2 2 2 1 1 + 25 1 2 2 2 2 2 1 . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/knot.dat b/resources/3rdparty/glpk-4.53/examples/pbn/knot.dat new file mode 100644 index 000000000..b9e12d796 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/knot.dat @@ -0,0 +1,95 @@ +/* knot.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #16 from <www.webpbn.com>. +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Probably Not +* +* created by Jan Wolter +* Mar 27, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 34; + +param n := 34; + +param row : 1 2 3 4 5 6 7 8 := + 1 1 1 . . . . . . + 2 2 2 . . . . . . + 3 3 3 . . . . . . + 4 2 1 1 2 . . . . + 5 2 1 1 2 . . . . + 6 1 1 1 1 . . . . + 7 1 1 1 1 . . . . + 8 18 . . . . . . . + 9 2 1 1 1 1 2 . . + 10 1 1 1 1 1 1 . . + 11 1 1 1 1 1 1 . . + 12 26 . . . . . . . + 13 2 1 1 1 1 1 1 2 + 14 2 1 1 2 2 1 1 2 + 15 2 1 1 2 2 1 1 2 + 16 14 14 . . . . . . + 17 1 1 1 1 . . . . + 18 1 1 1 1 . . . . + 19 14 14 . . . . . . + 20 2 1 1 2 2 1 1 2 + 21 2 1 1 2 2 1 1 2 + 22 2 1 1 1 1 1 1 2 + 23 26 . . . . . . . + 24 1 1 1 1 1 1 . . + 25 1 1 1 1 1 1 . . + 26 2 1 1 1 1 2 . . + 27 18 . . . . . . . + 28 1 1 1 1 . . . . + 29 1 1 1 1 . . . . + 30 2 1 1 2 . . . . + 31 2 1 1 2 . . . . + 32 3 3 . . . . . . + 33 2 2 . . . . . . + 34 1 1 . . . . . . +; + +param col : 1 2 3 4 5 6 7 8 := + 1 1 1 . . . . . . + 2 2 2 . . . . . . + 3 3 3 . . . . . . + 4 2 1 1 2 . . . . + 5 2 1 1 2 . . . . + 6 1 1 1 1 . . . . + 7 1 1 1 1 . . . . + 8 18 . . . . . . . + 9 2 1 1 1 1 2 . . + 10 1 1 1 1 1 1 . . + 11 1 1 1 1 1 1 . . + 12 26 . . . . . . . + 13 2 1 1 1 1 1 1 2 + 14 2 1 1 2 2 1 1 2 + 15 2 1 1 2 2 1 1 2 + 16 14 14 . . . . . . + 17 1 1 1 1 . . . . + 18 1 1 1 1 . . . . + 19 14 14 . . . . . . + 20 2 1 1 2 2 1 1 2 + 21 2 1 1 2 2 1 1 2 + 22 2 1 1 1 1 1 1 2 + 23 26 . . . . . . . + 24 1 1 1 1 1 1 . . + 25 1 1 1 1 1 1 . . + 26 2 1 1 1 1 2 . . + 27 18 . . . . . . . + 28 1 1 1 1 . . . . + 29 1 1 1 1 . . . . + 30 2 1 1 2 . . . . + 31 2 1 1 2 . . . . + 32 3 3 . . . . . . + 33 2 2 . . . . . . + 34 1 1 . . . . . . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/light.dat b/resources/3rdparty/glpk-4.53/examples/pbn/light.dat new file mode 100644 index 000000000..1ffc5d460 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/light.dat @@ -0,0 +1,122 @@ +/* light.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #803 from <www.webpbn.com>. +* Copyright (C) 2007 by Robert Kummerfeldt. Used by permission. +* +* You light up my life +* +* created by Robert Kummerfeldt +* Mar 15, 2007 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 45; + +param n := 50; + +param row : 1 2 3 4 := + 1 . . . . + 2 1 . . . + 3 1 . . . + 4 3 . . . + 5 2 2 . . + 6 1 1 . . + 7 7 . . . + 8 1 1 . . + 9 1 3 1 . + 10 1 3 1 . + 11 1 1 . . + 12 11 . . . + 13 1 1 . . + 14 1 1 . . + 15 2 2 . . + 16 1 1 . . + 17 1 1 . . + 18 1 1 . . + 19 1 1 . . + 20 2 2 . . + 21 1 1 . . + 22 1 1 . . + 23 1 1 . . + 24 1 1 . . + 25 1 1 . . + 26 1 1 . . + 27 1 1 . . + 28 1 1 . . + 29 1 1 . . + 30 1 1 . . + 31 2 2 . . + 32 1 1 . . + 33 1 1 . . + 34 1 1 . . + 35 1 1 . . + 36 1 1 . . + 37 1 4 1 . + 38 1 1 1 1 + 39 1 1 1 1 + 40 1 1 1 1 + 41 1 1 1 1 + 42 25 . . . + 43 6 5 . . + 44 5 6 . . + 45 4 5 . . +; + +param col : 1 2 3 4 5 := + 1 1 . . . . + 2 1 . . . . + 3 1 . . . . + 4 2 . . . . + 5 1 . . . . + 6 1 . . . . + 7 1 . . . . + 8 2 . . . . + 9 1 . . . . + 10 1 . . . . + 11 1 . . . . + 12 1 . . . . + 13 2 . . . . + 14 1 . . . . + 15 1 . . . . + 16 1 . . . . + 17 5 . . . . + 18 7 1 . . . + 19 6 1 . . . + 20 6 1 . . . + 21 1 6 1 . . + 22 4 1 . . . + 23 7 1 . . . + 24 1 1 1 1 . + 25 2 1 2 1 1 + 26 3 1 2 1 1 + 27 2 1 2 1 1 + 28 1 1 1 1 . + 29 7 6 . . . + 30 4 1 1 . . + 31 1 6 1 1 . + 32 6 6 . . . + 33 6 1 . . . + 34 5 1 . . . + 35 7 . . . . + 36 1 . . . . + 37 2 . . . . + 38 1 . . . . + 39 1 . . . . + 40 1 . . . . + 41 2 . . . . + 42 1 . . . . + 43 1 . . . . + 44 1 . . . . + 45 1 . . . . + 46 2 . . . . + 47 1 . . . . + 48 1 . . . . + 49 1 . . . . + 50 1 . . . . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/mum.dat b/resources/3rdparty/glpk-4.53/examples/pbn/mum.dat new file mode 100644 index 000000000..a1baf5090 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/mum.dat @@ -0,0 +1,101 @@ +/* mum.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #65 from <www.webpbn.com>. +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Mum's the Word [has only one solution] +* +* created by Jan Wolter +* Jul 10, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 40; + +param n := 34; + +param row : 1 2 3 4 5 6 7 8 9 := + 1 12 . . . . . . . . + 2 5 2 5 . . . . . . + 3 5 2 2 5 . . . . . + 4 1 2 2 2 2 2 1 . . + 5 4 2 2 4 2 2 4 . . + 6 4 2 2 4 2 2 4 . . + 7 1 2 2 2 2 2 1 . . + 8 6 2 2 2 2 2 6 . . + 9 6 2 2 2 2 2 6 . . + 10 1 14 1 . . . . . . + 11 10 10 . . . . . . . + 12 8 3 3 8 . . . . . + 13 1 1 2 1 1 2 1 1 . + 14 9 2 2 2 2 9 . . . + 15 9 9 . . . . . . . + 16 1 1 1 1 1 1 . . . + 17 12 2 12 . . . . . . + 18 12 12 . . . . . . . + 19 1 1 4 1 1 . . . . + 20 14 14 . . . . . . . + 21 12 12 . . . . . . . + 22 2 1 4 1 2 . . . . + 23 9 4 9 . . . . . . + 24 1 7 4 7 1 . . . . + 25 1 1 1 4 1 1 1 . . + 26 1 7 4 7 1 . . . . + 27 1 7 4 7 1 . . . . + 28 1 2 1 2 1 2 1 . . + 29 1 7 2 7 1 . . . . + 30 1 1 6 2 6 1 1 . . + 31 1 1 1 1 2 1 1 1 1 + 32 1 1 6 2 6 1 1 . . + 33 1 1 5 5 1 1 . . . + 34 1 1 1 8 1 1 1 . . + 35 1 1 4 4 1 1 . . . + 36 1 2 6 2 1 . . . . + 37 2 4 4 2 . . . . . + 38 2 6 2 . . . . . . + 39 4 4 . . . . . . . + 40 6 . . . . . . . . +; + +param col : 1 2 3 4 5 6 7 8 9 10 11 12 := + 1 5 . . . . . . . . . . . + 2 3 2 1 . . . . . . . . . + 3 3 2 2 1 . . . . . . . . + 4 3 2 2 2 2 . . . . . . . + 5 3 2 2 2 2 3 . . . . . . + 6 1 2 2 2 2 2 16 . . . . . + 7 1 2 2 2 2 2 2 1 2 . . . + 8 1 2 2 2 2 2 2 13 1 . . . + 9 3 2 2 2 2 2 2 4 1 1 . . + 10 6 5 2 2 2 2 6 1 1 . . . + 11 1 7 3 2 2 2 2 2 1 1 1 . + 12 3 4 1 2 2 2 2 2 2 1 1 1 + 13 6 1 2 3 2 2 2 2 1 1 1 . + 14 1 7 2 16 1 1 . . . . . . + 15 1 4 1 1 1 1 1 1 1 1 1 . + 16 1 2 1 3 1 1 6 1 1 1 1 . + 17 2 7 1 1 11 1 1 1 1 . . . + 18 2 7 1 1 11 1 1 1 1 . . . + 19 1 2 1 3 1 1 6 1 1 1 1 . + 20 1 4 1 1 1 1 1 1 1 1 1 . + 21 1 7 2 16 1 1 . . . . . . + 22 6 1 2 3 2 2 2 2 1 1 1 . + 23 3 4 1 2 2 2 2 2 2 1 1 1 + 24 1 7 3 2 2 2 2 2 1 1 1 . + 25 6 5 2 2 2 2 6 1 1 . . . + 26 3 2 2 2 2 2 2 4 1 1 . . + 27 1 2 2 2 2 2 2 13 1 . . . + 28 1 2 2 2 2 2 2 1 2 . . . + 29 1 2 2 2 2 2 16 . . . . . + 30 3 2 2 2 2 3 . . . . . . + 31 3 2 2 2 2 . . . . . . . + 32 3 2 2 1 . . . . . . . . + 33 3 2 1 . . . . . . . . . + 34 5 . . . . . . . . . . . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/pbn.mod b/resources/3rdparty/glpk-4.53/examples/pbn/pbn.mod new file mode 100644 index 000000000..f9616f104 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/pbn.mod @@ -0,0 +1,268 @@ +/* PBN, Paint-By-Numbers Puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* NOTE: See also the document "Solving Paint-By-Numbers Puzzles with + GLPK", which is included in the GLPK distribution. */ + +/* A paint-by-numbers puzzle consists of an m*n grid of pixels (the + canvas) together with m+n cluster-size sequences, one for each row + and column. The goal is to paint the canvas with a picture that + satisfies the following constraints: + + 1. Each pixel must be blank or white. + + 2. If a row or column has cluster-size sequence s1, s2, ..., sk, + then it must contain k clusters of black pixels - the first with + s1 black pixels, the second with s2 black pixels, and so on. + + It should be noted that "first" means "leftmost" for rows and + "topmost" for columns, and that rows and columns need not begin or + end with black pixels. + + Example: + 1 1 + 1 1 + 2 1 1 1 1 1 2 3 + 3 2 1 2 1 2 3 4 8 9 + + 3 6 # # # . # # # # # # + 1 4 # . . . . . # # # # + 1 1 3 . . # . # . . # # # + 2 . . . . . . . . # # + 3 3 . . # # # . . # # # + 1 4 # . . . . . # # # # + 2 5 # # . . . # # # # # + 2 5 # # . . . # # # # # + 1 1 . . . # . . . . . # + 3 . . # # # . . . . . + + (In Russia such puzzles are known as "Japanese crosswords".) + + References: + Robert A. Bosch, "Painting by Numbers", 2000. + <http://www.oberlin.edu/~math/faculty/bosch/pbn-page.html> */ + +/*--------------------------------------------------------------------*/ +/* Main part based on the formulation proposed by Robert Bosch. */ + +param m, integer, >= 1; +/* the number of rows */ + +param n, integer, >= 1; +/* the number of columns */ + +param row{i in 1..m, 1..n div 2}, integer, >= 0, default 0; +/* the cluster-size sequence for row i (raw data) */ + +param col{j in 1..n, 1..m div 2}, integer, >= 0, default 0; +/* the cluster-size sequence for column j (raw data) */ + +param kr{i in 1..m} := sum{t in 1..n div 2: row[i,t] > 0} 1; +/* the number of clusters in row i */ + +param kc{j in 1..n} := sum{t in 1..m div 2: col[j,t] > 0} 1; +/* the number of clusters in column j */ + +param sr{i in 1..m, t in 1..kr[i]} := row[i,t], integer, >= 1; +/* the cluster-size sequence for row i */ + +param sc{j in 1..n, t in 1..kc[j]} := col[j,t], integer, >= 1; +/* the cluster-size sequence for column j */ + +check{i in 1..m}: sum{t in 1..kr[i]} sr[i,t] <= n - (kr[i] - 1); +/* check that the sum of the cluster sizes in each row is valid */ + +check{j in 1..n}: sum{t in 1..kc[j]} sc[j,t] <= m - (kc[j] - 1); +/* check that the sum of the cluster sizes in each column is valid */ + +check: sum{i in 1..m, t in 1..kr[i]} sr[i,t] = + sum{j in 1..n, t in 1..kc[j]} sc[j,t]; +/* check that the sum of the cluster sizes in all rows is equal to the + sum of the cluster sizes in all columns */ + +param er{i in 1..m, t in 1..kr[i]} := + if t = 1 then 1 else er[i,t-1] + sr[i,t-1] + 1; +/* the smallest value of j such that row i's t-th cluster can be + placed in row i with its leftmost pixel occupying pixel j */ + +param lr{i in 1..m, t in 1..kr[i]} := + if t = kr[i] then n + 1 - sr[i,t] else lr[i,t+1] - sr[i,t] - 1; +/* the largest value of j such that row i's t-th cluster can be + placed in row i with its leftmost pixel occupying pixel j */ + +param ec{j in 1..n, t in 1..kc[j]} := + if t = 1 then 1 else ec[j,t-1] + sc[j,t-1] + 1; +/* the smallest value of i such that column j's t-th cluster can be + placed in column j with its topmost pixel occupying pixel i */ + +param lc{j in 1..n, t in 1..kc[j]} := + if t = kc[j] then m + 1 - sc[j,t] else lc[j,t+1] - sc[j,t] - 1; +/* the largest value of i such that column j's t-th cluster can be + placed in column j with its topmost pixel occupying pixel i */ + +var z{i in 1..m, j in 1..n}, binary; +/* z[i,j] = 1, if row i's j-th pixel is painted black + z[i,j] = 0, if row i's j-th pixel is painted white */ + +var y{i in 1..m, t in 1..kr[i], j in er[i,t]..lr[i,t]}, binary; +/* y[i,t,j] = 1, if row i's t-th cluster is placed in row i with its + leftmost pixel occupying pixel j + y[i,t,j] = 0, if not */ + +var x{j in 1..n, t in 1..kc[j], i in ec[j,t]..lc[j,t]}, binary; +/* x[j,t,i] = 1, if column j's t-th cluster is placed in column j with + its topmost pixel occupying pixel i + x[j,t,i] = 0, if not */ + +s.t. fa{i in 1..m, t in 1..kr[i]}: + sum{j in er[i,t]..lr[i,t]} y[i,t,j] = 1; +/* row i's t-th cluster must appear in row i exactly once */ + +s.t. fb{i in 1..m, t in 1..kr[i]-1, j in er[i,t]..lr[i,t]}: + y[i,t,j] <= sum{jp in j+sr[i,t]+1..lr[i,t+1]} y[i,t+1,jp]; +/* row i's (t+1)-th cluster must be placed to the right of its t-th + cluster */ + +s.t. fc{j in 1..n, t in 1..kc[j]}: + sum{i in ec[j,t]..lc[j,t]} x[j,t,i] = 1; +/* column j's t-th cluster must appear in column j exactly once */ + +s.t. fd{j in 1..n, t in 1..kc[j]-1, i in ec[j,t]..lc[j,t]}: + x[j,t,i] <= sum{ip in i+sc[j,t]+1..lc[j,t+1]} x[j,t+1,ip]; +/* column j's (t+1)-th cluster must be placed below its t-th cluster */ + +s.t. fe{i in 1..m, j in 1..n}: + z[i,j] <= sum{t in 1..kr[i], jp in er[i,t]..lr[i,t]: + j-sr[i,t]+1 <= jp and jp <= j} y[i,t,jp]; +/* the double coverage constraint stating that if row i's j-th pixel + is painted black, then at least one of row i's clusters must be + placed in such a way that it covers row i's j-th pixel */ + +s.t. ff{i in 1..m, j in 1..n}: + z[i,j] <= sum{t in 1..kc[j], ip in ec[j,t]..lc[j,t]: + i-sc[j,t]+1 <= ip and ip <= i} x[j,t,ip]; +/* the double coverage constraint making sure that if row i's j-th + pixel is painted black, then at least one of column j's clusters + covers it */ + +s.t. fg{i in 1..m, j in 1..n, t in 1..kr[i], jp in er[i,t]..lr[i,t]: + j-sr[i,t]+1 <= jp and jp <= j}: z[i,j] >= y[i,t,jp]; +/* the constraint to prevent white pixels from being covered by the + row clusters */ + +s.t. fh{i in 1..m, j in 1..n, t in 1..kc[j], ip in ec[j,t]..lc[j,t]: + i-sc[j,t]+1 <= ip and ip <= i}: z[i,j] >= x[j,t,ip]; +/* the constraint to prevent white pixels from being covered by the + column clusters */ + +/* this is a feasibility problem, so no objective is needed */ + +/*--------------------------------------------------------------------*/ +/* The following part is used only to check for multiple solutions. */ + +param zz{i in 1..m, j in 1..n}, binary, default 0; +/* zz[i,j] is z[i,j] for a previously found solution */ + +s.t. fz{1..1 : sum{i in 1..m, j in 1..n} zz[i,j] > 0}: + sum{i in 1..m, j in 1..n} + (if zz[i,j] then (1 - z[i,j]) else z[i,j]) >= 1; +/* the constraint to forbid finding a solution, which is identical to + the previously found one; this constraint is included in the model + only if the previously found solution specified by the parameter zz + is provided in the data section */ + +solve; + +/*--------------------------------------------------------------------*/ +/* Print solution to the standard output. */ + +for {i in 1..m} +{ printf{j in 1..n} " %s", if z[i,j] then "#" else "."; + printf "\n"; +} + +/*--------------------------------------------------------------------*/ +/* Write solution to a text file in PostScript format. */ + +param ps, symbolic, default "solution.ps"; + +printf "%%!PS-Adobe-3.0\n" > ps; +printf "%%%%Creator: GLPK (pbn.mod)\n" >> ps; +printf "%%%%BoundingBox: 0 0 %d %d\n", + 6 * (n + 2), 6 * (m + 2) >> ps; +printf "%%%%EndComments\n" >> ps; +printf "<</PageSize [%d %d]>> setpagedevice\n", + 6 * (n + 2), 6 * (m + 2) >> ps; +printf "0.1 setlinewidth\n" >> ps; +printf "/A { 2 copy 2 copy 2 copy newpath moveto exch 6 add exch line" & + "to\n" >> ps; +printf "exch 6 add exch 6 add lineto 6 add lineto closepath } bind de" & + "f\n" >> ps; +printf "/W { A stroke } def\n" >> ps; +printf "/B { A fill } def\n" >> ps; +printf {i in 1..m, j in 1..n} "%d %d %s\n", + (j - 1) * 6 + 6, (m - i) * 6 + 6, + if z[i,j] then "B" else "W" >> ps; +printf "%%%%EOF\n" >> ps; + +printf "Solution has been written to file %s\n", ps; + +/*--------------------------------------------------------------------*/ +/* Write solution to a text file in the form of MathProg data section, + which can be used later to check for multiple solutions. */ + +param dat, symbolic, default "solution.dat"; + +printf "data;\n" > dat; +printf "\n" >> dat; +printf "param zz :" >> dat; +printf {j in 1..n} " %d", j >> dat; +printf " :=\n" >> dat; +for {i in 1..m} +{ printf " %2d", i >> dat; + printf {j in 1..n} " %s", if z[i,j] then "1" else "." >> dat; + printf "\n" >> dat; +} +printf ";\n" >> dat; +printf "\n" >> dat; +printf "end;\n" >> dat; + +printf "Solution has also been written to file %s\n", dat; + +/*--------------------------------------------------------------------*/ +/* The following data correspond to the example above. */ + +data; + +param m := 10; + +param n := 10; + +param row : 1 2 3 := + 1 3 6 . + 2 1 4 . + 3 1 1 3 + 4 2 . . + 5 3 3 . + 6 1 4 . + 7 2 5 . + 8 2 5 . + 9 1 1 . + 10 3 . . +; + +param col : 1 2 3 4 := + 1 2 3 . . + 2 1 2 . . + 3 1 1 1 1 + 4 1 2 . . + 5 1 1 1 1 + 6 1 2 . . + 7 2 3 . . + 8 3 4 . . + 9 8 . . . + 10 9 . . . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/pbn.pdf b/resources/3rdparty/glpk-4.53/examples/pbn/pbn.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8342189cf63c09063f6184a909e0d4a4379e8c80 GIT binary patch literal 43620 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%0AC8O*BPVKd0LQcjSrmh7K!76nm@;p4kL%9f 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 bxw!*e-Mw5bED<=^S$S9y{xQFlr4arX?90%$ literal 0 HcmV?d00001 diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/pbn.tex b/resources/3rdparty/glpk-4.53/examples/pbn/pbn.tex new file mode 100644 index 000000000..c73a441b0 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/pbn.tex @@ -0,0 +1,279 @@ +%* pbn.tex *% + +\documentclass[11pt,draft]{article} +\usepackage{amssymb} + +\begin{document} + +\title{Solving Paint-By-Numbers Puzzles with GLPK} + +\author{Andrew Makhorin {\tt<mao@gnu.org>}} + +\date{August 2011} + +\maketitle + +\section{Introduction$^1$} + +\footnotetext[1]{This section is based on the material from [1].} + +A {\it paint-by-numbers} puzzle consists of an $m\times n$ grid of +pixels (the {\it canvas}) together with $m+n$ {\it cluster-size +sequences}, one for each row and column. The goal is to paint the canvas +with a picture that satisfies the following constraints: + +1. Each pixel must be blank or white. + +2. If a row or column has cluster-size sequence $s_1$, $s_2$, \dots, +$s_k$, then it must contain $k$ clusters of black pixels---the first +with $s_1$ black pixels, the second with $s_2$ black pixels, and so on. + +It should be noted that ``first'' means ``leftmost'' for rows and +``topmost'' for columns, and that rows and columns need not begin or end +with black pixels. + +\subsubsection*{Example} + +\def\arraystretch{.8} + +\begin{center} +\begin{tabular}{*{3}{@{$\;\;$}c}c*{10}{@{\ }c}@{}} + & & && & &1& &1& & & & & \\ + & & && & &1& &1& & & & & \\ + & & &&2&1&1&1&1&1&2&3& & \\ + & & &&3&2&1&2&1&2&3&4&8&9\\ +\\ + &3&6&&$\blacksquare$&$\blacksquare$&$\blacksquare$&$\square$& +$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$& +$\blacksquare$&$\blacksquare$\\ + &1&4&&$\blacksquare$&$\square$&$\square$&$\square$&$\square$& +$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ +1&1&3&&$\square$&$\square$&$\blacksquare$&$\square$&$\blacksquare$& +$\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ + & &2&&$\square$&$\square$&$\square$&$\square$&$\square$&$\square$& +$\square$&$\square$&$\blacksquare$&$\blacksquare$\\ + &3&3&&$\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$& +$\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ + &1&4&&$\blacksquare$&$\square$&$\square$&$\square$&$\square$&$\square$& +$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ + &2&5&&$\blacksquare$&$\blacksquare$&$\square$&$\square$&$\square$& +$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$& +$\blacksquare$\\ + &2&5&&$\blacksquare$&$\blacksquare$&$\square$&$\square$&$\square$& +$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$& +$\blacksquare$\\ + &1&1&&$\square$&$\square$&$\square$&$\blacksquare$&$\square$&$\square$& +$\square$&$\square$&$\square$&$\blacksquare$\\ + & &3&&$\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$& +$\square$&$\square$&$\square$&$\square$&$\square$\\ +\end{tabular} +\end{center} + +\def\arraystretch{1} + +\section{Solving a puzzle} + +The Paint-By-Numbers puzzle can be formulated as a 0-1 integer +feasibility problem. The formulation used in GLPK was proposed in [1]. + +For solving puzzles there are used two components, which both are +coded in the GNU MathProg modeling language [2]: the model section and +the data section. The model section is common for all puzzles and +placed in file \verb|pbn.mod|. This file is included in the GLPK +distribution and can be found in subdirectory \verb|examples/pbn|. + +To solve a particular puzzle the user only needs to prepare the data +section, which defines input data to the puzzle. The data section for +the example puzzle from the previous section may look like follows +(here \verb|m| is the number of rows, and \verb|n| is the number of +columns): + +\begin{footnotesize} +\begin{verbatim} +data; + +param m := 10; + +param n := 10; + +param row : 1 2 3 := + 1 3 6 . + 2 1 4 . + 3 1 1 3 + 4 2 . . + 5 3 3 . + 6 1 4 . + 7 2 5 . + 8 2 5 . + 9 1 1 . + 10 3 . . +; + +param col : 1 2 3 4 := + 1 2 3 . . + 2 1 2 . . + 3 1 1 1 1 + 4 1 2 . . + 5 1 1 1 1 + 6 1 2 . . + 7 2 3 . . + 8 3 4 . . + 9 8 . . . + 10 9 . . . +; + +end; +\end{verbatim} +\end{footnotesize} + +\newpage + +Let the data section for a puzzle be placed in file \verb|foo.dat|. +Then to solve the puzzle the user should enter the following command: + +\begin{verbatim} + glpsol --minisat -m pbn.mod -d foo.dat +\end{verbatim} + +\noindent +This command invokes \verb|glpsol|, the GLPK LP/MIP stand-alone solver, +which reads the model section from file \verb|pbn.mod|, the data section +from file \verb|foo.dat|, translates them to an internal representation, +and solves the resulting 0-1 integer feasibility problem. The option +\verb|--minisat| tells \verb|glpsol| to translate the feasibility +problem to a CNF satisfiability problem and then use the MiniSat solver +[3] to solve it. + +If a solution to the puzzle has been found, that is indicated by the +message \verb|SATISFIABLE|, \verb|glpsol| prints the solution to the +standard output (terminal), writes it to file \verb|solution.ps| in the +PostScript format, and also writes it to file \verb|solution.dat| in the +form of MathProg data section, which can be used later to check for +multiple solutions, if necessary (for details see the next section). +The message \verb|UNSATISFIABLE| means that the puzzle has no solution. + +Usually the time taken to solve a puzzle of moderate size (up to 50 rows +and columns) varies from several seconds to several minutes. However, +hard or large puzzles may require much more time. + +Data sections for some example puzzles included in the GLPK distribution +can be found in subdirectory \verb|examples/pbn|. + +\section{Checking for multiple solutions} + +Sometimes the user may be interested to know if the puzzle has exactly +one (unique) solution or it has multiple solutions. To check that the +user should solve the puzzle as explained above in the previous section +and then enter the following command: + +\begin{verbatim} + glpsol --minisat -m pbn.mod -d foo.dat -d solution.dat +\end{verbatim} + +\noindent +In this case \verb|glpsol| reads an additional data section from file +\verb|solution.dat|, which contains the previously found solution, +activates an additional constraint in the model section to forbid +finding the solution specified in the additional data section, and +attempts to find another solution. The message \verb|UNSATISFIABLE| +reported by \verb|glpsol| will mean that the puzzle has a unique +solution, while the message \verb|SATISFIABLE| will mean that the puzzle +has at least two different solutions. + +\newpage + +\section{Solution times} + +The table on the next page shows solution times on a sample set of +the paint-by-numbers puzzles from the \verb|<webpbn.com>| website. +This sample set was used in the survey [4] to compare efficiency of +existing PBN solvers. + +The authors of some puzzles from the sample set have given permission +for their puzzles to be freely redistributed as long as the original +attribution and copyright statement are retained. In the table these +puzzles are marked by an asterisk (*). The files containing the +MathProg data sections for these puzzles are included in the GLPK +distribution and can be found in subdirectory \verb|examples/pbn|. + +All runs were performed on Intel Pentium 4 (CPU 3GHz, 2GB of RAM). +The C compiler used was GCC 3.4.4 with default optimization options. + +The column `Sol.Time' shows the time, in seconds, taken by the +\verb|glpsol| solver to find a solution to corresponding puzzle. The +column `Chk.Time' shows the time, in seconds, taken by \verb|glpsol| to +check for multiple solutions, i.e. either to prove that the puzzle has +a unique solution or find another solution to the puzzle. Both these +times do not include the time used to translate the MathProg model and +data sections into an internal MIP representation, but include the time +used to translate the 0-1 feasibility problem to a CNF satisfiability +problem. + +\begin{thebibliography}{10} + +\bibitem{1} +Robert A. Bosch, ``Painting by Numbers'', 2000.\\ +\verb|<http://www.oberlin.edu/~math/faculty/bosch/pbn-page.html>|. + +\bibitem{2} +GLPK: Modeling Language GNU MathProg. Language Reference. (This +document is included in the GLPK distribution and can be found in +subdirectory \verb|doc|.) + +\bibitem{3} +Niklas E\'en, Niklas S\"orensson, ``An Extensible SAT-solver'', +Chalmers University of Technology, Sweden. \verb|<http://minisat.se/>|. + +\bibitem{4} +Jan Wolter, ``Survey of Paint-by-Number Puzzle Solvers''.\\ +\verb|<http://webpbn.com/survey/>|. + +\end{thebibliography} + +\newpage + +\begin{table} +\caption{Solution times on the sample set of puzzles from [4]} +\begin{center} +\begin{tabular}{@{}lllcrr@{}} +\hline +\multicolumn{2}{c}{Puzzle}&Size&Notes&Sol.Time, s&Chk.Time, s\\ +\hline +\#1&Dancer* &$10\times 5$&L&$<1$&$<1$\\ +\#6&Cat* &$20\times 20$&L&$<1$&$<1$\\ +\#21&Skid* &$25\times 14$&L, B&$<1$&$<1$\\ +\#27&Bucks* &$23\times 27$&B&$<1$&$<1$\\ +\#23&Edge* &$11\times 10$&&$<1$&$<1$\\ +\#2413&Smoke &$20\times 20$&&$<1$&$<1$\\ +\#16&Knot* &$34\times 34$&L&1&1\\ +\#529&Swing* &$45\times 45$&L&1&1\\ +\#65&Mum* &$40\times 34$&&1&1\\ +\#7604&DiCap &$55\times 55$&&10&10\\ +\#1694&Tragic &$50\times 45$&&3&3\\ +\#1611&Merka &$60\times 55$&B&4&4\\ +\#436&Petro* &$35\times 40$&&1&1\\ +\#4645&M\&M &$70\times 50$&B&5&6\\ +\#3541&Signed &$50\times 60$&&7&7\\ +\#803&Light* &$45\times 50$&B&1&1\\ +\#6574&Forever*&$25\times 25$&&1&1\\ +\#2040&Hot &$60\times 55$&&6&6\\ +\#6739&Karate &$40\times 40$&M&2&2\\ +\#8098&9-Dom* &$19\times 19$&&1&2\\ +\#2556&Flag &$45\times 65$&M, B&2&2\\ +\#2712&Lion &$47\times 47$&M&11&12\\ +\#10088&Marley &$63\times 52$&M&135&226\\ +\#9892&Nature &$40\times 50$&M&850&1053\\ +\hline +\end{tabular} + +\begin{tabular}{@{}lp{102mm}@{}} +*&Puzzle designer has given permission to redistribute the puzzle.\\ +L&Puzzle is line solvable. That is, it can be solved one line at a +time.\\ +B&Puzzle contains blank rows or columns.\\ +M&Puzzle has multiple solutions.\\ +\end{tabular} +\end{center} +\end{table} + +\end{document} diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/petro.dat b/resources/3rdparty/glpk-4.53/examples/pbn/petro.dat new file mode 100644 index 000000000..15ccc4a16 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/petro.dat @@ -0,0 +1,102 @@ +/* petro.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #436 from <www.webpbn.com>. +* Copyright (C) 2006 by Jan Wolter. Used by permission. +* +* Old Stone Face +* +* created by Jan Wolter +* Jun 17, 2006 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 35; + +param n := 40; + +param row : 1 2 3 4 5 6 7 8 9 := + 1 2 2 . . . . . . . + 2 2 3 2 . . . . . . + 3 3 3 3 2 . . . . . + 4 3 3 3 3 . . . . . + 5 2 3 3 3 3 2 . . . + 6 3 3 3 3 3 3 . . . + 7 4 2 3 2 2 4 . . . + 8 4 2 2 2 2 3 1 . . + 9 3 1 2 2 2 3 3 . . + 10 3 2 2 2 2 2 4 . . + 11 3 2 15 2 4 . . . . + 12 5 19 4 . . . . . . + 13 6 4 3 3 . . . . . + 14 6 4 4 . . . . . . + 15 2 4 6 2 . . . . . + 16 2 2 3 3 3 2 . . . + 17 9 2 2 2 3 9 . . . + 18 10 2 2 2 2 2 10 . . + 19 4 2 3 3 2 2 3 2 5 + 20 2 5 2 4 2 . . . . + 21 5 3 2 2 5 . . . . + 22 6 3 2 3 7 . . . . + 23 6 8 9 7 . . . . . + 24 4 8 7 5 . . . . . + 25 4 . . . . . . . . + 26 2 . . . . . . . . + 27 2 . . . . . . . . + 28 14 . . . . . . . . + 29 16 . . . . . . . . + 30 3 3 . . . . . . . + 31 2 2 . . . . . . . + 32 2 2 . . . . . . . + 33 4 4 . . . . . . . + 34 16 . . . . . . . . + 35 12 . . . . . . . . +; + +param col : 1 2 3 4 5 6 7 := + 1 1 . . . . . . + 2 3 2 . . . . . + 3 2 3 3 . . . . + 4 3 3 3 . . . . + 5 3 3 3 3 . . . + 6 4 2 2 2 . . . + 7 3 3 2 3 . . . + 8 3 2 2 2 . . . + 9 3 2 6 . . . . + 10 2 9 . . . . . + 11 2 3 3 . . . . + 12 4 4 3 2 4 . . + 13 7 2 5 2 6 . . + 14 12 2 3 2 3 2 . + 15 3 1 2 2 2 3 . + 16 2 2 3 2 2 2 . + 17 6 2 6 2 2 2 . + 18 12 4 3 2 2 . . + 19 12 2 2 2 . . . + 20 2 6 2 . . . . + 21 2 6 5 2 . . . + 22 10 9 2 2 . . . + 23 12 3 3 2 2 . . + 24 6 2 2 2 2 2 2 + 25 2 2 3 2 2 2 . + 26 4 3 2 2 2 3 . + 27 7 3 3 2 3 2 . + 28 5 3 5 2 6 . . + 29 4 3 3 3 4 . . + 30 3 5 3 . . . . + 31 3 9 . . . . . + 32 4 2 6 . . . . + 33 4 2 2 2 . . . + 34 4 2 2 3 . . . + 35 3 2 2 3 . . . + 36 3 3 3 . . . . + 37 3 3 3 . . . . + 38 4 3 3 . . . . + 39 2 3 3 . . . . + 40 2 1 . . . . . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/skid.dat b/resources/3rdparty/glpk-4.53/examples/pbn/skid.dat new file mode 100644 index 000000000..865c73b37 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/skid.dat @@ -0,0 +1,66 @@ +/* skid.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #21 from <www.webpbn.com>. +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Slippery Conditions +* +* created by Jan Wolter +* Apr 4, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 25; + +param n := 14; + +param row : 1 2 3 := + 1 9 . . + 2 1 1 . + 3 1 1 1 + 4 1 3 1 + 5 13 . . + 6 13 . . + 7 13 . . + 8 13 . . + 9 2 2 . + 10 2 2 . + 11 . . . + 12 2 2 . + 13 2 2 . + 14 2 2 . + 15 2 2 . + 16 2 2 . + 17 2 2 . + 18 2 2 . + 19 2 2 . + 20 2 2 . + 21 2 2 . + 22 2 2 . + 23 2 2 . + 24 2 2 . + 25 2 2 . +; + +param col : 1 2 3 4 5 := + 1 2 . . . . + 2 4 6 . . . + 3 9 4 4 2 . + 4 1 6 2 6 . + 5 1 5 2 . . + 6 1 6 . . . + 7 1 5 . . . + 8 1 4 . . . + 9 1 4 . . . + 10 1 4 2 . . + 11 1 4 6 . . + 12 1 6 4 4 2 + 13 9 2 6 . . + 14 4 2 . . . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/swing.dat b/resources/3rdparty/glpk-4.53/examples/pbn/swing.dat new file mode 100644 index 000000000..547e0dbd8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/pbn/swing.dat @@ -0,0 +1,117 @@ +/* swing.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #529 from <www.webpbn.com>. +* Copyright (C) 2006 by Jan Wolter. Used by permission. +* +* Swing +* +* created by Jan Wolter +* Sep 28, 2006 +* +* Encoded in GNU MathProg by Andrew Makhorin <mao@gnu.org>. +***********************************************************************/ + +data; + +param m := 45; + +param n := 45; + +param row : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 := + 1 7 1 1 1 1 1 . . . . . . . . + 2 3 1 3 1 4 1 4 1 5 1 5 1 2 . + 3 1 1 1 3 1 4 1 4 1 5 1 5 1 2 + 4 2 1 2 1 1 1 1 6 2 . . . . . + 5 3 30 1 5 . . . . . . . . . . + 6 1 5 8 1 1 7 1 1 3 . . . . . + 7 3 4 8 1 5 1 2 . . . . . . . + 8 3 20 6 6 . . . . . . . . . . + 9 3 3 7 2 5 1 . . . . . . . . + 10 3 3 1 1 9 1 1 5 6 . . . . . + 11 2 3 8 1 3 4 2 . . . . . . . + 12 5 3 1 10 4 5 2 . . . . . . . + 13 1 2 3 8 4 6 . . . . . . . . + 14 2 2 3 11 10 . . . . . . . . . + 15 2 2 3 10 7 . . . . . . . . . + 16 2 3 1 7 12 2 . . . . . . . . + 17 2 3 1 4 11 2 . . . . . . . . + 18 4 1 2 1 11 2 . . . . . . . . + 19 9 1 2 9 . . . . . . . . . . + 20 6 2 1 4 11 . . . . . . . . . + 21 2 5 1 2 6 6 . . . . . . . . + 22 6 2 4 8 4 . . . . . . . . . + 23 4 2 16 1 . . . . . . . . . . + 24 2 2 15 2 . . . . . . . . . . + 25 3 2 15 4 . . . . . . . . . . + 26 3 3 13 4 . . . . . . . . . . + 27 4 12 9 . . . . . . . . . . . + 28 1 9 10 . . . . . . . . . . . + 29 2 1 17 7 2 . . . . . . . . . + 30 2 2 8 3 8 2 . . . . . . . . + 31 2 3 6 3 8 2 . . . . . . . . + 32 2 4 5 4 7 2 . . . . . . . . + 33 2 5 5 4 6 . . . . . . . . . + 34 4 4 5 4 9 . . . . . . . . . + 35 1 4 6 4 4 . . . . . . . . . + 36 4 3 6 4 3 2 . . . . . . . . + 37 2 1 2 7 4 4 2 . . . . . . . + 38 2 2 2 9 5 5 2 . . . . . . . + 39 2 2 2 10 6 6 . . . . . . . . + 40 3 2 1 9 18 . . . . . . . . . + 41 8 4 23 . . . . . . . . . . . + 42 1 2 1 2 2 1 1 1 2 . . . . . + 43 2 1 4 2 1 4 1 5 1 3 1 2 . . + 44 2 1 5 4 4 1 5 1 3 1 2 . . . + 45 1 10 1 1 1 . . . . . . . . . +; + +param col : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 := + 1 7 1 1 1 1 1 . . . . . . . . + 2 2 2 4 1 4 1 5 1 4 1 4 1 2 . + 3 3 1 4 1 4 1 14 4 1 2 . . . . + 4 1 1 5 1 2 3 4 1 . . . . . . + 5 3 13 1 10 . . . . . . . . . . + 6 1 9 4 . . . . . . . . . . . + 7 6 7 2 2 . . . . . . . . . . + 8 8 4 1 4 . . . . . . . . . . + 9 2 8 3 2 5 3 . . . . . . . . + 10 10 1 3 7 2 . . . . . . . . . + 11 8 6 2 8 1 2 . . . . . . . . + 12 1 1 2 2 8 1 1 . . . . . . . + 13 2 1 1 1 2 1 3 1 3 3 1 . . . + 14 2 1 1 1 5 4 2 1 . . . . . . + 15 2 1 1 1 1 7 2 1 . . . . . . + 16 2 1 1 2 9 1 2 1 . . . . . . + 17 4 6 12 1 3 . . . . . . . . . + 18 16 13 3 2 . . . . . . . . . . + 19 12 21 2 . . . . . . . . . . . + 20 2 13 23 . . . . . . . . . . . + 21 2 14 19 . . . . . . . . . . . + 22 2 14 20 2 . . . . . . . . . . + 23 2 13 7 2 8 2 . . . . . . . . + 24 12 8 1 7 2 . . . . . . . . . + 25 5 1 1 1 2 8 1 5 2 . . . . . + 26 2 1 1 1 9 1 1 4 . . . . . . + 27 2 1 1 1 6 1 3 5 . . . . . . + 28 2 2 1 5 6 2 . . . . . . . . + 29 2 1 3 1 3 7 3 2 . . . . . . + 30 2 3 2 1 1 2 4 4 2 . . . . . + 31 2 2 1 1 2 3 1 8 2 . . . . . + 32 9 3 1 7 2 . . . . . . . . . + 33 12 4 1 6 2 . . . . . . . . . + 34 7 4 1 2 5 . . . . . . . . . + 35 2 6 6 5 6 . . . . . . . . . + 36 8 8 6 3 . . . . . . . . . . + 37 3 10 8 4 2 . . . . . . . . . + 38 5 11 9 5 2 . . . . . . . . . + 39 3 1 12 16 2 . . . . . . . . . + 40 3 1 12 16 . . . . . . . . . . + 41 5 2 13 21 . . . . . . . . . . + 42 6 1 3 3 1 1 . . . . . . . . + 43 5 1 3 1 3 1 1 2 1 4 1 3 1 3 + 44 5 1 3 1 3 1 4 1 4 1 3 1 3 . + 45 1 1 1 1 1 1 . . . . . . . . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/plan.lp b/resources/3rdparty/glpk-4.53/examples/plan.lp new file mode 100644 index 000000000..cab649449 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/plan.lp @@ -0,0 +1,39 @@ +\* plan.lp *\ + +Minimize + value: .03 bin1 + .08 bin2 + .17 bin3 + .12 bin4 + .15 bin5 + + .21 alum + .38 silicon + +Subject To + yield: bin1 + bin2 + bin3 + bin4 + bin5 + + alum + silicon = 2000 + + fe: .15 bin1 + .04 bin2 + .02 bin3 + .04 bin4 + .02 bin5 + + .01 alum + .03 silicon <= 60 + + cu: .03 bin1 + .05 bin2 + .08 bin3 + .02 bin4 + .06 bin5 + + .01 alum <= 100 + + mn: .02 bin1 + .04 bin2 + .01 bin3 + .02 bin4 + .02 bin5 <= 40 + + mg: .02 bin1 + .03 bin2 + .01 bin5 <= 30 + + al: .70 bin1 + .75 bin2 + .80 bin3 + .75 bin4 + .80 bin5 + + .97 alum >= 1500 + + si1: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + + .01 alum + .97 silicon >= 250 + + si2: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + + .01 alum + .97 silicon <= 300 + +Bounds + bin1 <= 200 + bin2 <= 2500 + 400 <= bin3 <= 800 + 100 <= bin4 <= 700 + bin5 <= 1500 + +End + +\* eof *\ diff --git a/resources/3rdparty/glpk-4.53/examples/plan.mod b/resources/3rdparty/glpk-4.53/examples/plan.mod new file mode 100644 index 000000000..effe8383c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/plan.mod @@ -0,0 +1,39 @@ +/* plan.mod */ + +var bin1, >= 0, <= 200; +var bin2, >= 0, <= 2500; +var bin3, >= 400, <= 800; +var bin4, >= 100, <= 700; +var bin5, >= 0, <= 1500; +var alum, >= 0; +var silicon, >= 0; + +minimize + +value: .03 * bin1 + .08 * bin2 + .17 * bin3 + .12 * bin4 + .15 * bin5 + + .21 * alum + .38 * silicon; + +subject to + +yield: bin1 + bin2 + bin3 + bin4 + bin5 + alum + silicon = 2000; + +fe: .15 * bin1 + .04 * bin2 + .02 * bin3 + .04 * bin4 + .02 * bin5 + + .01 * alum + .03 * silicon <= 60; + +cu: .03 * bin1 + .05 * bin2 + .08 * bin3 + .02 * bin4 + .06 * bin5 + + .01 * alum <= 100; + +mn: .02 * bin1 + .04 * bin2 + .01 * bin3 + .02 * bin4 + .02 * bin5 + <= 40; + +mg: .02 * bin1 + .03 * bin2 + .01 * bin5 <= 30; + +al: .70 * bin1 + .75 * bin2 + .80 * bin3 + .75 * bin4 + .80 * bin5 + + .97 * alum >= 1500; + +si: 250 <= .02 * bin1 + .06 * bin2 + .08 * bin3 + .12 * bin4 + + .02 * bin5 + .01 * alum + .97 * silicon <= 300; + +end; + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/plan.mps b/resources/3rdparty/glpk-4.53/examples/plan.mps new file mode 100644 index 000000000..b6bb09458 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/plan.mps @@ -0,0 +1,54 @@ +*000000001111111111222222222233333333334444444444555555555566 +*234567890123456789012345678901234567890123456789012345678901 +NAME PLAN +ROWS + N VALUE + E YIELD + L FE + L CU + L MN + L MG + G AL + L SI +COLUMNS + BIN1 VALUE .03000 YIELD 1.00000 + FE .15000 CU .03000 + MN .02000 MG .02000 + AL .70000 SI .02000 + BIN2 VALUE .08000 YIELD 1.00000 + FE .04000 CU .05000 + MN .04000 MG .03000 + AL .75000 SI .06000 + BIN3 VALUE .17000 YIELD 1.00000 + FE .02000 CU .08000 + MN .01000 AL .80000 + SI .08000 + BIN4 VALUE .12000 YIELD 1.00000 + FE .04000 CU .02000 + MN .02000 AL .75000 + SI .12000 + BIN5 VALUE .15000 YIELD 1.00000 + FE .02000 CU .06000 + MN .02000 MG .01000 + AL .80000 SI .02000 + ALUM VALUE .21000 YIELD 1.00000 + FE .01000 CU .01000 + AL .97000 SI .01000 + SILICON VALUE .38000 YIELD 1.00000 + FE .03000 SI .97000 +RHS + RHS1 YIELD 2000.00000 FE 60.00000 + CU 100.00000 MN 40.00000 + SI 300.00000 + MG 30.00000 AL 1500.00000 +RANGES + RNG1 SI 50.00000 +BOUNDS + UP BND1 BIN1 200.00000 + UP BIN2 2500.00000 + LO BIN3 400.00000 + UP BIN3 800.00000 + LO BIN4 100.00000 + UP BIN4 700.00000 + UP BIN5 1500.00000 +ENDATA diff --git a/resources/3rdparty/glpk-4.53/examples/prod.mod b/resources/3rdparty/glpk-4.53/examples/prod.mod new file mode 100644 index 000000000..aa793f76e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/prod.mod @@ -0,0 +1,331 @@ +# PROD, a multiperiod production model +# +# References: +# Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language +# for Mathematical Programming." Management Science 36 (1990) 519-554. + +### PRODUCTION SETS AND PARAMETERS ### + +set prd 'products'; # Members of the product group + +param pt 'production time' {prd} > 0; + + # Crew-hours to produce 1000 units + +param pc 'production cost' {prd} > 0; + + # Nominal production cost per 1000, used + # to compute inventory and shortage costs + +### TIME PERIOD SETS AND PARAMETERS ### + +param first > 0 integer; + # Index of first production period to be modeled + +param last > first integer; + + # Index of last production period to be modeled + +set time 'planning horizon' := first..last; + +### EMPLOYMENT PARAMETERS ### + +param cs 'crew size' > 0 integer; + + # Workers per crew + +param sl 'shift length' > 0; + + # Regular-time hours per shift + +param rtr 'regular time rate' > 0; + + # Wage per hour for regular-time labor + +param otr 'overtime rate' > rtr; + + # Wage per hour for overtime labor + +param iw 'initial workforce' >= 0 integer; + + # Crews employed at start of first period + +param dpp 'days per period' {time} > 0; + + # Regular working days in a production period + +param ol 'overtime limit' {time} >= 0; + + # Maximum crew-hours of overtime in a period + +param cmin 'crew minimum' {time} >= 0; + + # Lower limit on average employment in a period + +param cmax 'crew maximum' {t in time} >= cmin[t]; + + # Upper limit on average employment in a period + +param hc 'hiring cost' {time} >= 0; + + # Penalty cost of hiring a crew + +param lc 'layoff cost' {time} >= 0; + + # Penalty cost of laying off a crew + +### DEMAND PARAMETERS ### + +param dem 'demand' {prd,first..last+1} >= 0; + + # Requirements (in 1000s) + # to be met from current production and inventory + +param pro 'promoted' {prd,first..last+1} logical; + + # true if product will be the subject + # of a special promotion in the period + +### INVENTORY AND SHORTAGE PARAMETERS ### + +param rir 'regular inventory ratio' >= 0; + + # Proportion of non-promoted demand + # that must be in inventory the previous period + +param pir 'promotional inventory ratio' >= 0; + + # Proportion of promoted demand + # that must be in inventory the previous period + +param life 'inventory lifetime' > 0 integer; + + # Upper limit on number of periods that + # any product may sit in inventory + +param cri 'inventory cost ratio' {prd} > 0; + + # Inventory cost per 1000 units is + # cri times nominal production cost + +param crs 'shortage cost ratio' {prd} > 0; + + # Shortage cost per 1000 units is + # crs times nominal production cost + +param iinv 'initial inventory' {prd} >= 0; + + # Inventory at start of first period; age unknown + +param iil 'initial inventory left' {p in prd, t in time} + := iinv[p] less sum {v in first..t} dem[p,v]; + + # Initial inventory still available for allocation + # at end of period t + +param minv 'minimum inventory' {p in prd, t in time} + := dem[p,t+1] * (if pro[p,t+1] then pir else rir); + + # Lower limit on inventory at end of period t + +### VARIABLES ### + +var Crews{first-1..last} >= 0; + + # Average number of crews employed in each period + +var Hire{time} >= 0; # Crews hired from previous to current period + +var Layoff{time} >= 0; # Crews laid off from previous to current period + +var Rprd 'regular production' {prd,time} >= 0; + + # Production using regular-time labor, in 1000s + +var Oprd 'overtime production' {prd,time} >= 0; + + # Production using overtime labor, in 1000s + +var Inv 'inventory' {prd,time,1..life} >= 0; + + # Inv[p,t,a] is the amount of product p that is + # a periods old -- produced in period (t+1)-a -- + # and still in storage at the end of period t + +var Short 'shortage' {prd,time} >= 0; + + # Accumulated unsatisfied demand at the end of period t + +### OBJECTIVE ### + +minimize cost: + + sum {t in time} rtr * sl * dpp[t] * cs * Crews[t] + + sum {t in time} hc[t] * Hire[t] + + sum {t in time} lc[t] * Layoff[t] + + sum {t in time, p in prd} otr * cs * pt[p] * Oprd[p,t] + + sum {t in time, p in prd, a in 1..life} cri[p] * pc[p] * Inv[p,t,a] + + sum {t in time, p in prd} crs[p] * pc[p] * Short[p,t]; + + # Full regular wages for all crews employed, plus + # penalties for hiring and layoffs, plus + # wages for any overtime worked, plus + # inventory and shortage costs + + # (All other production costs are assumed + # to depend on initial inventory and on demands, + # and so are not included explicitly.) + +### CONSTRAINTS ### + +rlim 'regular-time limit' {t in time}: + + sum {p in prd} pt[p] * Rprd[p,t] <= sl * dpp[t] * Crews[t]; + + # Hours needed to accomplish all regular-time + # production in a period must not exceed + # hours available on all shifts + +olim 'overtime limit' {t in time}: + + sum {p in prd} pt[p] * Oprd[p,t] <= ol[t]; + + # Hours needed to accomplish all overtime + # production in a period must not exceed + # the specified overtime limit + +empl0 'initial crew level': Crews[first-1] = iw; + + # Use given initial workforce + +empl 'crew levels' {t in time}: Crews[t] = Crews[t-1] + Hire[t] - Layoff[t]; + + # Workforce changes by hiring or layoffs + +emplbnd 'crew limits' {t in time}: cmin[t] <= Crews[t] <= cmax[t]; + + # Workforce must remain within specified bounds + +dreq1 'first demand requirement' {p in prd}: + + Rprd[p,first] + Oprd[p,first] + Short[p,first] + - Inv[p,first,1] = dem[p,first] less iinv[p]; + +dreq 'demand requirements' {p in prd, t in first+1..last}: + + Rprd[p,t] + Oprd[p,t] + Short[p,t] - Short[p,t-1] + + sum {a in 1..life} (Inv[p,t-1,a] - Inv[p,t,a]) + = dem[p,t] less iil[p,t-1]; + + # Production plus increase in shortage plus + # decrease in inventory must equal demand + +ireq 'inventory requirements' {p in prd, t in time}: + + sum {a in 1..life} Inv[p,t,a] + iil[p,t] >= minv[p,t]; + + # Inventory in storage at end of period t + # must meet specified minimum + +izero 'impossible inventories' {p in prd, v in 1..life-1, a in v+1..life}: + + Inv[p,first+v-1,a] = 0; + + # In the vth period (starting from first) + # no inventory may be more than v periods old + # (initial inventories are handled separately) + +ilim1 'new-inventory limits' {p in prd, t in time}: + + Inv[p,t,1] <= Rprd[p,t] + Oprd[p,t]; + + # New inventory cannot exceed + # production in the most recent period + +ilim 'inventory limits' {p in prd, t in first+1..last, a in 2..life}: + + Inv[p,t,a] <= Inv[p,t-1,a-1]; + + # Inventory left from period (t+1)-p + # can only decrease as time goes on + +### DATA ### + +data; + +set prd := 18REG 24REG 24PRO ; + +param first := 1 ; +param last := 13 ; +param life := 2 ; + +param cs := 18 ; +param sl := 8 ; +param iw := 8 ; + +param rtr := 16.00 ; +param otr := 43.85 ; +param rir := 0.75 ; +param pir := 0.80 ; + +param : pt pc cri crs iinv := + + 18REG 1.194 2304. 0.015 1.100 82.0 + 24REG 1.509 2920. 0.015 1.100 792.2 + 24PRO 1.509 2910. 0.015 1.100 0.0 ; + +param : dpp ol cmin cmax hc lc := + + 1 19.5 96.0 0.0 8.0 7500 7500 + 2 19.0 96.0 0.0 8.0 7500 7500 + 3 20.0 96.0 0.0 8.0 7500 7500 + 4 19.0 96.0 0.0 8.0 7500 7500 + 5 19.5 96.0 0.0 8.0 15000 15000 + 6 19.0 96.0 0.0 8.0 15000 15000 + 7 19.0 96.0 0.0 8.0 15000 15000 + 8 20.0 96.0 0.0 8.0 15000 15000 + 9 19.0 96.0 0.0 8.0 15000 15000 + 10 20.0 96.0 0.0 8.0 15000 15000 + 11 20.0 96.0 0.0 8.0 7500 7500 + 12 18.0 96.0 0.0 8.0 7500 7500 + 13 18.0 96.0 0.0 8.0 7500 7500 ; + +param dem (tr) : + + 18REG 24REG 24PRO := + + 1 63.8 1212.0 0.0 + 2 76.0 306.2 0.0 + 3 88.4 319.0 0.0 + 4 913.8 208.4 0.0 + 5 115.0 298.0 0.0 + 6 133.8 328.2 0.0 + 7 79.6 959.6 0.0 + 8 111.0 257.6 0.0 + 9 121.6 335.6 0.0 + 10 470.0 118.0 1102.0 + 11 78.4 284.8 0.0 + 12 99.4 970.0 0.0 + 13 140.4 343.8 0.0 + 14 63.8 1212.0 0.0 ; + +param pro (tr) : + + 18REG 24REG 24PRO := + + 1 0 1 0 + 2 0 0 0 + 3 0 0 0 + 4 1 0 0 + 5 0 0 0 + 6 0 0 0 + 7 0 1 0 + 8 0 0 0 + 9 0 0 0 + 10 1 0 1 + 11 0 0 0 + 12 0 0 0 + 13 0 1 0 + 14 0 1 0 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/qfit.mod b/resources/3rdparty/glpk-4.53/examples/qfit.mod new file mode 100644 index 000000000..f168c4b52 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/qfit.mod @@ -0,0 +1,49 @@ +/*Quadratic Curve Fitting Solution + + Find a plausable quadratic fit to a sample of points + + Nigel_Galloway@operamail.com + February 1st., 2009 +*/ +set Sample; +param Sx {z in Sample}; +param Sy {z in Sample}; + +var a; +var b; +var c; + +equalz1 :sum{z in Sample} a*Sx[z]*Sx[z]*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z]*Sx[z]*Sx[z] + sum{z in Sample} c*Sx[z]*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]*Sx[z]; +equalz2 :sum{z in Sample} a*Sx[z]*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z]*Sx[z] + sum{z in Sample} c*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]; +equalz3 :sum{z in Sample} a*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z] + sum{z in Sample} c = sum{z in Sample} Sy[z]; + +solve; + +printf "\nbest quadratic fit is:\n\ty = %f %s %fx %s %fx^2\n\n", c, if b < 0 then "-" else "+", abs(b), if a < 0 then "-" else "+", abs(a); + +data; + +param: +Sample: Sx Sy := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/queens.mod b/resources/3rdparty/glpk-4.53/examples/queens.mod new file mode 100644 index 000000000..3f446ce4c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/queens.mod @@ -0,0 +1,41 @@ +/* QUEENS, a classic combinatorial optimization problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Queens Problem is to place as many queens as possible on the 8x8 + (or more generally, nxn) chess board in a way that they do not fight + each other. This problem is probably as old as the chess game itself, + and thus its origin is not known, but it is known that Gauss studied + this problem. */ + +param n, integer, > 0, default 8; +/* size of the chess board */ + +var x{1..n, 1..n}, binary; +/* x[i,j] = 1 means that a queen is placed in square [i,j] */ + +s.t. a{i in 1..n}: sum{j in 1..n} x[i,j] <= 1; +/* at most one queen can be placed in each row */ + +s.t. b{j in 1..n}: sum{i in 1..n} x[i,j] <= 1; +/* at most one queen can be placed in each column */ + +s.t. c{k in 2-n..n-2}: sum{i in 1..n, j in 1..n: i-j == k} x[i,j] <= 1; +/* at most one queen can be placed in each "\"-diagonal */ + +s.t. d{k in 3..n+n-1}: sum{i in 1..n, j in 1..n: i+j == k} x[i,j] <= 1; +/* at most one queen can be placed in each "/"-diagonal */ + +maximize obj: sum{i in 1..n, j in 1..n} x[i,j]; +/* objective is to place as many queens as possible */ + +/* solve the problem */ +solve; + +/* and print its optimal solution */ +for {i in 1..n} +{ for {j in 1..n} printf " %s", if x[i,j] then "Q" else "."; + printf("\n"); +} + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/samp1.mps b/resources/3rdparty/glpk-4.53/examples/samp1.mps new file mode 100644 index 000000000..dd60d1843 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/samp1.mps @@ -0,0 +1,29 @@ +NAME SAMP1 +ROWS + N Z + G R1 + G R2 + G R3 +COLUMNS + X1 R1 2.0 R2 1.0 + X1 R3 5.0 Z 3.0 + MARK0001 'MARKER' 'INTORG' + X2 R1 -1.0 R2 -1.0 + X2 R3 3.0 Z 7.0 + X3 R1 1.0 R2 -6.0 + X3 Z -1.0 + MARK0002 'MARKER' 'INTEND' + X4 R1 -1.0 R2 4.0 + X4 R3 1.0 Z 1.0 +RHS + RHS1 R1 1.0 + RHS1 R2 8.0 + RHS1 R3 5.0 +BOUNDS + UP BND1 X1 4.0 + LO BND1 X2 2.0 + UP BND1 X2 5.0 + UP BND1 X3 1.0 + LO BND1 X4 3.0 + UP BND1 X4 8.0 +ENDATA diff --git a/resources/3rdparty/glpk-4.53/examples/samp2.mps b/resources/3rdparty/glpk-4.53/examples/samp2.mps new file mode 100644 index 000000000..d2da1a31d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/samp2.mps @@ -0,0 +1,27 @@ +NAME SAMP2 +ROWS + N Z + G R1 + G R2 + G R3 +COLUMNS + X1 R1 2.0 R2 1.0 + X1 R3 5.0 Z 3.0 + X2 R1 -1.0 R2 -1.0 + X2 R3 3.0 Z 7.0 + X3 R1 1.0 R2 -6.0 + X3 Z -1.0 + X4 R1 -1.0 R2 4.0 + X4 R3 1.0 Z 1.0 +RHS + RHS1 R1 1.0 + RHS1 R2 8.0 + RHS1 R3 5.0 +BOUNDS + UP BND1 X1 4.0 + LO BND1 X2 2.0 + UI BND1 X2 5.0 + BV BND1 X3 + LO BND1 X4 3.0 + UP BND1 X4 8.0 +ENDATA diff --git a/resources/3rdparty/glpk-4.53/examples/sample.asn b/resources/3rdparty/glpk-4.53/examples/sample.asn new file mode 100644 index 000000000..edb0aafd9 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sample.asn @@ -0,0 +1,40 @@ +c sample.asn +c +c This is an example of the assignment problem data +c in DIMACS format. +c +p asn 17 22 +c +n 1 +n 2 +n 3 +n 4 +n 5 +n 6 +n 7 +n 8 +c +a 1 9 13 +a 1 10 21 +a 1 12 20 +a 2 10 12 +a 2 12 8 +a 2 13 26 +a 3 11 22 +a 3 13 11 +a 4 9 12 +a 4 12 36 +a 4 14 25 +a 5 11 41 +a 5 12 40 +a 5 13 11 +a 5 14 4 +a 5 15 8 +a 5 16 35 +a 5 17 32 +a 6 9 13 +a 7 10 19 +a 8 10 39 +a 8 11 15 +c +c eof diff --git a/resources/3rdparty/glpk-4.53/examples/sample.c b/resources/3rdparty/glpk-4.53/examples/sample.c new file mode 100644 index 000000000..468a6a354 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sample.c @@ -0,0 +1,52 @@ +/* sample.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *lp; + int ia[1+1000], ja[1+1000]; + double ar[1+1000], z, x1, x2, x3; +s1: lp = glp_create_prob(); +s2: glp_set_prob_name(lp, "sample"); +s3: glp_set_obj_dir(lp, GLP_MAX); +s4: glp_add_rows(lp, 3); +s5: glp_set_row_name(lp, 1, "p"); +s6: glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 100.0); +s7: glp_set_row_name(lp, 2, "q"); +s8: glp_set_row_bnds(lp, 2, GLP_UP, 0.0, 600.0); +s9: glp_set_row_name(lp, 3, "r"); +s10: glp_set_row_bnds(lp, 3, GLP_UP, 0.0, 300.0); +s11: glp_add_cols(lp, 3); +s12: glp_set_col_name(lp, 1, "x1"); +s13: glp_set_col_bnds(lp, 1, GLP_LO, 0.0, 0.0); +s14: glp_set_obj_coef(lp, 1, 10.0); +s15: glp_set_col_name(lp, 2, "x2"); +s16: glp_set_col_bnds(lp, 2, GLP_LO, 0.0, 0.0); +s17: glp_set_obj_coef(lp, 2, 6.0); +s18: glp_set_col_name(lp, 3, "x3"); +s19: glp_set_col_bnds(lp, 3, GLP_LO, 0.0, 0.0); +s20: glp_set_obj_coef(lp, 3, 4.0); +s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */ +s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2] = 1 */ +s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3] = 1 */ +s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */ +s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1] = 2 */ +s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2] = 4 */ +s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2] = 2 */ +s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3] = 5 */ +s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3] = 6 */ +s30: glp_load_matrix(lp, 9, ia, ja, ar); +s31: glp_simplex(lp, NULL); +s32: z = glp_get_obj_val(lp); +s33: x1 = glp_get_col_prim(lp, 1); +s34: x2 = glp_get_col_prim(lp, 2); +s35: x3 = glp_get_col_prim(lp, 3); +s36: printf("\nz = %g; x1 = %g; x2 = %g; x3 = %g\n", + z, x1, x2, x3); +s37: glp_delete_prob(lp); + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/sample.clq b/resources/3rdparty/glpk-4.53/examples/sample.clq new file mode 100644 index 000000000..741f71272 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sample.clq @@ -0,0 +1,30 @@ +c sample.clq +c +c This is an example of the Maximum Weight Clique +c Problem in DIMACS clique/coloring format. +c +p edge 8 16 +n 1 3 +n 2 4 +n 3 8 +n 5 5 +n 6 2 +n 8 3 +e 1 4 +e 1 5 +e 1 6 +e 1 8 +e 2 3 +e 2 6 +e 2 7 +e 2 8 +e 3 4 +e 3 6 +e 3 7 +e 4 5 +e 4 8 +e 5 7 +e 5 8 +e 6 7 +c +c eof diff --git a/resources/3rdparty/glpk-4.53/examples/sample.cnf b/resources/3rdparty/glpk-4.53/examples/sample.cnf new file mode 100644 index 000000000..508f15046 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sample.cnf @@ -0,0 +1,12 @@ +c sample.cnf +c +c This is an example of the CNF-SAT problem data +c in DIMACS format. +c +p cnf 4 3 +1 2 0 +-4 3 +-2 0 +-1 4 0 +c +c eof diff --git a/resources/3rdparty/glpk-4.53/examples/sample.col b/resources/3rdparty/glpk-4.53/examples/sample.col new file mode 100644 index 000000000..132f6e578 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sample.col @@ -0,0 +1,30 @@ +c sample.col +c +c This is an example of the vertex coloring problem data +c in DIMACS format. +c +p edge 10 21 +c +e 1 2 +e 1 6 +e 1 7 +e 1 10 +e 2 3 +e 2 7 +e 2 8 +e 3 4 +e 3 8 +e 4 5 +e 4 8 +e 4 9 +e 5 6 +e 5 9 +e 5 10 +e 6 10 +e 7 8 +e 7 10 +e 8 9 +e 8 10 +e 9 10 +c +c eof diff --git a/resources/3rdparty/glpk-4.53/examples/sample.max b/resources/3rdparty/glpk-4.53/examples/sample.max new file mode 100644 index 000000000..6b8042297 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sample.max @@ -0,0 +1,26 @@ +c sample.max +c +c This is an example of the maximum flow problem data +c in DIMACS format. +c +p max 9 14 +c +n 1 s +n 9 t +c +a 1 2 14 +a 1 4 23 +a 2 3 10 +a 2 4 9 +a 3 5 12 +a 3 8 18 +a 4 5 26 +a 5 2 11 +a 5 6 25 +a 5 7 4 +a 6 7 7 +a 6 8 8 +a 7 9 15 +a 8 9 20 +c +c eof diff --git a/resources/3rdparty/glpk-4.53/examples/sample.min b/resources/3rdparty/glpk-4.53/examples/sample.min new file mode 100644 index 000000000..5ebf58b1f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sample.min @@ -0,0 +1,26 @@ +c sample.min +c +c This is an example of the minimum cost flow problem data +c in DIMACS format. +c +p min 9 14 +c +n 1 20 +n 9 -20 +c +a 1 2 0 14 0 +a 1 4 0 23 0 +a 2 3 0 10 2 +a 2 4 0 9 3 +a 3 5 2 12 1 +a 3 8 0 18 0 +a 4 5 0 26 0 +a 5 2 0 11 1 +a 5 6 0 25 5 +a 5 7 0 4 7 +a 6 7 0 7 0 +a 6 8 4 8 0 +a 7 9 0 15 3 +a 8 9 0 20 9 +c +c eof diff --git a/resources/3rdparty/glpk-4.53/examples/sat.mod b/resources/3rdparty/glpk-4.53/examples/sat.mod new file mode 100644 index 000000000..84ba95249 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sat.mod @@ -0,0 +1,201 @@ +/* SAT, Satisfiability Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +param m, integer, > 0; +/* number of clauses */ + +param n, integer, > 0; +/* number of variables */ + +set C{1..m}; +/* clauses; each clause C[i], i = 1, ..., m, is disjunction of some + variables or their negations; in the data section each clause is + coded as a set of indices of corresponding variables, where negative + indices mean negation; for example, the clause (x3 or not x7 or x11) + is coded as the set { 3, -7, 11 } */ + +var x{1..n}, binary; +/* main variables */ + +/* To solve the satisfiability problem means to determine all variables + x[j] such that conjunction of all clauses C[1] and ... and C[m] takes + on the value true, i.e. all clauses are satisfied. + + Let the clause C[i] be (t or t' or ... or t''), where t, t', ..., t'' + are either variables or their negations. The condition of satisfying + C[i] can be most naturally written as: + + t + t' + ... + t'' >= 1, (1) + + where t, t', t'' have to be replaced by either x[j] or (1 - x[j]). + The formulation (1) leads to the mip problem with no objective, i.e. + to a feasibility problem. + + Another, more practical way is to write the condition for C[i] as: + + t + t' + ... + t'' + y[i] >= 1, (2) + + where y[i] is an auxiliary binary variable, and minimize the sum of + y[i]. If the sum is zero, all y[i] are also zero, and therefore all + clauses are satisfied. If the sum is minimal but non-zero, its value + shows the number of clauses which cannot be satisfied. */ + +var y{1..m}, binary, >= 0; +/* auxiliary variables */ + +s.t. c{i in 1..m}: + sum{j in C[i]} (if j > 0 then x[j] else (1 - x[-j])) + y[i] >= 1; +/* the condition (2) */ + +minimize unsat: sum{i in 1..m} y[i]; +/* number of unsatisfied clauses */ + +data; + +/* These data correspond to the instance hole6 (pigeon hole problem for + 6 holes) from SATLIB, the Satisfiability Library, which is part of + the collection at the Forschungsinstitut fuer anwendungsorientierte + Wissensverarbeitung in Ulm Germany */ + +/* The optimal solution is 1 (one clause cannot be satisfied) */ + +param m := 133; + +param n := 42; + +set C[1] := -1 -7; +set C[2] := -1 -13; +set C[3] := -1 -19; +set C[4] := -1 -25; +set C[5] := -1 -31; +set C[6] := -1 -37; +set C[7] := -7 -13; +set C[8] := -7 -19; +set C[9] := -7 -25; +set C[10] := -7 -31; +set C[11] := -7 -37; +set C[12] := -13 -19; +set C[13] := -13 -25; +set C[14] := -13 -31; +set C[15] := -13 -37; +set C[16] := -19 -25; +set C[17] := -19 -31; +set C[18] := -19 -37; +set C[19] := -25 -31; +set C[20] := -25 -37; +set C[21] := -31 -37; +set C[22] := -2 -8; +set C[23] := -2 -14; +set C[24] := -2 -20; +set C[25] := -2 -26; +set C[26] := -2 -32; +set C[27] := -2 -38; +set C[28] := -8 -14; +set C[29] := -8 -20; +set C[30] := -8 -26; +set C[31] := -8 -32; +set C[32] := -8 -38; +set C[33] := -14 -20; +set C[34] := -14 -26; +set C[35] := -14 -32; +set C[36] := -14 -38; +set C[37] := -20 -26; +set C[38] := -20 -32; +set C[39] := -20 -38; +set C[40] := -26 -32; +set C[41] := -26 -38; +set C[42] := -32 -38; +set C[43] := -3 -9; +set C[44] := -3 -15; +set C[45] := -3 -21; +set C[46] := -3 -27; +set C[47] := -3 -33; +set C[48] := -3 -39; +set C[49] := -9 -15; +set C[50] := -9 -21; +set C[51] := -9 -27; +set C[52] := -9 -33; +set C[53] := -9 -39; +set C[54] := -15 -21; +set C[55] := -15 -27; +set C[56] := -15 -33; +set C[57] := -15 -39; +set C[58] := -21 -27; +set C[59] := -21 -33; +set C[60] := -21 -39; +set C[61] := -27 -33; +set C[62] := -27 -39; +set C[63] := -33 -39; +set C[64] := -4 -10; +set C[65] := -4 -16; +set C[66] := -4 -22; +set C[67] := -4 -28; +set C[68] := -4 -34; +set C[69] := -4 -40; +set C[70] := -10 -16; +set C[71] := -10 -22; +set C[72] := -10 -28; +set C[73] := -10 -34; +set C[74] := -10 -40; +set C[75] := -16 -22; +set C[76] := -16 -28; +set C[77] := -16 -34; +set C[78] := -16 -40; +set C[79] := -22 -28; +set C[80] := -22 -34; +set C[81] := -22 -40; +set C[82] := -28 -34; +set C[83] := -28 -40; +set C[84] := -34 -40; +set C[85] := -5 -11; +set C[86] := -5 -17; +set C[87] := -5 -23; +set C[88] := -5 -29; +set C[89] := -5 -35; +set C[90] := -5 -41; +set C[91] := -11 -17; +set C[92] := -11 -23; +set C[93] := -11 -29; +set C[94] := -11 -35; +set C[95] := -11 -41; +set C[96] := -17 -23; +set C[97] := -17 -29; +set C[98] := -17 -35; +set C[99] := -17 -41; +set C[100] := -23 -29; +set C[101] := -23 -35; +set C[102] := -23 -41; +set C[103] := -29 -35; +set C[104] := -29 -41; +set C[105] := -35 -41; +set C[106] := -6 -12; +set C[107] := -6 -18; +set C[108] := -6 -24; +set C[109] := -6 -30; +set C[110] := -6 -36; +set C[111] := -6 -42; +set C[112] := -12 -18; +set C[113] := -12 -24; +set C[114] := -12 -30; +set C[115] := -12 -36; +set C[116] := -12 -42; +set C[117] := -18 -24; +set C[118] := -18 -30; +set C[119] := -18 -36; +set C[120] := -18 -42; +set C[121] := -24 -30; +set C[122] := -24 -36; +set C[123] := -24 -42; +set C[124] := -30 -36; +set C[125] := -30 -42; +set C[126] := -36 -42; +set C[127] := 6 5 4 3 2 1; +set C[128] := 12 11 10 9 8 7; +set C[129] := 18 17 16 15 14 13; +set C[130] := 24 23 22 21 20 19; +set C[131] := 30 29 28 27 26 25; +set C[132] := 36 35 34 33 32 31; +set C[133] := 42 41 40 39 38 37; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/shiftcover.mod b/resources/3rdparty/glpk-4.53/examples/shiftcover.mod new file mode 100644 index 000000000..1e036c8a2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/shiftcover.mod @@ -0,0 +1,244 @@ +/* File: shiftcover.mod */ + +/* WORKFORCE SHIFT COVERAGE assignment problem */ + +/* Written by Larry D'Agostino <larrydag -at- sbcglobal -dot- com> + + Maximize Productivity with Industrial Engineer and Operations Research Tools + http://industrialengineertools.blogspot.com + + +/* The WORKFORCE SHIFT COVERAGE is an assigment problem that determines + the schedule of crew given available time and shifts. + + The objective is to cover the available time given hourly demand with the minimum + number of crew members. + + This is a set covering problem that is very common among finding crew + and shift allocations. Notice in the data section the workforce shift allocation + per day of the week.*/ + + +/* ----- Model PARAMTERS and SETS -----*/ + +param numhrs; +/* number of hours of operations in a given day */ + +param dys; +/* number of days in a week */ + +set S; +/* set of crew shifts */ + +set H := 1..numhrs; +/* set of hours of a day*/ + +set D; +/* set of days of a week*/ + +param dmnd{h in H, d in D}; +/* demand for crew members given h hour and d day */ + +param shifts{d in D, h in H, s in S}; +/* shifts to assign to crew members given d day, h hour, and s shift schedule + +/*----- Model VARIABLES -----*/ + +var crew{s in S}, integer, >=0; +/* number of crew assigned to shift S */ + + +/*----- Model CONSTRAINTS -----*/ + +s.t. Coverage{h in H, d in D}: sum{s in S} crew[s]*shifts[d,h,s] >= dmnd[h,d]; +/* number of crew to cover with a shift given hourly demand and day */ + + +/*----- Model OBJECTIVE -----*/ + +minimize obj: sum{s in S} crew[s]; +/* minimize number of crew to cover demand*/ + +solve; +display crew; + +printf "\n"; +printf "Total Crew: %3d\n\n", sum{s in S} crew[s]; + + + +printf "\n\n"; +printf "Weekly Crew Schedule\n\n"; +printf "Hour "; +printf{d in D} " %s ", d; +printf "\n"; +for {h in H} { + printf " %2s ",h; + printf{d in D} " %3d ", sum{s in S} crew[s]*shifts[d,h,s]; + printf "\n"; +} +printf"\n"; + + + +data; + +param numhrs := 16; + +set D := SUN, MON, TUE, WED, THU, FRI, SAT; + +set S := Sh1, Sh2, Sh3, Sh4, Sh5, Sh6, Sh7, Sh8, Sh9; + +param dmnd : SUN MON TUE WED THU FRI SAT := +1 0 3 3 4 3 2 0 +2 0 14 14 16 14 12 12 +3 0 24 24 27 24 20 15 +4 0 28 28 32 28 23 15 +5 0 33 33 37 33 24 16 +6 0 34 34 38 34 24 15 +7 0 35 35 39 35 25 11 +8 0 35 35 40 35 27 0 +9 0 34 34 39 34 25 0 +10 0 31 31 35 31 24 0 +11 2 24 24 27 24 25 0 +12 3 19 19 21 19 21 0 +13 2 24 24 27 24 13 0 +14 2 16 16 18 16 0 0 +15 0 7 7 7 7 0 0 +16 0 5 5 5 5 0 0; + + +param shifts := +['SUN',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 0 0 0 0 0 0 0 0 0 +2 0 0 0 0 0 0 0 0 0 +3 0 0 0 0 0 0 0 0 0 +4 0 0 0 0 0 0 0 0 0 +5 0 0 0 0 0 0 0 0 0 +6 0 0 0 0 0 0 0 0 0 +7 0 0 0 0 0 0 0 0 0 +8 0 0 0 0 0 0 0 0 0 +9 0 0 0 0 0 0 0 0 0 +10 0 0 0 0 0 0 0 0 0 +11 0 0 0 0 0 0 0 0 1 +12 0 0 0 0 0 0 0 0 1 +13 0 0 0 0 0 0 0 0 1 +14 0 0 0 0 0 0 0 0 1 +15 0 0 0 0 0 0 0 0 0 +16 0 0 0 0 0 0 0 0 0 + + +['MON',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 1 0 0 0 0 0 0 0 0 +2 1 1 0 0 0 0 0 0 0 +3 1 1 1 0 0 0 0 0 0 +4 1 1 1 1 0 0 0 0 0 +5 0 1 1 1 1 0 0 0 0 +6 1 0 1 1 1 1 0 0 1 +7 1 1 0 1 1 1 1 0 1 +8 1 1 1 0 1 1 1 1 1 +9 1 1 1 1 0 1 1 1 1 +10 0 1 1 1 1 0 1 1 1 +11 0 0 1 1 1 1 0 1 0 +12 0 0 0 1 1 1 1 0 1 +13 0 0 0 0 1 1 1 1 1 +14 0 0 0 0 0 1 1 1 1 +15 0 0 0 0 0 0 1 1 1 +16 0 0 0 0 0 0 0 1 1 + +['TUE',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 1 0 0 0 0 0 0 0 0 +2 1 1 0 0 0 0 0 0 0 +3 1 1 1 0 0 0 0 0 0 +4 1 1 1 1 0 0 0 0 0 +5 0 1 1 1 1 0 0 0 0 +6 1 0 1 1 1 1 0 0 1 +7 1 1 0 1 1 1 1 0 1 +8 1 1 1 0 1 1 1 1 1 +9 1 1 1 1 0 1 1 1 1 +10 0 1 1 1 1 0 1 1 1 +11 0 0 1 1 1 1 0 1 0 +12 0 0 0 1 1 1 1 0 1 +13 0 0 0 0 1 1 1 1 1 +14 0 0 0 0 0 1 1 1 1 +15 0 0 0 0 0 0 1 1 1 +16 0 0 0 0 0 0 0 1 1 + +['WED',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 1 0 0 0 0 0 0 0 0 +2 1 1 0 0 0 0 0 0 0 +3 1 1 1 0 0 0 0 0 0 +4 1 1 1 1 0 0 0 0 0 +5 0 1 1 1 1 0 0 0 0 +6 1 0 1 1 1 1 0 0 1 +7 1 1 0 1 1 1 1 0 1 +8 1 1 1 0 1 1 1 1 1 +9 1 1 1 1 0 1 1 1 1 +10 0 1 1 1 1 0 1 1 1 +11 0 0 1 1 1 1 0 1 0 +12 0 0 0 1 1 1 1 0 1 +13 0 0 0 0 1 1 1 1 1 +14 0 0 0 0 0 1 1 1 1 +15 0 0 0 0 0 0 1 1 1 +16 0 0 0 0 0 0 0 1 1 + +['THU',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 1 0 0 0 0 0 0 0 0 +2 1 1 0 0 0 0 0 0 0 +3 1 1 1 0 0 0 0 0 0 +4 1 1 1 1 0 0 0 0 0 +5 0 1 1 1 1 0 0 0 0 +6 1 0 1 1 1 1 0 0 0 +7 1 1 0 1 1 1 1 0 0 +8 1 1 1 0 1 1 1 1 0 +9 1 1 1 1 0 1 1 1 0 +10 0 1 1 1 1 0 1 1 0 +11 0 0 1 1 1 1 0 1 0 +12 0 0 0 1 1 1 1 0 0 +13 0 0 0 0 1 1 1 1 0 +14 0 0 0 0 0 1 1 1 0 +15 0 0 0 0 0 0 1 1 0 +16 0 0 0 0 0 0 0 1 0 + +['FRI',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 1 0 0 0 0 0 0 0 0 +2 1 1 0 0 0 0 0 0 0 +3 1 1 1 0 0 0 0 0 0 +4 1 1 1 1 0 0 0 0 0 +5 0 1 1 1 1 0 0 0 0 +6 1 0 1 1 1 1 0 0 0 +7 1 1 0 1 1 1 1 0 0 +8 1 1 1 0 1 1 1 1 0 +9 1 1 1 1 0 1 1 1 0 +10 0 1 1 1 1 0 1 1 0 +11 0 0 1 1 1 1 0 1 0 +12 0 0 0 1 1 1 1 0 0 +13 0 0 0 0 1 1 1 1 0 +14 0 0 0 0 0 1 1 1 0 +15 0 0 0 0 0 0 1 1 0 +16 0 0 0 0 0 0 0 1 0 + +['SAT',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 0 0 0 0 0 0 0 0 0 +2 0 0 0 0 0 0 0 0 1 +3 0 0 0 0 0 0 0 0 1 +4 0 0 0 0 0 0 0 0 1 +5 0 0 0 0 0 0 0 0 1 +6 0 0 0 0 0 0 0 0 1 +7 0 0 0 0 0 0 0 0 1 +8 0 0 0 0 0 0 0 0 0 +9 0 0 0 0 0 0 0 0 0 +10 0 0 0 0 0 0 0 0 0 +11 0 0 0 0 0 0 0 0 0 +12 0 0 0 0 0 0 0 0 0 +13 0 0 0 0 0 0 0 0 0 +14 0 0 0 0 0 0 0 0 0 +15 0 0 0 0 0 0 0 0 0 +16 0 0 0 0 0 0 0 0 0; diff --git a/resources/3rdparty/glpk-4.53/examples/shikaku.mod b/resources/3rdparty/glpk-4.53/examples/shikaku.mod new file mode 100644 index 000000000..19cf5ddbe --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/shikaku.mod @@ -0,0 +1,107 @@ +/* A solver for the Japanese number-puzzle Shikaku + * http://en.wikipedia.org/wiki/Shikaku + * + * Sebastian Nowozin <nowozin@gmail.com>, 27th January 2009 + */ + +param ndim := 10; +set rows := 1..ndim; +set rows1 := 1..(ndim+1); +set cols := 1..ndim; +set cols1 := 1..(ndim+1); +param givens{rows, cols}, integer, >= 0, default 0; + +/* Set of vertices as (row,col) coordinates */ +set V := { (i,j) in { rows, cols }: givens[i,j] != 0 }; + +/* Set of all feasible boxes of the right size: only this boxes are possible. + * The box contains (i,j) and ranges from (k,l) to (m,n) + */ +set B := { (i,j,k,l,m,n) in { V, rows, cols, rows1, cols1 }: + i >= k and i < m and j >= l and j < n and /* Contains (i,j) */ + ((m-k)*(n-l)) = givens[i,j] and /* Right size */ + card({ (s,t) in V: s >= k and s < m and t >= l and t < n }) = 1 + /* Contains only (i,j), no other number */ +}; + +var x{B}, binary; + +/* Cover each square exactly once */ +s.t. cover_once{ (s,t) in { rows, cols } }: + sum{(i,j,k,l,m,n) in B: s >= k and s < m and t >= l and t < n} + x[i,j,k,l,m,n] = 1; + +minimize cost: 0; + +solve; + +/* Output solution graphically */ +printf "\nSolution:\n"; +for { row in rows1 } { + for { col in cols1 } { + printf{0..0: card({(i,j,k,l,m,n) in B: + col >= l and col <= n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) > 0 and + card({(i,j,k,l,m,n) in B: + row >= k and row <= m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) > 0} "+"; + printf{0..0: card({(i,j,k,l,m,n) in B: + col >= l and col <= n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) = 0 and + card({(i,j,k,l,m,n) in B: + row >= k and row <= m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) > 0} "|"; + printf{0..0: card({(i,j,k,l,m,n) in B: + row >= k and row <= m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) = 0 and + card({(i,j,k,l,m,n) in B: + col >= l and col <= n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) > 0} "-"; + printf{0..0: card({(i,j,k,l,m,n) in B: + row >= k and row <= m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) = 0 and + card({(i,j,k,l,m,n) in B: + col >= l and col <= n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) = 0} " "; + + printf{0..0: card({(i,j,k,l,m,n) in B: + col >= l and col < n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) > 0} "---"; + printf{0..0: card({(i,j,k,l,m,n) in B: + col >= l and col < n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) = 0} " "; + } + printf "\n"; + + for { (col,p) in { cols, 1 }: card({ s in rows: s = row }) = 1 } { + printf{0..0: card({(i,j,k,l,m,n) in B: + row >= k and row < m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) > 0} "|"; + printf{0..0: card({(i,j,k,l,m,n) in B: + row >= k and row < m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) = 0} " "; + printf{0..0: card({ (i,j) in V: i = row and j = col}) > 0} " %2d", givens[row,col]; + printf{0..0: card({ (i,j) in V: i = row and j = col}) = 0} " ."; + } + printf{0..0: card({ r in rows: r = row }) = 1} "|\n"; +} + +data; + +/* This Shikaku is from + * http://www.emn.fr/x-info/sdemasse/gccat/KShikaku.html#uid5449 + */ +param givens : 1 2 3 4 5 6 7 8 9 10 := + 1 9 . . . 12 . . 5 . . + 2 . . . . . . . . . . + 3 . . . . . . . . . 6 + 4 8 . 6 . 8 . . . . . + 5 . . . . . . . . . . + 6 . . . . . . . . . . + 7 . . . . . 6 . 8 . 12 + 8 4 . . . . . . . . . + 9 . . . . . . . . . . + 10 . . 3 . . 9 . . . 4 + ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/sorting.mod b/resources/3rdparty/glpk-4.53/examples/sorting.mod new file mode 100644 index 000000000..8f82b1fc5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sorting.mod @@ -0,0 +1,67 @@ +/* sorting.mod - how to sort arrays in MathProg */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +# Sometimes it is necessary to print parameters or variables in the +# order of ascending or descending their values. Suppose, for example, +# that we have the following subscripted parameter: + +set I := 1..12; + +param a{i in I} := Uniform(2, 7); + +# If we print all its members: + +printf{i in I} "a[%d] = %g\n", i, a[i]; + +# the output may look like follows: +# +# a[1] = 2.64156 +# a[2] = 2.04798 +# a[3] = 2.14843 +# a[4] = 4.76896 +# a[5] = 6.09132 +# a[6] = 3.27780 +# a[7] = 4.06113 +# a[8] = 4.05898 +# a[9] = 6.63120 +# a[10] = 6.50318 +# a[11] = 3.46065 +# a[12] = 4.69845 +# +# However, we would like the parameter members to appear in the order +# of ascending their values. +# +# Introduce the following auxiliary parameter: + +param pos{i in I} := + 1 + card({j in I: a[j] < a[i] or a[j] = a[i] and j < i}); + +# where pos[i] = k means that in the sorted list member a[i] would +# have k-th position, 1 <= k <= |I|. Then introduce another auxiliary +# parameter: + +param ind{k in 1..card(I)} := sum{i in I: pos[i] = k} i; + +# where ind[k] = i iff pos[k] = i. +# +# Now, the following statement: + +printf{k in 1..card(I)} "a[%d] = %g\n", ind[k], a[ind[k]]; + +# prints the parameter members in the desired order: +# +# a[2] = 2.04798 +# a[3] = 2.14843 +# a[1] = 2.64156 +# a[6] = 3.27780 +# a[11] = 3.46065 +# a[8] = 4.05898 +# a[7] = 4.06113 +# a[12] = 4.69845 +# a[4] = 4.76896 +# a[5] = 6.09132 +# a[10] = 6.50318 +# a[9] = 6.63120 + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/spp.mod b/resources/3rdparty/glpk-4.53/examples/spp.mod new file mode 100644 index 000000000..53008f62c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/spp.mod @@ -0,0 +1,67 @@ +/* SPP, Shortest Path Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* Given a directed graph G = (V,E), its edge lengths c(i,j) for all + (i,j) in E, and two nodes s, t in V, the Shortest Path Problem (SPP) + is to find a directed path from s to t whose length is minimal. */ + +param n, integer, > 0; +/* number of nodes */ + +set E, within {i in 1..n, j in 1..n}; +/* set of edges */ + +param c{(i,j) in E}; +/* c[i,j] is length of edge (i,j); note that edge lengths are allowed + to be of any sign (positive, negative, or zero) */ + +param s, in {1..n}; +/* source node */ + +param t, in {1..n}; +/* target node */ + +var x{(i,j) in E}, >= 0; +/* x[i,j] = 1 means that edge (i,j) belong to shortest path; + x[i,j] = 0 means that edge (i,j) does not belong to shortest path; + note that variables x[i,j] are binary, however, there is no need to + declare them so due to the totally unimodular constraint matrix */ + +s.t. r{i in 1..n}: sum{(j,i) in E} x[j,i] + (if i = s then 1) = + sum{(i,j) in E} x[i,j] + (if i = t then 1); +/* conservation conditions for unity flow from s to t; every feasible + solution is a path from s to t */ + +minimize Z: sum{(i,j) in E} c[i,j] * x[i,j]; +/* objective function is the path length to be minimized */ + +data; + +/* Optimal solution is 20 that corresponds to the following shortest + path: s = 1 -> 2 -> 4 -> 8 -> 6 = t */ + +param n := 8; + +param s := 1; + +param t := 6; + +param : E : c := + 1 2 1 + 1 4 8 + 1 7 6 + 2 4 2 + 3 2 14 + 3 4 10 + 3 5 6 + 3 6 19 + 4 5 8 + 4 8 13 + 5 8 12 + 6 5 7 + 7 4 5 + 8 6 4 + 8 7 10; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/spxsamp1.c b/resources/3rdparty/glpk-4.53/examples/spxsamp1.c new file mode 100644 index 000000000..715642341 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/spxsamp1.c @@ -0,0 +1,18 @@ +/* spxsamp1.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *P; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_adv_basis(P, 0); + glp_simplex(P, NULL); + glp_print_sol(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/spxsamp2.c b/resources/3rdparty/glpk-4.53/examples/spxsamp2.c new file mode 100644 index 000000000..f952e740e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/spxsamp2.c @@ -0,0 +1,20 @@ +/* spxsamp2.c */ + +#include <stdio.h> +#include <stdlib.h> +#include <glpk.h> + +int main(void) +{ glp_prob *P; + glp_smcp parm; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_init_smcp(&parm); + parm.meth = GLP_DUAL; + glp_simplex(P, &parm); + glp_print_sol(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/examples/sql/README b/resources/3rdparty/glpk-4.53/examples/sql/README new file mode 100644 index 000000000..f78ec1574 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sql/README @@ -0,0 +1,5 @@ +This subdirectory contains files which demonstrate using data tables +in MathProg models for MySQL and iODBC. + +Script mysql_setup.sh is used to load the data from the *.sql files to +a MySQL database. Change the username, if necessary. diff --git a/resources/3rdparty/glpk-4.53/examples/sql/mysql_setup.sh b/resources/3rdparty/glpk-4.53/examples/sql/mysql_setup.sh new file mode 100644 index 000000000..1dce8edd9 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sql/mysql_setup.sh @@ -0,0 +1,6 @@ +#!/bin/sh +# This file can be used to create database glpk in MySQL. +echo MySQL is called for user root. +mysql -f -u root -p < sudoku.sql +echo MySQL is called for user root. +mysql -f -u root -p < transp.sql diff --git a/resources/3rdparty/glpk-4.53/examples/sql/sudoku.sql b/resources/3rdparty/glpk-4.53/examples/sql/sudoku.sql new file mode 100644 index 000000000..2fe40d777 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sql/sudoku.sql @@ -0,0 +1,101 @@ +CREATE DATABASE glpk; +CREATE USER glpk@localhost IDENTIFIED BY 'gnu'; +GRANT ALL PRIVILEGES ON glpk.* TO glpk@localhost; +USE glpk; +DROP TABLE sudoku; +CREATE TABLE sudoku ( + ID INT , + COL INT , + LIN INT , + VAL INT , + PRIMARY KEY ( ID, COL, LIN ) + ); +DROP TABLE sudoku_solution; +CREATE TABLE sudoku_solution ( + ID INT , + COL INT , + LIN INT , + VAL INT , + PRIMARY KEY ( ID, COL, LIN ) + ); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 1, 5); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 3, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 5, 4); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 3, 3); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 7, 6); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 8, 2); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 3, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 6, 9); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 9, 4); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 3, 6); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 6, 7); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 7, 2); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 1, 8); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 2, 1); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 3, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 8, 4); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 9, 3); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 3, 9); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 4, 1); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 1, 7); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 3, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 4, 5); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 2, 9); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 3, 2); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 7, 8); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 3, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 5, 3); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 9, 6); diff --git a/resources/3rdparty/glpk-4.53/examples/sql/sudoku_mysql.mod b/resources/3rdparty/glpk-4.53/examples/sql/sudoku_mysql.mod new file mode 100644 index 000000000..6e56f2c6d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sql/sudoku_mysql.mod @@ -0,0 +1,113 @@ +/* SUDOKU, Number Placement Puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@mai2.rcnet.ru> */ + +/* This example shows how to use the table statement. + The sudoku to be solves is read from file sudoku_in.csv. + The solution is written to sudoku_out.csv. + The file format is CSV as defined in + RFC 4180 - Common Format and MIME Type for + Comma-Separated Values (CSV) Files */ + +/* Sudoku, also known as Number Place, is a logic-based placement + puzzle. The aim of the canonical puzzle is to enter a numerical + digit from 1 through 9 in each cell of a 9x9 grid made up of 3x3 + subgrids (called "regions"), starting with various digits given in + some cells (the "givens"). Each row, column, and region must contain + only one instance of each numeral. + + Example: + + +-------+-------+-------+ + | 5 3 . | . 7 . | . . . | + | 6 . . | 1 9 5 | . . . | + | . 9 8 | . . . | . 6 . | + +-------+-------+-------+ + | 8 . . | . 6 . | . . 3 | + | 4 . . | 8 . 3 | . . 1 | + | 7 . . | . 2 . | . . 6 | + +-------+-------+-------+ + | . 6 . | . . . | 2 8 . | + | . . . | 4 1 9 | . . 5 | + | . . . | . 8 . | . 7 9 | + +-------+-------+-------+ + + (From Wikipedia, the free encyclopedia.) */ +set fields dimen 2; + +param id; + +param givens{1..9, 1..9}, integer, >= 0, <= 9, default 0; +/* the "givens" */ + +/* +table ti IN 'MySQL' 'Database=glpk;UID=glpk;PWD=gnu' + 'sudoku' : + fields <- [COL, LIN], givens ~ VAL; +*/ +table ti IN 'MySQL' 'Database=glpk;UID=glpk;PWD=gnu' + 'SELECT * FROM sudoku WHERE ID = ' & id : + fields <- [COL, LIN], givens ~ VAL; + +var x{i in 1..9, j in 1..9, k in 1..9}, binary; +/* x[i,j,k] = 1 means cell [i,j] is assigned number k */ + +s.t. fa{i in 1..9, j in 1..9, k in 1..9: givens[i,j] != 0}: + x[i,j,k] = (if givens[i,j] = k then 1 else 0); +/* assign pre-defined numbers using the "givens" */ + +s.t. fb{i in 1..9, j in 1..9}: sum{k in 1..9} x[i,j,k] = 1; +/* each cell must be assigned exactly one number */ + +s.t. fc{i in 1..9, k in 1..9}: sum{j in 1..9} x[i,j,k] = 1; +/* cells in the same row must be assigned distinct numbers */ + +s.t. fd{j in 1..9, k in 1..9}: sum{i in 1..9} x[i,j,k] = 1; +/* cells in the same column must be assigned distinct numbers */ + +s.t. fe{I in 1..9 by 3, J in 1..9 by 3, k in 1..9}: + sum{i in I..I+2, j in J..J+2} x[i,j,k] = 1; +/* cells in the same region must be assigned distinct numbers */ + +/* there is no need for an objective function here */ + +solve; + +table ta{(i,j) in fields} OUT + 'MySQL' 'Database=glpk;UID=glpk;PWD=gnu' + 'DELETE FROM sudoku_solution' + 'WHERE ID = ' & id & ';' + 'INSERT INTO sudoku_solution' + '(ID, COL, LIN, VAL)' + 'VALUES(?, ?, ?, ?);' : + id ~ ID, i ~ COL, j ~ LIN, (sum{k in 1..9} x[i,j,k] * k) ~ VAL; + +printf "\nSudoku to be solved\n"; +for {i in 1..9} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +-------+-------+-------+\n"; + for {j in 1..9} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %d", givens[i,j]; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +-------+-------+-------+\n"; + } +printf "\nSolution\n"; +for {i in 1..9} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +-------+-------+-------+\n"; + for {j in 1..9} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %d", sum{k in 1..9} x[i,j,k] * k; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +-------+-------+-------+\n"; +} + +data; + +param id := 1; +end; diff --git a/resources/3rdparty/glpk-4.53/examples/sql/sudoku_odbc.mod b/resources/3rdparty/glpk-4.53/examples/sql/sudoku_odbc.mod new file mode 100644 index 000000000..9ffa3ab06 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sql/sudoku_odbc.mod @@ -0,0 +1,111 @@ +/* SUDOKU, Number Placement Puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@mai2.rcnet.ru> */ + +/* This example shows how to use the table statement. + The sudoku to be solves is read from file sudoku_in.csv. + The solution is written to sudoku_out.csv. + The file format is CSV as defined in + RFC 4180 - Common Format and MIME Type for + Comma-Separated Values (CSV) Files */ + +/* Sudoku, also known as Number Place, is a logic-based placement + puzzle. The aim of the canonical puzzle is to enter a numerical + digit from 1 through 9 in each cell of a 9x9 grid made up of 3x3 + subgrids (called "regions"), starting with various digits given in + some cells (the "givens"). Each row, column, and region must contain + only one instance of each numeral. + + Example: + + +-------+-------+-------+ + | 5 3 . | . 7 . | . . . | + | 6 . . | 1 9 5 | . . . | + | . 9 8 | . . . | . 6 . | + +-------+-------+-------+ + | 8 . . | . 6 . | . . 3 | + | 4 . . | 8 . 3 | . . 1 | + | 7 . . | . 2 . | . . 6 | + +-------+-------+-------+ + | . 6 . | . . . | 2 8 . | + | . . . | 4 1 9 | . . 5 | + | . . . | . 8 . | . 7 9 | + +-------+-------+-------+ + + (From Wikipedia, the free encyclopedia.) */ +set fields dimen 2; + +param id; + +param givens{1..9, 1..9}, integer, >= 0, <= 9, default 0; +/* the "givens" */ + +table ti IN 'iODBC' + 'DSN=glpk;UID=glpk;PWD=gnu' + 'SELECT * FROM sudoku' + 'WHERE ID = ' & id : + fields <- [COL, LIN], givens ~ VAL; + +var x{i in 1..9, j in 1..9, k in 1..9}, binary; +/* x[i,j,k] = 1 means cell [i,j] is assigned number k */ + +s.t. fa{i in 1..9, j in 1..9, k in 1..9: givens[i,j] != 0}: + x[i,j,k] = (if givens[i,j] = k then 1 else 0); +/* assign pre-defined numbers using the "givens" */ + +s.t. fb{i in 1..9, j in 1..9}: sum{k in 1..9} x[i,j,k] = 1; +/* each cell must be assigned exactly one number */ + +s.t. fc{i in 1..9, k in 1..9}: sum{j in 1..9} x[i,j,k] = 1; +/* cells in the same row must be assigned distinct numbers */ + +s.t. fd{j in 1..9, k in 1..9}: sum{i in 1..9} x[i,j,k] = 1; +/* cells in the same column must be assigned distinct numbers */ + +s.t. fe{I in 1..9 by 3, J in 1..9 by 3, k in 1..9}: + sum{i in I..I+2, j in J..J+2} x[i,j,k] = 1; +/* cells in the same region must be assigned distinct numbers */ + +/* there is no need for an objective function here */ + + +solve; + +table ta {(i, j) in {i1 in 1..9} cross {i2 in 1..9}} OUT + 'iODBC' 'DSN=glpk;UID=glpk;PWD=gnu' + 'DELETE FROM sudoku_solution' + 'WHERE ID = ' & id & ';' + 'INSERT INTO sudoku_solution' + '(ID, COL, LIN, VAL)' + 'VALUES(?, ?, ?, ?);' : + id ~ ID, i ~ COL, j ~ LIN, (sum{k in 1..9} x[i,j,k] * k) ~ VAL; + +printf "\nSudoku to be solved\n"; +for {i in 1..9} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +-------+-------+-------+\n"; + for {j in 1..9} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %d", givens[i,j]; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +-------+-------+-------+\n"; + } +printf "\nSolution\n"; +for {i in 1..9} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +-------+-------+-------+\n"; + for {j in 1..9} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %d", sum{k in 1..9} x[i,j,k] * k; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +-------+-------+-------+\n"; +} + +data; + +param id := 1; +end; diff --git a/resources/3rdparty/glpk-4.53/examples/sql/transp.sql b/resources/3rdparty/glpk-4.53/examples/sql/transp.sql new file mode 100644 index 000000000..873733303 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sql/transp.sql @@ -0,0 +1,45 @@ +CREATE DATABASE glpk; +CREATE USER glpk@localhost IDENTIFIED BY 'gnu'; +GRANT ALL PRIVILEGES ON glpk.* TO glpk@localhost; +USE glpk; +# production capacity +DROP TABLE transp_capa; +CREATE TABLE transp_capa ( + PLANT TEXT(127), + CAPA REAL, + PRIMARY KEY ( PLANT(127) ) + ); +INSERT INTO transp_capa ( PLANT, CAPA ) VALUES ( 'Seattle', 350 ); +INSERT INTO transp_capa ( PLANT, CAPA ) VALUES ( 'San Diego', 600 ); +# demand +DROP TABLE transp_demand; +CREATE TABLE transp_demand ( + MARKET TEXT(127), + DEMAND REAL, + PRIMARY KEY ( MARKET(127) ) + ); +INSERT INTO transp_demand ( MARKET, DEMAND ) VALUES ( 'New York', 325 ); +INSERT INTO transp_demand ( MARKET, DEMAND ) VALUES ( 'Chicago', 300 ); +INSERT INTO transp_demand ( MARKET, DEMAND ) VALUES ( 'Topeka', 275 ); +# distance +DROP TABLE transp_dist; +CREATE TABLE transp_dist ( + LOC1 TEXT(127), + LOC2 TEXT(127), + DIST REAL, + PRIMARY KEY ( LOC1(127), LOC2(127) ) + ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'Seattle', 'New York', 2.5 ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'Seattle', 'Chicago', 1.7 ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'Seattle', 'Topeka', 1.8 ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'San Diego', 'New York', 2.5 ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'San Diego', 'Chicago', 1.8 ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'San Diego', 'Topeka', 1.4 ); +# result +DROP TABLE transp_result; +CREATE TABLE transp_result ( + LOC1 TEXT(127), + LOC2 TEXT(127), + QUANTITY REAL, + PRIMARY KEY ( LOC1(127), LOC2(127) ) + ); diff --git a/resources/3rdparty/glpk-4.53/examples/sql/transp_mysql.mod b/resources/3rdparty/glpk-4.53/examples/sql/transp_mysql.mod new file mode 100644 index 000000000..f375fa395 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sql/transp_mysql.mod @@ -0,0 +1,71 @@ +# A TRANSPORTATION PROBLEM +# +# This problem finds a least cost shipping schedule that meets +# requirements at markets and supplies at factories. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* canning plants */ + +param a{i in I}; +/* capacity of plant i in cases */ + +table plants IN "MySQL" + 'Database=glpk;UID=glpk;PWD=gnu' + 'SELECT PLANT, CAPA AS CAPACITY FROM transp_capa' : + I <- [ PLANT ], a ~ CAPACITY; + +set J; +/* markets */ + +param b{j in J}; +/* demand at market j in cases */ + +table markets IN "MySQL" + 'Database=glpk;UID=glpk;PWD=gnu' + 'transp_demand' : + J <- [ MARKET ], b ~ DEMAND; + +param d{i in I, j in J}; +/* distance in thousands of miles */ + +table dist IN "MySQL" + 'Database=glpk;UID=glpk;PWD=gnu' + 'transp_dist' : + [ LOC1, LOC2 ], d ~ DIST; + +param f; +/* freight in dollars per case per thousand miles */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* transport cost in thousands of dollars per case */ + +var x{i in I, j in J} >= 0; +/* shipment quantities in cases */ + +minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; +/* total transportation costs in thousands of dollars */ + +s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observe supply limit at plant i */ + +s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfy demand at market j */ + +solve; + +table result{i in I, j in J: x[i,j]} OUT "MySQL" + 'Database=glpk;UID=glpk;PWD=gnu' + 'DELETE FROM transp_result;' + 'INSERT INTO transp_result VALUES (?,?,?)' : + i ~ LOC1, j ~ LOC2, x[i,j] ~ QUANTITY; + +data; + +param f := 90; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/sql/transp_odbc.mod b/resources/3rdparty/glpk-4.53/examples/sql/transp_odbc.mod new file mode 100644 index 000000000..36d807e41 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sql/transp_odbc.mod @@ -0,0 +1,72 @@ +# A TRANSPORTATION PROBLEM +# +# This problem finds a least cost shipping schedule that meets +# requirements at markets and supplies at factories. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* canning plants */ + +param a{i in I}; +/* capacity of plant i in cases */ + +table plants IN "iODBC" + 'DSN=glpk;UID=glpk;PWD=gnu' + 'SELECT PLANT, CAPA AS CAPACITY' + 'FROM transp_capa' : + I <- [ PLANT ], a ~ CAPACITY; + +set J; +/* markets */ + +param b{j in J}; +/* demand at market j in cases */ + +table markets IN "iODBC" + 'DSN=glpk;UID=glpk;PWD=gnu' + 'transp_demand' : + J <- [ MARKET ], b ~ DEMAND; + +param d{i in I, j in J}; +/* distance in thousands of miles */ + +table dist IN "iODBC" + 'DSN=glpk;UID=glpk;PWD=gnu' + 'transp_dist' : + [ LOC1, LOC2 ], d ~ DIST; + +param f; +/* freight in dollars per case per thousand miles */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* transport cost in thousands of dollars per case */ + +var x{i in I, j in J} >= 0; +/* shipment quantities in cases */ + +minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; +/* total transportation costs in thousands of dollars */ + +s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observe supply limit at plant i */ + +s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfy demand at market j */ + +solve; + +table result{i in I, j in J: x[i,j]} OUT "iODBC" + 'DSN=glpk;UID=glpk;PWD=gnu' + 'DELETE FROM transp_result;' + 'INSERT INTO transp_result VALUES (?,?,?)' : + i ~ LOC1, j ~ LOC2, x[i,j] ~ QUANTITY; + +data; + +param f := 90; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/stigler.mod b/resources/3rdparty/glpk-4.53/examples/stigler.mod new file mode 100644 index 000000000..20c5d9d13 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/stigler.mod @@ -0,0 +1,411 @@ +/* STIGLER, original Stigler's 1939 diet problem */ + +/* The Stigler Diet is an optimization problem named for George Stigler, + a 1982 Nobel Laureate in economics, who posed the following problem: + For a moderately active man weighing 154 pounds, how much of each of + 77 foods should be eaten on a daily basis so that the man's intake of + nine nutrients will be at least equal to the recommended dietary + allowances (RDSs) suggested by the National Research Council in 1943, + with the cost of the diet being minimal? + + The nutrient RDAs required to be met in Stigler's experiment were + calories, protein, calcium, iron, vitamin A, thiamine, riboflavin, + niacin, and ascorbic acid. The result was an annual budget allocated + to foods such as evaporated milk, cabbage, dried navy beans, and beef + liver at a cost of approximately $0.11 a day in 1939 U.S. dollars. + + While the name "Stigler Diet" was applied after the experiment by + outsiders, according to Stigler, "No one recommends these diets for + anyone, let alone everyone." The Stigler diet has been much ridiculed + for its lack of variety and palatability, however his methodology has + received praise and is considered to be some of the earliest work in + linear programming. + + The Stigler diet question is a linear programming problem. Lacking + any sophisticated method of solving such a problem, Stigler was + forced to utilize heuristic methods in order to find a solution. The + diet question originally asked in which quantities a 154 pound male + would have to consume 77 different foods in order to fulfill the + recommended intake of 9 different nutrients while keeping expense at + a minimum. Through "trial and error, mathematical insight and + agility," Stigler was able to eliminate 62 of the foods from the + original 77 (these foods were removed based because they lacked + nutrients in comparison to the remaining 15). From the reduced list, + Stigler calculated the required amounts of each of the remaining 15 + foods to arrive at a cost-minimizing solution to his question. + According to Stigler's calculations, the annual cost of his solution + was $39.93 in 1939 dollars. When corrected for inflation using the + consumer price index, the cost of the diet in 2005 dollars is + $561.43. The specific combination of foods and quantities is as + follows: + + Stigler's 1939 Diet + + Food Annual Quantities Annual Cost + ---------------- ----------------- ----------- + Wheat Flour 370 lb. $13.33 + Evaporated Milk 57 cans 3.84 + Cabbage 111 lb. 4.11 + Spinach 23 lb. 1.85 + Dried Navy Beans 285 lb. 16.80 + ---------------------------------------------- + Total Annual Cost $39.93 + + The 9 nutrients that Stigler's diet took into consideration and their + respective recommended daily amounts were: + + Table of nutrients considered in Stigler's diet + + Nutrient Daily Recommended Intake + ------------------------- ------------------------ + Calories 3,000 Calories + Protein 70 grams + Calcium .8 grams + Iron 12 milligrams + Vitamin A 5,000 IU + Thiamine (Vitamin B1) 1.8 milligrams + Riboflavin (Vitamin B2) 2.7 milligrams + Niacin 18 milligrams + Ascorbic Acid (Vitamin C) 75 milligrams + + Seven years after Stigler made his initial estimates, the development + of George Dantzig's Simplex algorithm made it possible to solve the + problem without relying on heuristic methods. The exact value was + determined to be $39.69 (using the original 1939 data). Dantzig's + algorithm describes a method of traversing the vertices of a polytope + of N+1 dimensions in order to find the optimal solution to a specific + situation. + + (From Wikipedia, the free encyclopedia.) */ + +/* Translated from GAMS by Andrew Makhorin <mao@gnu.org>. + + For the original GAMS model stigler1939.gms see [3]. + + References: + + 1. George J. Stigler, "The Cost of Subsistence," J. Farm Econ. 27, + 1945, pp. 303-14. + + 2. National Research Council, "Recommended Daily Allowances," Reprint + and Circular Series No. 115, January, 1943. + + 3. Erwin Kalvelagen, "Model building with GAMS," Chapter 2, "Building + linear programming models," pp. 128-34. */ + +set C; +/* commodities */ + +check card(C) = 77; +/* there must be 77 commodities */ + +set N; +/* nutrients */ + +param data{c in C, {"price", "weight"} union N}; +/* nutritive values per dollar of expenditure */ + +param allowance{n in N}; +/* recommended daily allowance for a moderately active man */ + +var x{c in C}, >= 0; +/* dollars of food to be purchased daily */ + +s.t. nb{n in N}: sum{c in C} data[c,n] * x[c] >= allowance[n]; +/* nutrient balance */ + +minimize cost: sum{c in C} x[c]; +/* total food bill */ + +solve; + +param days := 365.25; +/* days in a year */ + +param commodity{c in C}, symbolic; + +param unit{c in C}, symbolic; + +printf "\n"; +printf "MINIMUM COST ANNUAL DIET\n"; +printf "\n"; +printf " Commodity Unit Quantity Cost \n"; +printf "------------------------- ---------- ---------- ----------\n"; +printf{c in C: x[c] != 0} "%-25s %10s %10.2f $%7.2f\n", commodity[c], + unit[c], 100 * days * x[c] / data[c,"price"], days * x[c]; +printf " -----------------\n"; +printf " Total: $%7.2f\n", + days * sum{c in C} x[c]; +printf "\n"; + +data; + +param : C : commodity unit := +flour "Wheat Flour (Enriched)" "10 lb." +macaroni "Macaroni" "1 lb." +cereal "Wheat Cereal (Enriched)" "28 oz." +cornflakes "Corn Flakes" "8 oz." +cornmeal "Corn Meal" "1 lb." +grits "Hominy Grits" "24 oz." +rice "Rice" "1 lb." +oats "Rolled Oats" "1 lb." +whitebread "White Bread (Enriched)" "1 lb." +wheatbread "Whole Wheat Bread" "1 lb." +ryebread "Rye Bread" "1 lb." +poundcake "Pound Cake" "1 lb." +crackers "Soda Crackers" "1 lb." +milk "Milk" "1 qt." +evapmild "Evaporated Milk (can)" "14.5 oz." +butter "Butter" "1 lb." +margarine "Oleomargarine" "1 lb." +eggs "Eggs" "1 doz." +cheese "Cheese (Cheddar)" "1 lb." +cream "Cream" "1/2 pt." +peanutbutter "Peanut Butter" "1 lb." +mayonnaise "Mayonnaise" "1/2 pt." +crisco "Crisco" "1 lb." +lard "Lard" "1 lb." +sirloinsteak "Sirloin Steak" "1 lb." +roundsteak "Round Steak" "1 lb." +ribroast "Rib Roast" "1 lb." +chuckroast "Chuck Roast" "1 lb." +plate "Plate" "1 lb." +liver "Liver (Beef)" "1 lb." +lambleg "Leg of Lamb" "1 lb." +lambchops "Lamb Chops (Rib)" "1 lb." +porkchops "Pork Chops" "1 lb." +porkroast "Pork Loin Roast" "1 lb." +bacon "Bacon" "1 lb." +ham "Ham - smoked" "1 lb." +saltpork "Salt Pork" "1 lb." +chicken "Roasting Chicken" "1 lb." +veal "Veal Cutlets" "1 lb." +salmon "Salmon, Pink (can)" "16 oz." +apples "Apples" "1 lb." +bananas "Bananas" "1 lb." +lemons "Lemons" "1 doz." +oranges "Oranges" "1 doz." +greenbeans "Green Beans" "1 lb." +cabbage "Cabbage" "1 lb." +carrots "Carrots" "1 bunch" +celery "Celery" "1 stalk" +lettuce "Lettuce" "1 head" +onions "Onions" "1 lb." +potatoes "Potatoes" "15 lb." +spinach "Spinach" "1 lb." +sweetpotato "Sweet Potatoes" "1 lb." +peaches "Peaches (can)" "No. 2 1/2" +pears "Pears (can)" "No. 2 1/2" +pineapple "Pineapple (can)" "No. 2 1/2" +asparagus "Asparagus (can)" "No. 2" +cannedgrbn "Grean Beans (can)" "No. 2" +porkbeans "Pork and Beans (can)" "16 oz." +corn "Corn (can)" "No. 2" +peas "Peas (can)" "No. 2" +tomatoes "Tomatoes (can)" "No. 2" +tomatosoup "Tomato Soup (can)" "10 1/2 oz." +driedpeach "Peaches, Dried" "1 lb." +prunes "Prunes, Dried" "1 lb." +raisins "Raisins, Dried" "15 oz." +driedpeas "Peas, Dried" "1 lb." +limabeans "Lima Beans, Dried" "1 lb." +navybeans "Navy Beans, Dried" "1 lb." +coffee "Coffee" "1 lb." +tea "Tea" "1/4 lb." +cocoa "Cocoa" "8 oz." +chocolate "Chocolate" "8 oz." +sugar "Sugar" "10 lb." +cornsirup "Corn Sirup" "24 oz." +molasses "Molasses" "18 oz." +strawberry "Strawberry Preserve" "1 lb." +; + +set N := +calories /* Calories, unit = 1000 */ +protein /* Protein, unit = grams */ +calcium /* Calcium, unit = grams */ +iron /* Iron, unit = milligrams */ +vitaminA /* Vitamin A, unit = 1000 International Units */ +thiamine /* Thiamine, Vit. B1, unit = milligrams */ +riboflavin /* Riboflavin, Vit. B2, unit = milligrams */ +niacin /* Niacin (Nicotinic Acid), unit = milligrams */ +ascorbicAcid /* Ascorbic Acid, Vit. C, unit = milligrams */ +; + +param data +: price weight calories protein calcium iron := +# aug. 15 edible +# 1939 per $1 +# (cents) (grams) (1000) (grams) (grams) (mg.) +flour 36.0 12600 44.7 1411 2.0 365 +macaroni 14.1 3217 11.6 418 .7 54 +cereal 24.2 3280 11.8 377 14.4 175 +cornflakes 7.1 3194 11.4 252 .1 56 +cornmeal 4.6 9861 36.0 897 1.7 99 +grits 8.5 8005 28.6 680 .8 80 +rice 7.5 6048 21.2 460 .6 41 +oats 7.1 6389 25.3 907 5.1 341 +whitebread 7.9 5742 15.6 488 2.5 115 +wheatbread 9.1 4985 12.2 484 2.7 125 +ryebread 9.2 4930 12.4 439 1.1 82 +poundcake 24.8 1829 8.0 130 .4 31 +crackers 15.1 3004 12.5 288 .5 50 +milk 11.0 8867 6.1 310 10.5 18 +evapmild 6.7 6035 8.4 422 15.1 9 +butter 20.8 1473 10.8 9 .2 3 +margarine 16.1 2817 20.6 17 .6 6 +eggs 32.6 1857 2.9 238 1.0 52 +cheese 24.2 1874 7.4 448 16.4 19 +cream 14.1 1689 3.5 49 1.7 3 +peanutbutter 17.9 2534 15.7 661 1.0 48 +mayonnaise 16.7 1198 8.6 18 .2 8 +crisco 20.3 2234 20.1 0 .0 0 +lard 9.8 4628 41.7 0 .0 0 +sirloinsteak 39.6 1145 2.9 166 .1 34 +roundsteak 36.4 1246 2.2 214 .1 32 +ribroast 29.2 1553 3.4 213 .1 33 +chuckroast 22.6 2007 3.6 309 .2 46 +plate 14.6 3107 8.5 404 .2 62 +liver 26.8 1692 2.2 333 .2 139 +lambleg 27.6 1643 3.1 245 .1 20 +lambchops 36.6 1239 3.3 140 .1 15 +porkchops 30.7 1477 3.5 196 .2 80 +porkroast 24.2 1874 4.4 249 .3 37 +bacon 25.6 1772 10.4 152 .2 23 +ham 27.4 1655 6.7 212 .2 31 +saltpork 16.0 2835 18.8 164 .1 26 +chicken 30.3 1497 1.8 184 .1 30 +veal 42.3 1072 1.7 156 .1 24 +salmon 13.0 3489 5.8 705 6.8 45 +apples 4.4 9072 5.8 27 .5 36 +bananas 6.1 4982 4.9 60 .4 30 +lemons 26.0 2380 1.0 21 .5 14 +oranges 30.9 4439 2.2 40 1.1 18 +greenbeans 7.1 5750 2.4 138 3.7 80 +cabbage 3.7 8949 2.6 125 4.0 36 +carrots 4.7 6080 2.7 73 2.8 43 +celery 7.3 3915 .9 51 3.0 23 +lettuce 8.2 2247 .4 27 1.1 22 +onions 3.6 11844 5.8 166 3.8 59 +potatoes 34.0 16810 14.3 336 1.8 118 +spinach 8.1 4592 1.1 106 .0 138 +sweetpotato 5.1 7649 9.6 138 2.7 54 +peaches 16.8 4894 3.7 20 .4 10 +pears 20.4 4030 3.0 8 .3 8 +pineapple 21.3 3993 2.4 16 .4 8 +asparagus 27.7 1945 .4 33 .3 12 +cannedgrbn 10.0 5386 1.0 54 2.0 65 +porkbeans 7.1 6389 7.5 364 4.0 134 +corn 10.4 5452 5.2 136 .2 16 +peas 13.8 4109 2.3 136 .6 45 +tomatoes 8.6 6263 1.3 63 .7 38 +tomatosoup 7.6 3917 1.6 71 .6 43 +driedpeach 15.7 2889 8.5 87 1.7 173 +prunes 9.0 4284 12.8 99 2.5 154 +raisins 9.4 4524 13.5 104 2.5 136 +driedpeas 7.9 5742 20.0 1367 4.2 345 +limabeans 8.9 5097 17.4 1055 3.7 459 +navybeans 5.9 7688 26.9 1691 11.4 792 +coffee 22.4 2025 .0 0 .0 0 +tea 17.4 652 .0 0 .0 0 +cocoa 8.6 2637 8.7 237 3.0 72 +chocolate 16.2 1400 8.0 77 1.3 39 +sugar 51.7 8773 34.9 0 .0 0 +cornsirup 13.7 4996 14.7 0 .5 74 +molasses 13.6 3752 9.0 0 10.3 244 +strawberry 20.5 2213 6.4 11 .4 7 + +: vitaminA thiamine riboflavin niacin ascorbicAcid := +# (1000 IU) (mg.) (mg.) (mg.) (mg.) +flour .0 55.4 33.3 441 0 +macaroni .0 3.2 1.9 68 0 +cereal .0 14.4 8.8 114 0 +cornflakes .0 13.5 2.3 68 0 +cornmeal 30.9 17.4 7.9 106 0 +grits .0 10.6 1.6 110 0 +rice .0 2.0 4.8 60 0 +oats .0 37.1 8.9 64 0 +whitebread .0 13.8 8.5 126 0 +wheatbread .0 13.9 6.4 160 0 +ryebread .0 9.9 3.0 66 0 +poundcake 18.9 2.8 3.0 17 0 +crackers .0 .0 .0 0 0 +milk 16.8 4.0 16.0 7 177 +evapmild 26.0 3.0 23.5 11 60 +butter 44.2 .0 .2 2 0 +margarine 55.8 .2 .0 0 0 +eggs 18.6 2.8 6.5 1 0 +cheese 28.1 .8 10.3 4 0 +cream 16.9 .6 2.5 0 17 +peanutbutter .0 9.6 8.1 471 0 +mayonnaise 2.7 .4 .5 0 0 +crisco .0 .0 .0 0 0 +lard .2 .0 .5 5 0 +sirloinsteak .2 2.1 2.9 69 0 +roundsteak .4 2.5 2.4 87 0 +ribroast .0 .0 2.0 0 0 +chuckroast .4 1.0 4.0 120 0 +plate .0 .9 .0 0 0 +liver 169.2 6.4 50.8 316 525 +lambleg .0 2.8 3.0 86 0 +lambchops .0 1.7 2.7 54 0 +porkchops .0 17.4 2.7 60 0 +porkroast .0 18.2 3.6 79 0 +bacon .0 1.8 1.8 71 0 +ham .0 9.9 3.3 50 0 +saltpork .0 1.4 1.8 0 0 +chicken .1 .9 1.8 68 46 +veal .0 1.4 2.4 57 0 +salmon 3.5 1.0 4.9 209 0 +apples 7.3 3.6 2.7 5 544 +bananas 17.4 2.5 3.5 28 498 +lemons .0 .5 .0 4 952 +oranges 11.1 3.6 1.3 10 1993 +greenbeans 69.0 4.3 5.8 37 862 +cabbage 7.2 9.0 4.5 26 5369 +carrots 188.5 6.1 4.3 89 608 +celery .9 1.4 1.4 9 313 +lettuce 112.4 1.8 3.4 11 449 +onions 16.6 4.7 5.9 21 1184 +potatoes 6.7 29.4 7.1 198 2522 +spinach 918.4 5.7 13.8 33 2755 +sweetpotato 290.7 8.4 5.4 83 1912 +peaches 21.5 .5 1.0 31 196 +pears .8 .8 .8 5 81 +pineapple 2.0 2.8 .8 7 399 +asparagus 16.3 1.4 2.1 17 272 +cannedgrbn 53.9 1.6 4.3 32 431 +porkbeans 3.5 8.3 7.7 56 0 +corn 12.0 1.6 2.7 42 218 +peas 34.9 4.9 2.5 37 370 +tomatoes 53.2 3.4 2.5 36 1253 +tomatosoup 57.9 3.5 2.4 67 862 +driedpeach 86.8 1.2 4.3 55 57 +prunes 85.7 3.9 4.3 65 257 +raisins 4.5 6.3 1.4 24 136 +driedpeas 2.9 28.7 18.4 162 0 +limabeans 5.1 26.9 38.2 93 0 +navybeans .0 38.4 24.6 217 0 +coffee .0 4.0 5.1 50 0 +tea .0 .0 2.3 42 0 +cocoa .0 2.0 11.9 40 0 +chocolate .0 .9 3.4 14 0 +sugar .0 .0 .0 0 0 +cornsirup .0 .0 .0 5 0 +molasses .0 1.9 7.5 146 0 +strawberry .2 .2 .4 3 0 +; + +param allowance := +calories 3 +protein 70 +calcium .8 +iron 12 +vitaminA 5 +thiamine 1.8 +riboflavin 2.7 +niacin 18 +ascorbicAcid 75 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/sudoku.dat b/resources/3rdparty/glpk-4.53/examples/sudoku.dat new file mode 100644 index 000000000..074ff4f8f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sudoku.dat @@ -0,0 +1,16 @@ +/* sudoku.dat, a hard Sudoku puzzle which causes branching */ + +data; + +param givens : 1 2 3 4 5 6 7 8 9 := + 1 1 . . . . . 7 . . + 2 . 2 . . . . 5 . . + 3 6 . . 3 8 . . . . + 4 . 7 8 . . . . . . + 5 . . . 6 . 9 . . . + 6 . . . . . . 1 4 . + 7 . . . . 2 5 . . 9 + 8 . . 3 . . . . 6 . + 9 . . 4 . . . . . 2 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/sudoku.mod b/resources/3rdparty/glpk-4.53/examples/sudoku.mod new file mode 100644 index 000000000..61f2fe2bf --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/sudoku.mod @@ -0,0 +1,84 @@ +/* SUDOKU, Number Placement Puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* Sudoku, also known as Number Place, is a logic-based placement + puzzle. The aim of the canonical puzzle is to enter a numerical + digit from 1 through 9 in each cell of a 9x9 grid made up of 3x3 + subgrids (called "regions"), starting with various digits given in + some cells (the "givens"). Each row, column, and region must contain + only one instance of each numeral. + + Example: + + +-------+-------+-------+ + | 5 3 . | . 7 . | . . . | + | 6 . . | 1 9 5 | . . . | + | . 9 8 | . . . | . 6 . | + +-------+-------+-------+ + | 8 . . | . 6 . | . . 3 | + | 4 . . | 8 . 3 | . . 1 | + | 7 . . | . 2 . | . . 6 | + +-------+-------+-------+ + | . 6 . | . . . | 2 8 . | + | . . . | 4 1 9 | . . 5 | + | . . . | . 8 . | . 7 9 | + +-------+-------+-------+ + + (From Wikipedia, the free encyclopedia.) */ + +param givens{1..9, 1..9}, integer, >= 0, <= 9, default 0; +/* the "givens" */ + +var x{i in 1..9, j in 1..9, k in 1..9}, binary; +/* x[i,j,k] = 1 means cell [i,j] is assigned number k */ + +s.t. fa{i in 1..9, j in 1..9, k in 1..9: givens[i,j] != 0}: + x[i,j,k] = (if givens[i,j] = k then 1 else 0); +/* assign pre-defined numbers using the "givens" */ + +s.t. fb{i in 1..9, j in 1..9}: sum{k in 1..9} x[i,j,k] = 1; +/* each cell must be assigned exactly one number */ + +s.t. fc{i in 1..9, k in 1..9}: sum{j in 1..9} x[i,j,k] = 1; +/* cells in the same row must be assigned distinct numbers */ + +s.t. fd{j in 1..9, k in 1..9}: sum{i in 1..9} x[i,j,k] = 1; +/* cells in the same column must be assigned distinct numbers */ + +s.t. fe{I in 1..9 by 3, J in 1..9 by 3, k in 1..9}: + sum{i in I..I+2, j in J..J+2} x[i,j,k] = 1; +/* cells in the same region must be assigned distinct numbers */ + +/* there is no need for an objective function here */ + +solve; + +for {i in 1..9} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +-------+-------+-------+\n"; + for {j in 1..9} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %d", sum{k in 1..9} x[i,j,k] * k; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +-------+-------+-------+\n"; +} + +data; + +/* These data correspond to the example above. */ + +param givens : 1 2 3 4 5 6 7 8 9 := + 1 5 3 . . 7 . . . . + 2 6 . . 1 9 5 . . . + 3 . 9 8 . . . . 6 . + 4 8 . . . 6 . . . 3 + 5 4 . . 8 . 3 . . 1 + 6 7 . . . 2 . . . 6 + 7 . 6 . . . . 2 8 . + 8 . . . 4 1 9 . . 5 + 9 . . . . 8 . . 7 9 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/t1.cs b/resources/3rdparty/glpk-4.53/examples/t1.cs new file mode 100644 index 000000000..d07780f4e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/t1.cs @@ -0,0 +1,99 @@ +/*Find the minimum value which satisfies the linear inequality: + a*x + b*y >= 1 {a,b,x,y Integers} {a,b > 0} {a,b entered on command line} + + Nigel_Galloway@operamail.com + February 2008 +*/ +using System; +using System.Runtime.InteropServices; + +unsafe class GLPK{ + double *lp; + public int a; + public int b; + + const string glpkLibrary = "libglpk.so"; + readonly int GLP_FR = 1; + readonly int GLP_IV = 2; + readonly int GLP_DB = 4; + struct ConstraintMatrix{ + public fixed int ia[3]; + public fixed int ja[3]; + public fixed double ar[3]; + } + [DllImport(glpkLibrary, SetLastError=true)] + static extern double* glp_create_prob(); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_add_rows(double* lp, int rows); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_add_cols(double* lp, int cols); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_set_col_bnds(double* lp, int col, int bound_type, double lower_bound, double upper_bound); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_set_col_kind(double* lp, int col, int kind); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_load_matrix(double* lp, int elements, int* ia, int* ja, double* ar); + public GLPK(int a, int b){ + this.a = a; + this.b = b; + lp = glp_create_prob(); + //Col 1 is x, Col 2 is y + glp_add_rows(lp, 1); + glp_add_cols(lp, 2); + glp_set_col_bnds(lp, 1, GLP_FR, 0.0, 0.0); + glp_set_col_bnds(lp, 2, GLP_FR, 0.0, 0.0); + glp_set_col_kind(lp, 1, GLP_IV); + glp_set_col_kind(lp, 2, GLP_IV); + //Row 1 is a*x + b*y + ConstraintMatrix CM = new ConstraintMatrix(); + CM.ia[1]=1; CM.ja[1]=1; CM.ar[1]=a; + CM.ia[2]=1; CM.ja[2]=2; CM.ar[2]=b; + glp_load_matrix(lp, 2, CM.ia, CM.ja, CM.ar); + Console.WriteLine("Hello Nigel"); + } + + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_set_row_bnds(double* lp, int row, int bound_type, double lower_bound, double upper_bound); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_simplex(double* lp, void* options); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_intopt(double* lp, void* options); + [DllImport(glpkLibrary, SetLastError=true)] + static extern double glp_mip_col_val(double* lp, int col); + public int betterGuess(int upper_bound){ + //Find a new guess less than the old guess: 1 <= (a*x + b*y) <= (old guess - 1) + glp_set_row_bnds(lp, 1, GLP_DB, 1.0, ((double)upper_bound)-0.5); + glp_simplex(lp, null); + glp_intopt(lp, null); + int x = (int)glp_mip_col_val(lp, 1); + int y = (int)glp_mip_col_val(lp, 2); + int nextGuess = a*x + b*y; + Console.WriteLine("x = {0}, y = {1}, a*x + b*y = {2}",x,y,nextGuess); + return nextGuess; + } + + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_delete_prob(double* lp); + ~GLPK(){ + glp_delete_prob(lp); + Console.WriteLine("Goodbye Nigel"); + } + +} + +class test{ + static bool isMinimum(int a, int b, int guess){ + Console.WriteLine("Trying {0}",guess); + if (a%guess > 0) return false; + if (b%guess > 0) return false; + Console.WriteLine("Solution is {0}",guess); + return true; + } + + public static void Main(string[] args){ + Console.WriteLine("a = {0}, b = {1}",args[0], args[1]); + GLPK lp = new GLPK(Int32.Parse(args[0]),Int32.Parse(args[1])); + int guess = (lp.a > lp.b) ? lp.b : lp.a; + while (!isMinimum(lp.a,lp.b,guess)) guess = lp.betterGuess(guess); + } +} diff --git a/resources/3rdparty/glpk-4.53/examples/tas.mod b/resources/3rdparty/glpk-4.53/examples/tas.mod new file mode 100644 index 000000000..dbb5ac2da --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/tas.mod @@ -0,0 +1,486 @@ +/* TAS, Tail Assignment Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Tail Assignment Problem (TAS) is to construct rosters for a set + of aircrafts (tails), which cover all flights for a given scheduling + period. + + This model includes only flight connection constraints while other + constraints (for example, maintenance constraints) are ignored. Such + simplification allows using a single commodity network to model the + problem, where commodity corresponds to the set of aircrafts. + + Nodes of the network are activities. They include all flights plus + two dummy nodes (activities): source node, s, corresponding to + initial activity of each aircraft, and sink node t, corresponding to + final activity of each aircraft. Arc v->v' exists in the network if + and only if the same aircraft is able to operate activity v and then + immediately activity v'. In partucular, arcs s->f and f->t exist for + all flights f. Arcs f->f', where f and f' are some flights, exist + only if the connection time (which is the difference between the + departure time of f' and the arrival time of f) is not less than a + given minimal connection time. + + Reference: + M. Groenkvist, "The Tail Assignment Problem," Dept. of Comp. Sci. + and Eng., Chalmers University of Technology and Goeteborg University, + Goeteborg, Sweden, August 2005. */ + +######################################################################## + +param nf, integer, > 0; +/* number of flights */ + +set F := 1..nf; +/* set of flights (for a given period from timetable) */ + +param hub{f in F}, in {1, 2}; +/* hub[f] = 1: Sheremetyevo-1 + hub[f] = 2: Sheremetyevo-2 */ + +param dest{f in F}, symbolic; +/* destination airport (IATA code) */ + +param fno1{f in F}, integer; +/* first leg flight number */ + +param dep1{f in F}, integer, >= 0; +/* departure time from Sheremetyevo airport, in minutes */ + +check{f in F: f < nf}: dep1[f] <= dep1[f+1]; +/* all flights must be ordered by ascending of the departure time */ + +param arr1{f in F}, integer, >= 0; +/* arrival time to destination airport, in minutes */ + +param fno2{f in F}, integer; +/* second leg flight number */ + +param dep2{f in F}, integer, >= 0; +/* departure time from destination airport, in minutes */ + +param arr2{f in F}, integer, >= 0; +/* arrival time to Sheremetyevo airport, in minutes */ + +param mct1, integer, >= 0, default 80; +/* minimal connection time (within SVO1 or SVO2), in minutes */ + +param mct2, integer, >= 0, default 150; +/* minimal connection time (between SVO1 and SVO2), in minutes */ + +set E := setof{f in F, ff in F: arr2[f] + (if hub[f] = hub[ff] then + mct1 else mct2) <= dep1[ff]} (f, ff); +/* connection network; arc f->ff is in E, iff the same aircraft can be + assigned to flight f and then immediately to flight ff */ + +var s{f in F}, >= 0; +/* s[f] is a flow from source node to node f */ + +var x{(f,ff) in E}, >= 0; +/* x[f,ff] is a flow from node f to node ff */ + +var t{f in F}, >= 0; +/* t[f] is a flow from node f to sink node */ + +s.t. into{f in F}: s[f] + sum{(ff,f) in E} x[ff,f] = 1; +/* exactly one aircraft must come into each node f */ + +s.t. from{f in F}: t[f] + sum{(f,ff) in E} x[f,ff] = 1; +/* exactly one aircraft must come from each node f */ + +minimize obj: sum{f in F} s[f]; +/* minimize the number aircrafts sufficient to cover all flights */ + +solve; + +######################################################################## + +param na := floor(sum{f in F} s[f] + .5); +/* minimal number of aircrafts found */ + +printf "At least %d aircrafts needed\n", na; + +set A := 1..na; +/* set of aircrafts */ + +printf "Building rosters...\n"; + +param tail{f in F}, in A, := +/* tail[f] is the number of an aircraft assigned to flight f */ + + if f = 1 then 1 + /* assign aircraft 1 to the earliest flight */ + + else if s[f] >= 0.9 then (max{ff in 1..f-1} tail[ff]) + 1 + /* if f is the first flight in a roster, assign to it a next + aircraft */ + + else sum{(ff,f) in E} tail[ff] * (if x[ff,f] >= 0.9 then 1); + /* otherwise, assign to flight f the same aircraft, which is + assigned to a preceding flight in the roster */ + +######################################################################## + +param file, symbolic, default "tas.ps"; +/* file to output the assignment chart in postscript format */ + +param title, symbolic, default "(no title)"; +/* chart title */ + +param left, default 25; +/* left margin, in mm */ + +param top, default 25; +/* top margin, in mm */ + +param right, default 20; +/* right margin, in mm */ + +param bottom, default 15; +/* bottom margin, in mm */ + +param sx := 297 - left - right; +/* chart area horizontal size, in mm */ + +param sy := 210 - top - bottom; +/* chart area vertical size, in mm */ + +param gap, default sy / (na - 1); +/* gap between rosters, in mm */ + +printf "Writing assignment chart to %s...\n", file; + +printf "%%!PS-Adobe-3.0\n" > file; +printf "%%%%Title: Tail Assignment Chart\n" >> file; +printf "%%%%Creator: GLPK MathProg\n" >> file; +printf "%%%%BoundingBox: 0 0 595 842\n" >> file; +printf "%%%%EndComments\n" >> file; +printf "<</PageSize [595 842]>> setpagedevice\n" >> file; +printf "72 25.4 div dup scale\n" >> file; +printf "210 %.3f sub %.3f translate\n", bottom, left >> file; +printf "90 rotate\n" >> file; + +printf "/HelveticaBold findfont 5 scalefont setfont\n" >> file; +printf "%.3f %.3f moveto (%s) dup show\n", 0, sy + 5, title >> file; + +param period := floor((max{f in F} arr2[f]) / 60. + .5); +/* period duration, in hours */ + +/* vertical bars */ +printf ".8 .8 .8 setrgbcolor\n" >> file; +for {tt in 0..period} +{ printf "%s setlinewidth\n", + if tt mod 24 = 0 then ".5" else "0" >> file; + printf "newpath %.3f %.3f moveto %.3f %.3f lineto stroke\n", + tt * (sx / period), 0, tt * (sx / period), + sy + (if tt mod 24 = 0 then 2) >> file; +} + +/* rosters */ +for {a in A} +{ printf "0 0 0 setrgbcolor\n" >> file; + printf "0 setlinewidth\n" >> file; + printf "newpath %.3f %.3f moveto %.3f %.3f lineto stroke\n", + 0, sy - gap * (a - 1), sx, sy - gap * (a - 1) >> file; + printf "/Dingbats findfont 4 scalefont setfont\n" >> file; + printf "%.3f %.3f moveto <28> dup show\n", + -4, sy - gap * (a - 1) - 1.4, a >> file; + printf "/Helvetica findfont 3 scalefont setfont\n" >> file; + printf "%.3f %.3f moveto (%2d) dup show\n", + -9, sy - gap * (a - 1) - 1.2, a >> file; + for {f in F: tail[f] == a} + { printf "0 0 %s setrgbcolor\n", + if hub[f] = 1 then "0" else ".8" >> file; + printf "1 setlinewidth\n" >> file; + printf "newpath %.3f %.3f moveto %.3f %.3f lineto stroke\n", + dep1[f] / 60 * (sx / period), sy - gap * (a - 1), + arr2[f] / 60 * (sx / period), sy - gap * (a - 1) >> file; + printf "/Helvetica findfont 1.8 scalefont setfont\n" >> file; + printf "%.3f %.3f moveto (%02d:%02d %s) dup show\n", + dep1[f] / 60 * (sx / period), sy - gap * (a - 1) + .8, + (dep1[f] mod 1440) div 60, (dep1[f] mod 1440) mod 60, + dest[f] >> file; + printf "%.3f %.3f moveto (%d %02d:%02d) dup show\n", + dep1[f] / 60 * (sx / period), sy - gap * (a - 1) - 2.1, + fno1[f], + (arr2[f] mod 1440) div 60, (arr2[f] mod 1440) mod 60 >> file; + } +} + +printf "showpage\n" >> file; +printf "%%%%EOF\n" >> file; + +######################################################################## + +data; + +param title := "Tu-154 [from 2008-08-18 to 2008-08-24]"; + +param nf := 261; + +param : hub dest fno1 dep1 arr1 fno2 dep2 arr2 := + 1 1 IKT 743 195 520 744 610 970 + 2 1 OMS 815 205 405 816 485 700 + 3 1 CEK 897 205 360 898 430 595 + 4 1 KRR 763 260 400 764 480 610 + 5 2 SIP 133 280 420 134 500 620 + 6 2 BUD 131 290 450 132 520 675 + 7 1 AAQ 701 305 440 702 510 640 + 8 1 MRV 785 310 440 786 520 650 + 9 2 WAW 101 355 475 102 540 660 + 10 2 GYD 147 370 550 148 675 860 + 11 1 AER 869 385 530 870 655 795 + 12 1 KRR 765 430 560 766 630 760 + 13 1 AAQ 703 520 660 704 740 850 + 14 1 LED 845 530 620 846 690 775 + 15 1 KRR 767 540 675 768 765 895 + 16 2 KBP 183 665 760 184 850 940 + 17 1 MRV 787 755 905 788 985 1135 + 18 1 KRR 771 810 940 772 1030 1165 + 19 1 LED 849 825 900 850 960 1095 + 20 2 IST 209 880 1050 210 1120 1280 + 21 1 AER 873 885 1030 874 1760 1900 + 22 1 ASF 711 995 1145 712 1640 1795 + 23 2 ULN 563 995 1335 564 1415 1815 + 24 2 OTP 151 1020 1175 152 1800 1940 + 25 2 BEY 509 1025 1265 510 1350 1580 + 26 2 OSL 211 1060 1220 212 1860 2015 + 27 1 IKT 739 1085 1420 740 1510 1870 + 28 1 KRR 773 1095 1240 774 1620 1765 + 29 1 SGC 877 1120 1315 878 1395 1625 + 30 1 LED 857 1150 1230 858 1610 1690 + 31 1 CEK 899 1230 1385 900 1455 1620 + 32 1 PEE 821 1235 1390 822 1450 1600 + 33 2 TBS 197 1240 1405 198 1560 1715 + 34 1 UFA 891 1275 1405 892 1475 1610 + 35 1 KJA 781 1300 1570 782 1680 1990 + 36 1 IKT 743 1635 1960 744 2050 2410 + 37 1 OMS 815 1645 1845 816 1925 2140 + 38 1 CEK 897 1645 1800 898 1870 2035 + 39 1 KRR 763 1700 1840 764 1920 2050 + 40 2 SIP 133 1720 1860 134 1940 2060 + 41 2 BUD 131 1730 1890 132 1960 2115 + 42 1 AAQ 701 1745 1880 702 1950 2080 + 43 1 MRV 785 1750 1880 786 1960 2090 + 44 2 WAW 101 1795 1915 102 1980 2100 + 45 2 GYD 147 1810 1990 148 2115 2300 + 46 1 AER 869 1825 1970 870 2095 2235 + 47 2 EVN 193 1850 2030 194 2105 2275 + 48 1 KRR 765 1870 2000 766 2070 2200 + 49 1 AAQ 703 1960 2100 704 2180 2290 + 50 1 LED 845 1970 2060 846 2130 2215 + 51 1 KRR 767 1980 2115 768 2205 2335 + 52 2 KBP 183 2105 2200 184 2290 2380 + 53 1 MRV 787 2195 2345 788 2425 2575 + 54 1 KRR 771 2250 2380 772 2470 2605 + 55 1 LED 849 2265 2340 850 2400 2535 + 56 2 IST 209 2320 2490 210 2560 2720 + 57 1 AER 873 2325 2470 874 3200 3340 + 58 2 ULN 563 2435 2775 564 2855 3255 + 59 1 ASF 711 2435 2585 712 3080 3235 + 60 2 DAM 517 2465 2705 518 2790 3020 + 61 2 OSL 211 2500 2660 212 3300 3455 + 62 2 KBP 185 2510 2610 186 3160 3250 + 63 1 IKT 739 2525 2860 740 2950 3310 + 64 1 KRR 773 2535 2680 774 3060 3205 + 65 1 SGC 877 2560 2755 878 2835 3065 + 66 1 LED 857 2590 2670 858 3050 3130 + 67 1 CEK 899 2670 2825 900 2895 3060 + 68 1 PEE 821 2675 2830 822 2890 3040 + 69 2 TBS 197 2680 2845 198 3000 3155 + 70 1 UFA 891 2715 2845 892 2915 3050 + 71 1 KJA 781 2740 3010 782 3120 3430 + 72 1 IKT 743 3075 3400 744 3490 3850 + 73 1 CEK 897 3085 3240 898 3310 3475 + 74 1 OMS 815 3085 3285 816 3365 3580 + 75 1 KRR 763 3140 3280 764 3360 3490 + 76 2 SIP 133 3160 3300 134 3380 3500 + 77 2 BUD 131 3170 3330 132 3400 3555 + 78 1 AAQ 701 3185 3320 702 3390 3520 + 79 1 MRV 785 3190 3320 786 3400 3530 + 80 2 WAW 101 3235 3355 102 3420 3540 + 81 2 FRU 181 3245 3495 182 3590 3860 + 82 2 GYD 147 3250 3430 148 3555 3740 + 83 1 AER 869 3265 3410 870 3535 3675 + 84 1 KRR 765 3310 3440 766 3510 3640 + 85 1 AAQ 703 3400 3540 704 3620 3730 + 86 1 LED 845 3410 3500 846 3570 3655 + 87 1 KRR 767 3420 3555 768 3645 3775 + 88 2 KBP 183 3545 3640 184 3730 3820 + 89 1 MRV 787 3635 3785 788 3865 4015 + 90 1 KRR 771 3690 3820 772 3910 4045 + 91 1 LED 849 3705 3780 850 3840 3975 + 92 2 IST 209 3760 3930 210 4000 4160 + 93 1 AER 873 3765 3910 874 4640 4780 + 94 2 ULN 563 3875 4215 564 4295 4695 + 95 1 ASF 711 3875 4025 712 4520 4675 + 96 2 OTP 151 3900 4055 152 4680 4820 + 97 2 BEY 509 3905 4145 510 4230 4460 + 98 2 OSL 211 3940 4100 212 4740 4895 + 99 2 KBP 185 3950 4050 186 4600 4690 + 100 1 IKT 739 3965 4300 740 4390 4750 + 101 1 KRR 773 3975 4120 774 4500 4645 + 102 1 SGC 877 4000 4195 878 4275 4505 + 103 1 LED 857 4030 4110 858 4490 4570 + 104 1 CEK 899 4110 4265 900 4335 4500 + 105 1 PEE 821 4115 4270 822 4330 4480 + 106 2 TBS 197 4120 4285 198 4440 4595 + 107 1 UFA 891 4155 4285 892 4355 4490 + 108 1 KJA 781 4180 4450 782 4560 4870 + 109 1 IKT 743 4515 4840 744 4930 5290 + 110 1 OMS 815 4525 4725 816 4805 5020 + 111 1 CEK 897 4525 4680 898 4750 4915 + 112 1 KRR 763 4580 4720 764 4800 4930 + 113 2 SIP 133 4600 4740 134 4820 4940 + 114 2 BUD 131 4610 4770 132 4840 4995 + 115 1 AAQ 701 4625 4760 702 4830 4960 + 116 1 MRV 785 4630 4760 786 4840 4970 + 117 2 WAW 101 4675 4795 102 4860 4980 + 118 2 GYD 147 4690 4870 148 4995 5180 + 119 1 AER 869 4705 4850 870 4975 5115 + 120 2 EVN 193 4730 4910 194 4985 5155 + 121 1 KRR 765 4750 4880 766 4950 5080 + 122 1 AAQ 703 4840 4980 704 5060 5170 + 123 1 LED 845 4850 4940 846 5010 5095 + 124 1 KRR 767 4860 4995 768 5085 5215 + 125 2 KBP 183 4985 5080 184 5170 5260 + 126 1 MRV 787 5075 5225 788 5305 5455 + 127 1 KRR 771 5130 5260 772 5350 5485 + 128 1 LED 849 5145 5220 850 5280 5415 + 129 2 IST 209 5200 5370 210 5440 5600 + 130 1 AER 873 5205 5350 874 6080 6220 + 131 1 ASF 711 5315 5465 712 5960 6115 + 132 2 ULN 563 5315 5655 564 5735 6135 + 133 2 DAM 517 5345 5585 518 5670 5900 + 134 2 OSL 211 5380 5540 212 6180 6335 + 135 2 KBP 185 5390 5490 186 6040 6130 + 136 1 IKT 739 5405 5740 740 5830 6190 + 137 1 KRR 773 5415 5560 774 5940 6085 + 138 1 SGC 877 5440 5635 878 5715 5945 + 139 1 LED 857 5470 5550 858 5930 6010 + 140 1 CEK 899 5550 5705 900 5775 5940 + 141 1 PEE 821 5555 5710 822 5770 5920 + 142 2 TBS 197 5560 5725 198 5880 6035 + 143 1 UFA 891 5595 5725 892 5795 5930 + 144 1 KJA 781 5620 5890 782 6000 6310 + 145 1 IKT 743 5955 6280 744 6370 6730 + 146 1 OMS 815 5965 6165 816 6245 6460 + 147 1 CEK 897 5965 6120 898 6190 6355 + 148 1 KRR 763 6020 6160 764 6240 6370 + 149 2 SIP 133 6040 6180 134 6260 6380 + 150 2 BUD 131 6050 6210 132 6280 6435 + 151 1 AAQ 701 6065 6200 702 6270 6400 + 152 1 MRV 785 6070 6200 786 6280 6410 + 153 2 WAW 101 6115 6235 102 6300 6420 + 154 2 FRU 181 6125 6375 182 6470 6740 + 155 2 GYD 147 6130 6310 148 6435 6620 + 156 1 AER 869 6145 6290 870 6415 6555 + 157 2 EVN 193 6170 6350 194 6425 6595 + 158 1 KRR 765 6190 6320 766 6390 6520 + 159 1 AAQ 703 6280 6420 704 6500 6610 + 160 1 LED 845 6290 6380 846 6450 6535 + 161 1 KRR 767 6300 6435 768 6525 6655 + 162 2 KBP 183 6425 6520 184 6610 6700 + 163 2 AYT 223 6500 6690 224 6750 6940 + 164 1 AER 867 6510 6660 868 6730 6880 + 165 1 MRV 787 6515 6665 788 6745 6895 + 166 1 KRR 771 6570 6700 772 6790 6925 + 167 1 LED 849 6585 6660 850 6720 6855 + 168 2 IST 209 6640 6810 210 6880 7040 + 169 1 AER 873 6645 6790 874 7520 7660 + 170 1 ASF 711 6755 6905 712 7400 7555 + 171 2 ULN 563 6755 7095 564 7175 7575 + 172 2 OTP 151 6780 6935 152 7560 7700 + 173 2 BEY 509 6785 7025 510 7110 7340 + 174 2 OSL 211 6820 6980 212 7620 7775 + 175 2 KBP 185 6830 6930 186 7480 7570 + 176 1 IKT 739 6845 7180 740 7270 7630 + 177 1 KRR 773 6855 7000 774 7380 7525 + 178 1 SGC 877 6880 7075 878 7155 7385 + 179 1 LED 857 6910 6990 858 7370 7450 + 180 1 CEK 899 6990 7145 900 7215 7380 + 181 1 PEE 821 6995 7150 822 7210 7360 + 182 2 TBS 197 7000 7165 198 7320 7475 + 183 1 UFA 891 7035 7165 892 7235 7370 + 184 1 KJA 781 7060 7330 782 7440 7750 + 185 1 IKT 743 7395 7720 744 7810 8170 + 186 1 CEK 897 7405 7560 898 7630 7795 + 187 1 KRR 763 7460 7600 764 7680 7810 + 188 2 SIP 133 7480 7620 134 7700 7820 + 189 2 BUD 131 7490 7650 132 7720 7875 + 190 1 AAQ 701 7505 7640 702 7710 7840 + 191 1 MRV 785 7510 7640 786 7720 7850 + 192 2 IST 207 7545 7720 208 7795 7985 + 193 2 WAW 101 7555 7675 102 7740 7860 + 194 2 GYD 147 7570 7750 148 7875 8060 + 195 1 AER 869 7585 7730 870 7855 7995 + 196 2 AYT 221 7610 7800 222 7895 8085 + 197 2 EVN 193 7610 7790 194 7865 8035 + 198 1 KRR 765 7630 7760 766 7830 7960 + 199 1 AAQ 703 7720 7860 704 7940 8050 + 200 1 LED 845 7730 7820 846 7890 7975 + 201 1 KRR 767 7740 7875 768 7965 8095 + 202 2 KBP 183 7865 7960 184 8050 8140 + 203 2 AYT 223 7940 8130 224 8190 8380 + 204 1 MRV 787 7955 8105 788 8185 8335 + 205 1 KRR 771 8010 8140 772 8230 8365 + 206 1 LED 849 8025 8100 850 8160 8295 + 207 2 IST 209 8080 8250 210 8320 8480 + 208 1 AER 873 8085 8230 874 8960 9100 + 209 1 ASF 711 8195 8345 712 8840 8995 + 210 2 ULN 563 8195 8535 564 8615 9015 + 211 1 KJA 779 8230 8500 780 8575 8870 + 212 2 OSL 211 8260 8420 212 9060 9215 + 213 2 KBP 185 8270 8370 186 8920 9010 + 214 1 IKT 739 8285 8620 740 8710 9070 + 215 1 KRR 773 8295 8440 774 8820 8965 + 216 1 SGC 877 8320 8515 878 8595 8825 + 217 1 LED 857 8350 8430 858 8810 8890 + 218 1 CEK 899 8430 8585 900 8655 8820 + 219 1 PEE 821 8435 8590 822 8650 8800 + 220 2 TBS 197 8440 8605 198 8760 8915 + 221 1 UFA 891 8475 8605 892 8675 8810 + 222 1 KJA 781 8500 8770 782 8880 9190 + 223 1 IKT 743 8835 9160 744 9250 9610 + 224 1 OMS 815 8845 9045 816 9125 9340 + 225 1 CEK 897 8845 9000 898 9070 9235 + 226 1 KRR 763 8900 9040 764 9120 9250 + 227 2 SIP 133 8920 9060 134 9140 9260 + 228 2 BUD 131 8930 9090 132 9160 9315 + 229 1 AAQ 701 8945 9080 702 9150 9280 + 230 1 MRV 785 8950 9080 786 9160 9290 + 231 2 IST 207 8985 9160 208 9235 9425 + 232 2 WAW 101 8995 9115 102 9180 9300 + 233 2 FRU 181 9005 9255 182 9350 9620 + 234 2 GYD 147 9010 9190 148 9315 9500 + 235 1 AER 869 9025 9170 870 9295 9435 + 236 2 EVN 193 9050 9230 194 9305 9475 + 237 1 KRR 765 9070 9200 766 9270 9400 + 238 1 AAQ 703 9160 9300 704 9380 9490 + 239 1 LED 845 9170 9260 846 9330 9415 + 240 1 KRR 767 9180 9315 768 9405 9535 + 241 2 KBP 183 9305 9400 184 9490 9580 + 242 2 AYT 223 9380 9570 224 9630 9820 + 243 1 MRV 787 9395 9545 788 9625 9775 + 244 1 KRR 771 9450 9580 772 9670 9805 + 245 1 LED 849 9465 9540 850 9600 9735 + 246 2 IST 209 9520 9690 210 9760 9920 + 247 1 AER 873 9525 9670 874 10400 10540 + 248 1 ASF 711 9635 9785 712 10280 10435 + 249 2 ULN 563 9635 9975 564 10055 10455 + 250 2 OTP 151 9660 9815 152 10440 10580 + 251 2 DAM 517 9665 9905 518 9990 10220 + 252 2 OSL 211 9700 9860 212 10500 10655 + 253 2 KBP 185 9710 9810 186 10360 10450 + 254 1 IKT 739 9725 10060 740 10150 10510 + 255 1 KRR 773 9735 9880 774 10260 10405 + 256 1 SGC 877 9760 9955 878 10035 10265 + 257 1 LED 857 9790 9870 858 10250 10330 + 258 1 CEK 899 9870 10025 900 10095 10260 + 259 1 PEE 821 9875 10030 822 10090 10240 + 260 1 UFA 891 9915 10045 892 10115 10250 + 261 1 KJA 781 9940 10210 782 10320 10630 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/todd.mod b/resources/3rdparty/glpk-4.53/examples/todd.mod new file mode 100644 index 000000000..c0ef44b4c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/todd.mod @@ -0,0 +1,36 @@ +/* TODD, a class of hard instances of zero-one knapsack problems */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* Chvatal describes a class of instances of zero-one knapsack problems + due to Todd. He shows that a wide class of algorithms - including all + based on branch and bound or dynamic programming - find it difficult + to solve problems in the Todd class. More exactly, the time required + by these algorithms to solve instances of problems that belong to the + Todd class grows as an exponential function of the problem size. + + Reference: + Chvatal V. (1980), Hard knapsack problems, Op. Res. 28, 1402-1411. */ + +param n > 0 integer; + +param log2_n := log(n) / log(2); + +param k := floor(log2_n); + +param a{j in 1..n} := 2 ** (k + n + 1) + 2 ** (k + n + 1 - j) + 1; + +param b := 0.5 * floor(sum{j in 1..n} a[j]); + +var x{1..n} binary; + +maximize obj: sum{j in 1..n} a[j] * x[j]; + +s.t. cap: sum{j in 1..n} a[j] * x[j] <= b; + +data; + +param n := 15; +/* change this parameter to choose a particular instance */ + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/train.mod b/resources/3rdparty/glpk-4.53/examples/train.mod new file mode 100644 index 000000000..a17520ea1 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/train.mod @@ -0,0 +1,281 @@ +# TRAIN, a model of railroad passenger car allocation +# +# References: +# Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language +# for Mathematical Programming." Management Science 36 (1990) 519-554. + +### SCHEDULE SETS AND PARAMETERS ### + +set cities; + +set links within {c1 in cities, c2 in cities: c1 <> c2}; + + # Set of cities, and set of intercity links + +param last > 0 integer; # Number of time intervals in a day + +set times := 1..last; # Set of time intervals in a day + +set schedule within + {c1 in cities, t1 in times, + c2 in cities, t2 in times: (c1,c2) in links}; + + # Member (c1,t1,c2,t2) of this set represents + # a train that leaves city c1 at time t1 + # and arrives in city c2 at time t2 + +### DEMAND PARAMETERS ### + +param section > 0 integer; + + # Maximum number of cars in one section of a train + +param demand {schedule} > 0; + + # For each scheduled train: + # the smallest number of cars that + # can meet demand for the train + +param low {(c1,t1,c2,t2) in schedule} := ceil(demand[c1,t1,c2,t2]); + + # Minimum number of cars needed to meet demand + +param high {(c1,t1,c2,t2) in schedule} + + := max (2, min (ceil(2*demand[c1,t1,c2,t2]), + section*ceil(demand[c1,t1,c2,t2]/section) )); + + # Maximum number of cars allowed on a train: + # 2 if demand is for less than one car; + # otherwise, lesser of + # number of cars needed to hold twice the demand, and + # number of cars in minimum number of sections needed + +### DISTANCE PARAMETERS ### + +param dist_table {links} >= 0 default 0.0; + +param distance {(c1,c2) in links} > 0 + := if dist_table[c1,c2] > 0 then dist_table[c1,c2] else dist_table[c2,c1]; + + # Inter-city distances: distance[c1,c2] is miles + # between city c1 and city c2 + +### VARIABLES ### + +var U 'cars stored' {cities,times} >= 0; + + # u[c,t] is the number of unused cars stored + # at city c in the interval beginning at time t + +var X 'cars in train' {schedule} >= 0; + + # x[c1,t1,c2,t2] is the number of cars assigned to + # the scheduled train that leaves c1 at t1 and + # arrives in c2 at t2 + +### OBJECTIVES ### + +minimize cars: + sum {c in cities} U[c,last] + + sum {(c1,t1,c2,t2) in schedule: t2 < t1} X[c1,t1,c2,t2]; + + # Number of cars in the system: + # sum of unused cars and cars in trains during + # the last time interval of the day + +minimize miles: + sum {(c1,t1,c2,t2) in schedule} distance[c1,c2] * X[c1,t1,c2,t2]; + + # Total car-miles run by all scheduled trains in a day + +### CONSTRAINTS ### + +account {c in cities, t in times}: + + U[c,t] = U[c, if t > 1 then t-1 else last] + + + sum {(c1,t1,c,t) in schedule} X[c1,t1,c,t] - + sum {(c,t,c2,t2) in schedule} X[c,t,c2,t2]; + + # For every city and time: + # unused cars in the present interval must equal + # unused cars in the previous interval, + # plus cars just arriving in trains, + # minus cars just leaving in trains + +satisfy {(c1,t1,c2,t2) in schedule}: + + low[c1,t1,c2,t2] <= X[c1,t1,c2,t2] <= high[c1,t1,c2,t2]; + + # For each scheduled train: + # number of cars must meet demand, + # but must not be so great that unnecessary + # sections are run + +### DATA ### + +data; + +set cities := BO NY PH WA ; + +set links := (BO,NY) (NY,PH) (PH,WA) + (NY,BO) (PH,NY) (WA,PH) ; + +param dist_table := [*,*] BO NY 232 + NY PH 90 + PH WA 135 ; + +param last := 48 ; + +param section := 14 ; + +set schedule := + + (WA,*,PH,*) 2 5 6 9 8 11 10 13 + 12 15 13 16 14 17 15 18 + 16 19 17 20 18 21 19 22 + 20 23 21 24 22 25 23 26 + 24 27 25 28 26 29 27 30 + 28 31 29 32 30 33 31 34 + 32 35 33 36 34 37 35 38 + 36 39 37 40 38 41 39 42 + 40 43 41 44 42 45 44 47 + 46 1 + + (PH,*,NY,*) 1 3 5 7 9 11 11 13 + 13 15 14 16 15 17 16 18 + 17 19 18 20 19 21 20 22 + 21 23 22 24 23 25 24 26 + 25 27 26 28 27 29 28 30 + 29 31 30 32 31 33 32 34 + 33 35 34 36 35 37 36 38 + 37 39 38 40 39 41 40 42 + 41 43 42 44 43 45 44 46 + 45 47 47 1 + + (NY,*,BO,*) 10 16 12 18 14 20 15 21 + 16 22 17 23 18 24 19 25 + 20 26 21 27 22 28 23 29 + 24 30 25 31 26 32 27 33 + 28 34 29 35 30 36 31 37 + 32 38 33 39 34 40 35 41 + 36 42 37 43 38 44 39 45 + 40 46 41 47 42 48 43 1 + 44 2 45 3 46 4 48 6 + + (BO,*,NY,*) 7 13 9 15 11 17 12 18 + 13 19 14 20 15 21 16 22 + 17 23 18 24 19 25 20 26 + 21 27 22 28 23 29 24 30 + 25 31 26 32 27 33 28 34 + 29 35 30 36 31 37 32 38 + 33 39 34 40 35 41 36 42 + 37 43 38 44 39 45 40 46 + 41 47 43 1 45 3 47 5 + + (NY,*,PH,*) 1 3 12 14 13 15 14 16 + 15 17 16 18 17 19 18 20 + 19 21 20 22 21 23 22 24 + 23 25 24 26 25 27 26 28 + 27 29 28 30 29 31 30 32 + 31 33 32 34 33 35 34 36 + 35 37 36 38 37 39 38 40 + 39 41 40 42 41 43 42 44 + 43 45 44 46 45 47 46 48 + 47 1 + + (PH,*,WA,*) 1 4 14 17 15 18 16 19 + 17 20 18 21 19 22 20 23 + 21 24 22 25 23 26 24 27 + 25 28 26 29 27 30 28 31 + 29 32 30 33 31 34 32 35 + 33 36 34 37 35 38 36 39 + 37 40 38 41 39 42 40 43 + 41 44 42 45 43 46 44 47 + 45 48 46 1 47 2 ; + +param demand := + + [WA,*,PH,*] 2 5 .55 6 9 .01 8 11 .01 + 10 13 .13 12 15 1.59 13 16 1.69 + 14 17 5.19 15 18 3.55 16 19 6.29 + 17 20 4.00 18 21 5.80 19 22 3.40 + 20 23 4.88 21 24 2.92 22 25 4.37 + 23 26 2.80 24 27 4.23 25 28 2.88 + 26 29 4.33 27 30 3.11 28 31 4.64 + 29 32 3.44 30 33 4.95 31 34 3.73 + 32 35 5.27 33 36 3.77 34 37 4.80 + 35 38 3.31 36 39 3.89 37 40 2.65 + 38 41 3.01 39 42 2.04 40 43 2.31 + 41 44 1.52 42 45 1.75 44 47 1.88 + 46 1 1.05 + + [PH,*,NY,*] 1 3 1.05 5 7 .43 9 11 .20 + 11 13 .21 13 15 .40 14 16 6.49 + 15 17 16.40 16 18 9.48 17 19 17.15 + 18 20 9.31 19 21 15.20 20 22 8.21 + 21 23 13.32 22 24 7.35 23 25 11.83 + 24 26 6.61 25 27 10.61 26 28 6.05 + 27 29 9.65 28 30 5.61 29 31 9.25 + 30 32 5.40 31 33 8.24 32 34 4.84 + 33 35 7.44 34 36 4.44 35 37 6.80 + 36 38 4.11 37 39 6.25 38 40 3.69 + 39 41 5.55 40 42 3.29 41 43 4.77 + 42 44 2.91 43 45 4.19 44 46 2.53 + 45 47 4.00 47 1 1.65 + + [NY,*,BO,*] 10 16 1.23 12 18 3.84 14 20 4.08 + 15 21 1.47 16 22 2.96 17 23 1.60 + 18 24 2.95 19 25 1.71 20 26 2.81 + 21 27 1.77 22 28 2.87 23 29 1.84 + 24 30 2.95 25 31 1.91 26 32 3.12 + 27 33 1.93 28 34 3.31 29 35 2.00 + 30 36 3.40 31 37 2.08 32 38 3.41 + 33 39 2.69 34 40 4.45 35 41 2.32 + 36 42 3.40 37 43 1.80 38 44 2.63 + 39 45 1.52 40 46 2.23 41 47 1.25 + 42 48 1.79 43 1 .97 44 2 1.28 + 45 3 .48 46 4 .68 48 6 .08 + + [BO,*,NY,*] 7 13 .03 9 15 1.29 11 17 4.59 + 12 18 2.56 13 19 3.92 14 20 2.37 + 15 21 3.81 16 22 2.24 17 23 3.51 + 18 24 2.13 19 25 3.28 20 26 2.05 + 21 27 3.15 22 28 1.99 23 29 3.09 + 24 30 1.93 25 31 3.19 26 32 1.91 + 27 33 3.21 28 34 1.85 29 35 3.21 + 30 36 1.71 31 37 3.04 32 38 2.08 + 33 39 3.13 34 40 1.96 35 41 2.53 + 36 42 1.43 37 43 2.04 38 44 1.12 + 39 45 1.71 40 46 .91 41 47 1.32 + 43 1 1.80 45 3 1.13 47 5 .23 + + [NY,*,PH,*] 1 3 .04 12 14 4.68 13 15 5.61 + 14 16 3.56 15 17 5.81 16 18 3.81 + 17 19 6.31 18 20 4.07 19 21 7.33 + 20 22 4.55 21 23 7.37 22 24 4.73 + 23 25 7.61 24 26 4.92 25 27 7.91 + 26 28 5.19 27 29 8.40 28 30 5.53 + 29 31 9.32 30 32 5.51 31 33 10.33 + 32 34 9.21 33 35 18.95 34 36 11.23 + 35 37 16.85 36 38 7.29 37 39 10.89 + 38 40 5.41 39 41 8.21 40 42 4.52 + 41 43 6.99 42 44 3.92 43 45 6.21 + 44 46 3.44 45 47 5.17 46 48 2.55 + 47 1 1.24 + + [PH,*,WA,*] 1 4 .20 14 17 4.49 15 18 3.53 + 16 19 2.67 17 20 3.83 18 21 3.01 + 19 22 4.12 20 23 3.15 21 24 4.67 + 22 25 3.20 23 26 4.23 24 27 2.87 + 25 28 3.84 26 29 2.60 27 30 3.80 + 28 31 2.77 29 32 4.31 30 33 3.16 + 31 34 4.88 32 35 3.45 33 36 5.55 + 34 37 3.52 35 38 6.11 36 39 3.32 + 37 40 5.53 38 41 3.03 39 42 4.51 + 40 43 2.53 41 44 3.39 42 45 1.93 + 43 46 2.52 44 47 1.20 45 48 1.75 + 46 1 .88 47 2 .87 ; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/transp.mod b/resources/3rdparty/glpk-4.53/examples/transp.mod new file mode 100644 index 000000000..a7cb939ae --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/transp.mod @@ -0,0 +1,63 @@ +# A TRANSPORTATION PROBLEM +# +# This problem finds a least cost shipping schedule that meets +# requirements at markets and supplies at factories. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* canning plants */ + +set J; +/* markets */ + +param a{i in I}; +/* capacity of plant i in cases */ + +param b{j in J}; +/* demand at market j in cases */ + +param d{i in I, j in J}; +/* distance in thousands of miles */ + +param f; +/* freight in dollars per case per thousand miles */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* transport cost in thousands of dollars per case */ + +var x{i in I, j in J} >= 0; +/* shipment quantities in cases */ + +minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; +/* total transportation costs in thousands of dollars */ + +s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observe supply limit at plant i */ + +s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfy demand at market j */ + +data; + +set I := Seattle San-Diego; + +set J := New-York Chicago Topeka; + +param a := Seattle 350 + San-Diego 600; + +param b := New-York 325 + Chicago 300 + Topeka 275; + +param d : New-York Chicago Topeka := + Seattle 2.5 1.7 1.8 + San-Diego 2.5 1.8 1.4 ; + +param f := 90; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/trick.mod b/resources/3rdparty/glpk-4.53/examples/trick.mod new file mode 100644 index 000000000..df5717b8a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/trick.mod @@ -0,0 +1,72 @@ +/* TRICK, A Transportation Design Problem */ + +/* Translated from the Mosel modeling language to GNU MathProg by + Andrew Makhorin <mao@gnu.org> */ + +/* This example model is described in the article "Formulations and + Reformulations in Integer Programming" by Michael Trick (it is + publicly available at http://mat.gsia.cmu.edu/trick/formul04.pdf). + + This model demonstrates an amazing effect when including in the + formulation an additional constraint, which is redundant even for + LP relaxation, makes the model easy for solving with the B&B. */ + +set TRUCKS := 1..10; + +set PACKAGES := 1..20; + +param capacity{TRUCKS}; + +param size{PACKAGES}; + +param cost{TRUCKS}; + +param can_use{PACKAGES, TRUCKS}; + +var x{PACKAGES, TRUCKS}, binary; + +var y{TRUCKS}, binary; + +minimize total: sum{i in TRUCKS} cost[i] * y[i]; + +f1{i in TRUCKS}: + sum{j in PACKAGES} size[j] * x[j,i] <= capacity[i] * y[i]; + +f2{i in TRUCKS, j in PACKAGES}: + x[j,i] <= y[i]; + +f3{j in PACKAGES}: + sum{i in TRUCKS} can_use[j,i] * x[j,i] = 1; + +redundant_constraint: + sum{i in TRUCKS} capacity[i] * y[i] >= sum{j in PACKAGES} size[j]; + +data; + +param capacity := + [1] 100 [2] 200 [3] 100 [4] 200 [5] 100 [6] 200 [7] 100 [8] 200 + [9] 100 [10] 200; + +param size := + [1] 17 [2] 21 [3] 54 [4] 45 [5] 87 [6] 34 [7] 23 [8] 45 [9] 12 + [10] 43 [11] 54 [12] 39 [13] 31 [14] 26 [15] 75 [16] 48 [17] 16 + [18] 32 [19] 45 [20] 55; + +param cost := + [1] 1 [2] 1.8 [3] 1 [4] 1.8 [5] 1 [6] 1.8 [7] 1 [8] 1.8 [9] 1 + [10] 1.8; + +param can_use (tr): + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 := + 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 + 2 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 0 + 3 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 + 4 0 0 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 + 5 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 + 6 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 + 7 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 + 8 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 + 9 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 + 10 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/tsp.mod b/resources/3rdparty/glpk-4.53/examples/tsp.mod new file mode 100644 index 000000000..358245dae --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/tsp.mod @@ -0,0 +1,335 @@ +/* TSP, Traveling Salesman Problem */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +/* The Traveling Salesman Problem (TSP) is stated as follows. + Let a directed graph G = (V, E) be given, where V = {1, ..., n} is + a set of nodes, E <= V x V is a set of arcs. Let also each arc + e = (i,j) be assigned a number c[i,j], which is the length of the + arc e. The problem is to find a closed path of minimal length going + through each node of G exactly once. */ + +param n, integer, >= 3; +/* number of nodes */ + +set V := 1..n; +/* set of nodes */ + +set E, within V cross V; +/* set of arcs */ + +param c{(i,j) in E}; +/* distance from node i to node j */ + +var x{(i,j) in E}, binary; +/* x[i,j] = 1 means that the salesman goes from node i to node j */ + +minimize total: sum{(i,j) in E} c[i,j] * x[i,j]; +/* the objective is to make the path length as small as possible */ + +s.t. leave{i in V}: sum{(i,j) in E} x[i,j] = 1; +/* the salesman leaves each node i exactly once */ + +s.t. enter{j in V}: sum{(i,j) in E} x[i,j] = 1; +/* the salesman enters each node j exactly once */ + +/* Constraints above are not sufficient to describe valid tours, so we + need to add constraints to eliminate subtours, i.e. tours which have + disconnected components. Although there are many known ways to do + that, I invented yet another way. The general idea is the following. + Let the salesman sell, say, cars, starting the travel from node 1, + where he has n cars. If we require the salesman to sell exactly one + car in each node, he will need to go through all nodes to satisfy + this requirement, thus, all subtours will be eliminated. */ + +var y{(i,j) in E}, >= 0; +/* y[i,j] is the number of cars, which the salesman has after leaving + node i and before entering node j; in terms of the network analysis, + y[i,j] is a flow through arc (i,j) */ + +s.t. cap{(i,j) in E}: y[i,j] <= (n-1) * x[i,j]; +/* if arc (i,j) does not belong to the salesman's tour, its capacity + must be zero; it is obvious that on leaving a node, it is sufficient + to have not more than n-1 cars */ + +s.t. node{i in V}: +/* node[i] is a conservation constraint for node i */ + + sum{(j,i) in E} y[j,i] + /* summary flow into node i through all ingoing arcs */ + + + (if i = 1 then n) + /* plus n cars which the salesman has at starting node */ + + = /* must be equal to */ + + sum{(i,j) in E} y[i,j] + /* summary flow from node i through all outgoing arcs */ + + + 1; + /* plus one car which the salesman sells at node i */ + +solve; + +printf "Optimal tour has length %d\n", + sum{(i,j) in E} c[i,j] * x[i,j]; +printf("From node To node Distance\n"); +printf{(i,j) in E: x[i,j]} " %3d %3d %8g\n", + i, j, c[i,j]; + +data; + +/* These data correspond to the symmetric instance ulysses16 from: + + Reinelt, G.: TSPLIB - A travelling salesman problem library. + ORSA-Journal of the Computing 3 (1991) 376-84; + http://elib.zib.de/pub/Packages/mp-testdata/tsp/tsplib */ + +/* The optimal solution is 6859 */ + +param n := 16; + +param : E : c := + 1 2 509 + 1 3 501 + 1 4 312 + 1 5 1019 + 1 6 736 + 1 7 656 + 1 8 60 + 1 9 1039 + 1 10 726 + 1 11 2314 + 1 12 479 + 1 13 448 + 1 14 479 + 1 15 619 + 1 16 150 + 2 1 509 + 2 3 126 + 2 4 474 + 2 5 1526 + 2 6 1226 + 2 7 1133 + 2 8 532 + 2 9 1449 + 2 10 1122 + 2 11 2789 + 2 12 958 + 2 13 941 + 2 14 978 + 2 15 1127 + 2 16 542 + 3 1 501 + 3 2 126 + 3 4 541 + 3 5 1516 + 3 6 1184 + 3 7 1084 + 3 8 536 + 3 9 1371 + 3 10 1045 + 3 11 2728 + 3 12 913 + 3 13 904 + 3 14 946 + 3 15 1115 + 3 16 499 + 4 1 312 + 4 2 474 + 4 3 541 + 4 5 1157 + 4 6 980 + 4 7 919 + 4 8 271 + 4 9 1333 + 4 10 1029 + 4 11 2553 + 4 12 751 + 4 13 704 + 4 14 720 + 4 15 783 + 4 16 455 + 5 1 1019 + 5 2 1526 + 5 3 1516 + 5 4 1157 + 5 6 478 + 5 7 583 + 5 8 996 + 5 9 858 + 5 10 855 + 5 11 1504 + 5 12 677 + 5 13 651 + 5 14 600 + 5 15 401 + 5 16 1033 + 6 1 736 + 6 2 1226 + 6 3 1184 + 6 4 980 + 6 5 478 + 6 7 115 + 6 8 740 + 6 9 470 + 6 10 379 + 6 11 1581 + 6 12 271 + 6 13 289 + 6 14 261 + 6 15 308 + 6 16 687 + 7 1 656 + 7 2 1133 + 7 3 1084 + 7 4 919 + 7 5 583 + 7 6 115 + 7 8 667 + 7 9 455 + 7 10 288 + 7 11 1661 + 7 12 177 + 7 13 216 + 7 14 207 + 7 15 343 + 7 16 592 + 8 1 60 + 8 2 532 + 8 3 536 + 8 4 271 + 8 5 996 + 8 6 740 + 8 7 667 + 8 9 1066 + 8 10 759 + 8 11 2320 + 8 12 493 + 8 13 454 + 8 14 479 + 8 15 598 + 8 16 206 + 9 1 1039 + 9 2 1449 + 9 3 1371 + 9 4 1333 + 9 5 858 + 9 6 470 + 9 7 455 + 9 8 1066 + 9 10 328 + 9 11 1387 + 9 12 591 + 9 13 650 + 9 14 656 + 9 15 776 + 9 16 933 + 10 1 726 + 10 2 1122 + 10 3 1045 + 10 4 1029 + 10 5 855 + 10 6 379 + 10 7 288 + 10 8 759 + 10 9 328 + 10 11 1697 + 10 12 333 + 10 13 400 + 10 14 427 + 10 15 622 + 10 16 610 + 11 1 2314 + 11 2 2789 + 11 3 2728 + 11 4 2553 + 11 5 1504 + 11 6 1581 + 11 7 1661 + 11 8 2320 + 11 9 1387 + 11 10 1697 + 11 12 1838 + 11 13 1868 + 11 14 1841 + 11 15 1789 + 11 16 2248 + 12 1 479 + 12 2 958 + 12 3 913 + 12 4 751 + 12 5 677 + 12 6 271 + 12 7 177 + 12 8 493 + 12 9 591 + 12 10 333 + 12 11 1838 + 12 13 68 + 12 14 105 + 12 15 336 + 12 16 417 + 13 1 448 + 13 2 941 + 13 3 904 + 13 4 704 + 13 5 651 + 13 6 289 + 13 7 216 + 13 8 454 + 13 9 650 + 13 10 400 + 13 11 1868 + 13 12 68 + 13 14 52 + 13 15 287 + 13 16 406 + 14 1 479 + 14 2 978 + 14 3 946 + 14 4 720 + 14 5 600 + 14 6 261 + 14 7 207 + 14 8 479 + 14 9 656 + 14 10 427 + 14 11 1841 + 14 12 105 + 14 13 52 + 14 15 237 + 14 16 449 + 15 1 619 + 15 2 1127 + 15 3 1115 + 15 4 783 + 15 5 401 + 15 6 308 + 15 7 343 + 15 8 598 + 15 9 776 + 15 10 622 + 15 11 1789 + 15 12 336 + 15 13 287 + 15 14 237 + 15 16 636 + 16 1 150 + 16 2 542 + 16 3 499 + 16 4 455 + 16 5 1033 + 16 6 687 + 16 7 592 + 16 8 206 + 16 9 933 + 16 10 610 + 16 11 2248 + 16 12 417 + 16 13 406 + 16 14 449 + 16 15 636 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/xyacfs.mod b/resources/3rdparty/glpk-4.53/examples/xyacfs.mod new file mode 100644 index 000000000..5a0b22e0e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/xyacfs.mod @@ -0,0 +1,56 @@ +/*Extended Yet Another Curve Fitting Solution (The poor man's RMA) + + An extension of yacfs.mod adding a Weight parameter: + When set to 1 the model produces best fit by least squares with all error in y and none in x (YonX); + When set to zero the model produces best fit by least squares with all error in x and none in y (XonY); + When set to 0.5 the model assumes equal error in x and y producing results similar to fitting by Reduced Major Axis Analysis. + + Nigel_Galloway@operamail.com + November 5th., 2009 +*/ +set Sample; +param Sx {z in Sample}; +param Sy {z in Sample}; +param Weight := 0.5; + +var a; +var b; +var p; +var q; + +XonY1 :sum{z in Sample} q*Sy[z]*Sy[z] + sum{z in Sample} p*Sy[z] = sum{z in Sample} Sy[z]*Sx[z]; +XonY2 :sum{z in Sample} q*Sy[z] + sum{z in Sample} p = sum{z in Sample} Sx[z]; +YonX1 :sum{z in Sample} a*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]; +YonX2 :sum{z in Sample} a*Sx[z] + sum{z in Sample} b = sum{z in Sample} Sy[z]; + +solve; + +param W := Weight*a + (1-Weight)*(1/q); +printf "\nbest linear fit is:\n\ty = %f %s %fx\n\n", b*Weight - (1-Weight)*(p/q), if W < 0 then "-" else "+", abs(W); + +data; + +param: +Sample: Sx Sy := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/yacfs.mod b/resources/3rdparty/glpk-4.53/examples/yacfs.mod new file mode 100644 index 000000000..270f2a083 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/yacfs.mod @@ -0,0 +1,48 @@ +/*Yet Another Curve Fitting Solution + + Obviously this solution produces the same answer + as examples/cflsq.mod + + Nigel_Galloway@operamail.com + February 1st., 2009 +*/ +set Sample; +param Sx {z in Sample}; +param Sy {z in Sample}; + +var a; +var b; + +equalz1 :sum{z in Sample} a*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]; +equalz2 :sum{z in Sample} a*Sx[z] + sum{z in Sample} b = sum{z in Sample} Sy[z]; + +solve; + +printf "\nbest linear fit is:\n\ty = %f %s %fx\n\n", b, if a < 0 then "-" else "+", abs(a); + +data; + +param: +Sample: Sx Sy := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/zebra.mod b/resources/3rdparty/glpk-4.53/examples/zebra.mod new file mode 100644 index 000000000..66f8c1aaf --- /dev/null +++ b/resources/3rdparty/glpk-4.53/examples/zebra.mod @@ -0,0 +1,151 @@ +/* ZEBRA, Who Owns the Zebra? */ + +/* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */ + +######################################################################## +# The Zebra Puzzle is a well-known logic puzzle. +# +# It is often called "Einstein's Puzzle" or "Einstein's Riddle" +# because it is said to have been invented by Albert Einstein as a boy, +# with the common claim that Einstein said "only 2 percent of the +# world's population can solve". It is also sometimes attributed to +# Lewis Carroll. However, there is no known evidence for Einstein's or +# Carroll's authorship. +# +# There are several versions of this puzzle. The version below is +# quoted from the first known publication in Life International +# magazine on December 17, 1962. +# +# 1. There are five houses. +# 2. The Englishman lives in the red house. +# 3. The Spaniard owns the dog. +# 4. Coffee is drunk in the green house. +# 5. The Ukrainian drinks tea. +# 6. The green house is immediately to the right of the ivory house. +# 7. The Old Gold smoker owns snails. +# 8. Kools are smoked in the yellow house. +# 9. Milk is drunk in the middle house. +# 10. The Norwegian lives in the first house. +# 11. The man who smokes Chesterfields lives in the house next to the +# man with the fox. +# 12. Kools are smoked in the house next to the house where the horse +# is kept. +# 13. The Lucky Strike smoker drinks orange juice. +# 14. The Japanese smokes Parliaments. +# 15. The Norwegian lives next to the blue house. +# +# Now, who drinks water? Who owns the zebra? +# +# In the interest of clarity, it must be added that each of the five +# houses is painted a different color, and their inhabitants are of +# different national extractions, own different pets, drink different +# beverages and smoke different brands of American cigarettes. One +# other thing: In statement 6, right means your right. +# +# (From Wikipedia, the free encyclopedia.) +######################################################################## + +set HOUSE := { 1..5 }; + +set COLOR := { "blue", "green", "ivory", "red", "yellow" }; + +set NATIONALITY := { "Englishman", "Japanese", "Norwegian", "Spaniard", + "Ukranian" }; + +set DRINK := { "coffee", "milk", "orange_juice", "tea", "water" }; + +set SMOKE := { "Chesterfield", "Kools", "Lucky_Strike", "Old_Gold", + "Parliament" }; + +set PET := { "dog", "fox", "horse", "snails", "zebra" }; + +var color{HOUSE, COLOR}, binary; +c1{h in HOUSE}: sum{c in COLOR} color[h,c] = 1; +c2{c in COLOR}: sum{h in HOUSE} color[h,c] = 1; + +var nationality{HOUSE, NATIONALITY}, binary; +n1{h in HOUSE}: sum{n in NATIONALITY} nationality[h,n] = 1; +n2{n in NATIONALITY}: sum{h in HOUSE} nationality[h,n] = 1; + +var drink{HOUSE, DRINK}, binary; +d1{h in HOUSE}: sum{d in DRINK} drink[h,d] = 1; +d2{d in DRINK}: sum{h in HOUSE} drink[h,d] = 1; + +var smoke{HOUSE, SMOKE}, binary; +s1{h in HOUSE}: sum{s in SMOKE} smoke[h,s] = 1; +s2{s in SMOKE}: sum{h in HOUSE} smoke[h,s] = 1; + +var pet{HOUSE, PET}, binary; +p1{h in HOUSE}: sum{p in PET} pet[h,p] = 1; +p2{p in PET}: sum{h in HOUSE} pet[h,p] = 1; + +/* the Englishman lives in the red house */ +f2{h in HOUSE}: nationality[h,"Englishman"] = color[h,"red"]; + +/* the Spaniard owns the dog */ +f3{h in HOUSE}: nationality[h,"Spaniard"] = pet[h,"dog"]; + +/* coffee is drunk in the green house */ +f4{h in HOUSE}: drink[h,"coffee"] = color[h,"green"]; + +/* the Ukrainian drinks tea */ +f5{h in HOUSE}: nationality[h,"Ukranian"] = drink[h,"tea"]; + +/* the green house is immediately to the right of the ivory house */ +f6{h in HOUSE}: + color[h,"green"] = if h = 1 then 0 else color[h-1,"ivory"]; + +/* the Old Gold smoker owns snails */ +f7{h in HOUSE}: smoke[h,"Old_Gold"] = pet[h,"snails"]; + +/* Kools are smoked in the yellow house */ +f8{h in HOUSE}: smoke[h,"Kools"] = color[h,"yellow"]; + +/* milk is drunk in the middle house */ +f9: drink[3,"milk"] = 1; + +/* the Norwegian lives in the first house */ +f10: nationality[1,"Norwegian"] = 1; + +/* the man who smokes Chesterfields lives in the house next to the man + with the fox */ +f11{h in HOUSE}: + (1 - smoke[h,"Chesterfield"]) + + (if h = 1 then 0 else pet[h-1,"fox"]) + + (if h = 5 then 0 else pet[h+1,"fox"]) >= 1; + +/* Kools are smoked in the house next to the house where the horse is + kept */ +f12{h in HOUSE}: + (1 - smoke[h,"Kools"]) + + (if h = 1 then 0 else pet[h-1,"horse"]) + + (if h = 5 then 0 else pet[h+1,"horse"]) >= 1; + +/* the Lucky Strike smoker drinks orange juice */ +f13{h in HOUSE}: smoke[h,"Lucky_Strike"] = drink[h,"orange_juice"]; + +/* the Japanese smokes Parliaments */ +f14{h in HOUSE}: nationality[h,"Japanese"] = smoke[h,"Parliament"]; + +/* the Norwegian lives next to the blue house */ +f15{h in HOUSE}: + (1 - nationality[h,"Norwegian"]) + + (if h = 1 then 0 else color[h-1,"blue"]) + + (if h = 5 then 0 else color[h+1,"blue"]) >= 1; + +solve; + +printf "\n"; +printf "HOUSE COLOR NATIONALITY DRINK SMOKE PET\n"; +for {h in HOUSE} +{ printf "%5d", h; + printf{c in COLOR: color[h,c]} " %-6s", c; + printf{n in NATIONALITY: nationality[h,n]} " %-11s", n; + printf{d in DRINK: drink[h,d]} " %-12s", d; + printf{s in SMOKE: smoke[h,s]} " %-12s", s; + printf{p in PET: pet[h,p]} " %-6s", p; + printf "\n"; +} +printf "\n"; + +end; diff --git a/resources/3rdparty/glpk-4.53/install-sh b/resources/3rdparty/glpk-4.53/install-sh new file mode 100644 index 000000000..377bb8687 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# 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. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +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: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -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. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; 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 + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + 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 "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # 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: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # 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 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $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 $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 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. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/resources/3rdparty/glpk-4.53/ltmain.sh b/resources/3rdparty/glpk-4.53/ltmain.sh new file mode 100644 index 000000000..fcebbcb5f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/ltmain.sh @@ -0,0 +1,9687 @@ + +# libtool (GNU libtool) 2.4 +# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010 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. + +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [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 +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message +# +# 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. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to <bug-libtool@gnu.org>. +# GNU libtool home page: <http://www.gnu.org/software/libtool/>. +# General help using GNU software: <http://www.gnu.org/gethelp/>. + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4 +TIMESTAMP="" +package_revision=1.3294 + +# 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+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# NLS nuisances: We save the old values to restore during execute mode. +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL + +$lt_unset CDPATH + + +# 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" + + + +: ${CP="cp -f"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${EGREP="/usr/bin/grep -E"} +: ${FGREP="/usr/bin/grep -F"} +: ${GREP="/usr/bin/grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="/usr/bin/sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation + + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation + + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation + + +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} + +# The name of this program: +func_dirname_and_basename "$progpath" +progname=$func_basename_result + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +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 that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' + +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + done + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# 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 "$opt_dry_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" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "$my_tmpdir" +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "$1" | $SED \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $opt_debug + + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $opt_debug + + $SED -n '/^# Usage:/,/^# *.*--help/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + echo + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. +func_help () +{ + $opt_debug + + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $opt_debug + + func_error "missing argument for $1." + exit_cmd=exit +} + + +# func_split_short_opt shortopt +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +func_split_short_opt () +{ + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation + + +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () +{ + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' + + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation + +exit_cmd=: + + + + + +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" + +# Global variables. +nonopt= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +# 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= + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "${1}=\$${1}\${2}" +} # func_append may be replaced by extended shell implementation + +# func_append_quoted var value +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +func_append_quoted () +{ + func_quote_for_eval "${2}" + eval "${1}=\$${1}\\ \$func_quote_for_eval_result" +} # func_append_quoted may be replaced by extended shell implementation + + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "${@}"` +} # func_arith may be replaced by extended shell implementation + + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation + + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation + + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation + + +# func_fatal_configuration arg... +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." +} + + +# func_config +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + +# func_features +# Display the features supported by this script. +func_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 $? +} + +# func_enable_tag tagname +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname="$1" + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac + + + +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_verbose=: +opt_silent=false +opt_verbose=false + + +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. +{ + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done + + # Validate options: + + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift + fi + + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } + + + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE +} + + + + +## ----------- ## +## Main. ## +## ----------- ## + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE 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. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case "$lt_sysroot:$1" in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result="=$func_stripname_result" + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# 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 () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + 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 "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # 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. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # 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 + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T <<EOF +# $write_libobj - a libtool object file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object=$write_lobj + +# Name of the non-PIC object +non_pic_object=$write_oldobj + +EOF + $MV "${write_libobj}T" "${write_libobj}" + } +} + + +################################################## +# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS # +################################################## + +# func_convert_core_file_wine_to_w32 ARG +# Helper function used by file name conversion functions when $build is *nix, +# and $host is mingw, cygwin, or some other w32 environment. Relies on a +# correctly configured wine environment available, with the winepath program +# in $build's $PATH. +# +# ARG is the $build file name to be converted to w32 format. +# Result is available in $func_convert_core_file_wine_to_w32_result, and will +# be empty on error (or when ARG is empty) +func_convert_core_file_wine_to_w32 () +{ + $opt_debug + func_convert_core_file_wine_to_w32_result="$1" + if test -n "$1"; then + # Unfortunately, winepath does not exit with a non-zero error code, so we + # are forced to check the contents of stdout. On the other hand, if the + # command is not found, the shell will set an exit code of 127 and print + # *an error message* to stdout. So we must check for both error code of + # zero AND non-empty stdout, which explains the odd construction: + func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null` + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$lt_sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $opt_debug + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result="" + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $opt_debug + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $opt_debug + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $opt_debug + if test -z "$2" && test -n "$1" ; then + func_error "Could not determine host file name corresponding to" + func_error " \`$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result="$1" + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $opt_debug + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " \`$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result="$3" + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $opt_debug + case $4 in + $1 ) func_to_host_path_result="$3$func_to_host_path_result" + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via `$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $opt_debug + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $opt_debug + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result="$1" +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result="$func_convert_core_msys_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via `$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $opt_debug + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd="func_convert_path_${func_stripname_result}" + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $opt_debug + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result="$1" +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_mode_compile arg... +func_mode_compile () +{ + $opt_debug + # 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= + pie_flag= + + 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) + test -n "$libobj" && \ + func_fatal_error "you cannot specify \`-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append 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,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + func_append_quoted lastarg "$arg" + done + IFS="$save_ifs" + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append 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. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with \`-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj="$func_basename_result" + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from \`$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # 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 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + 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 "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + 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 $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "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." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/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." + + $opt_dry_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 + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/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." + + $opt_dry_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 + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [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: $progname [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 + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +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: $progname [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: $progname [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: $progname [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 following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [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 + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -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 + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +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: $progname [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." + ;; + + *) + func_fatal_help "invalid operation mode \`$opt_mode'" + ;; + esac + + echo + $ECHO "Try \`$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test "$opt_help" = :; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | sed -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + sed '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + 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 + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # 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 +} + +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "\`$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument \`$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + 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" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # 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. + case $nonopt in *shtool*) :;; *) false;; esac; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + 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. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + func_append 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 -e "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. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + 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 + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_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 + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append 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 + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_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 + func_basename "$file" + destfile="$func_basename_result" + 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 + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "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) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename="$func_basename_result" + else + # no lafile. user explicitly requested -dlpreopen <import library>. + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # 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 >/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/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + 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*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + 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 "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# 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. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $opt_debug + 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 + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $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_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $opt_debug + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $opt_debug + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1" ; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result="" + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + 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 + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_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've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# 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. +sed_quote_subst='$sed_quote_subst' + +# 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+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# 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 variables: + generated_by_libtool_version='$macro_version' + 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 + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED '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 \"\$file\" | $SED '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 \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + 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 "\ + + # 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 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # 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 \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + 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 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat <<EOF + +/* $cwrappersource - temporary wrapper executable for $objdir/$outputname + Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION + + The $output program cannot be directly executed until all the libtool + libraries that it depends on are installed. + + This wrapper executable should never be moved out of the build directory. + If it is, it will not operate correctly. +*/ +EOF + cat <<"EOF" +#ifdef _MSC_VER +# define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#include <stdio.h> +#include <stdlib.h> +#ifdef _MSC_VER +# include <direct.h> +# include <process.h> +# include <io.h> +#else +# include <unistd.h> +# include <stdint.h> +# ifdef __CYGWIN__ +# include <io.h> +# endif +#endif +#include <malloc.h> +#include <stdarg.h> +#include <assert.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> + +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#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 +# define FOPEN_WB "wb" +# 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 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <<EOF +volatile const char * MAGIC_EXE = "$magic_exe"; +const char * LIB_PATH_VARNAME = "$shlibpath_var"; +EOF + + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + func_to_host_path "$temp_rpath" + cat <<EOF +const char * LIB_PATH_VALUE = "$func_to_host_path_result"; +EOF + else + cat <<"EOF" +const char * LIB_PATH_VALUE = ""; +EOF + fi + + if test -n "$dllsearchpath"; then + func_to_host_path "$dllsearchpath:" + cat <<EOF +const char * EXE_PATH_VARNAME = "PATH"; +const char * EXE_PATH_VALUE = "$func_to_host_path_result"; +EOF + else + cat <<"EOF" +const char * EXE_PATH_VARNAME = ""; +const char * EXE_PATH_VALUE = ""; +EOF + fi + + if test "$fast_install" = yes; then + cat <<EOF +const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */ +EOF + else + cat <<EOF +const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */ +EOF + fi + + + cat <<"EOF" + +#define LTWRAPPER_OPTION_PREFIX "--lt-" + +static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX; +static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script"; +static const char *debug_opt = LTWRAPPER_OPTION_PREFIX "debug"; + +int +main (int argc, char *argv[]) +{ + char **newargz; + int newargc; + char *tmp_pathspec; + char *actual_cwrapper_path; + char *actual_cwrapper_name; + char *target_name; + char *lt_argv_zero; + intptr_t rval = 127; + + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + newargz = XMALLOC (char *, argc + 1); + + /* very simple arg parsing; don't want to rely on getopt + * also, copy all non cwrapper options to newargz, except + * argz[0], which is handled differently + */ + newargc=0; + for (i = 1; i < argc; i++) + { + if (strcmp (argv[i], dumpscript_opt) == 0) + { +EOF + case "$host" in + *mingw* | *cygwin* ) + # make stdout use "unix" line endings + echo " setmode(1,_O_BINARY);" + ;; + esac + + cat <<"EOF" + lt_dump_script (stdout); + return 0; + } + if (strcmp (argv[i], debug_opt) == 0) + { + lt_debug = 1; + continue; + } + if (strcmp (argv[i], ltwrapper_option_prefix) == 0) + { + /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX + namespace, but it is not one of the ones we know about and + have already dealt with, above (inluding dump-script), then + report an error. Otherwise, targets might begin to believe + they are allowed to use options in the LTWRAPPER_OPTION_PREFIX + namespace. The first time any user complains about this, we'll + need to make LTWRAPPER_OPTION_PREFIX a configure-time option + or a configure.ac-settable value. + */ + lt_fatal (__FILE__, __LINE__, + "unrecognized %s option: '%s'", + ltwrapper_option_prefix, argv[i]); + } + /* otherwise ... */ + newargz[++newargc] = xstrdup (argv[i]); + } + newargz[++newargc] = NULL; + +EOF + cat <<EOF + /* The GNU banner must be the first non-error debug message */ + lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\n"); +EOF + cat <<"EOF" + lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]); + lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name); + + tmp_pathspec = find_executable (argv[0]); + if (tmp_pathspec == NULL) + lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]); + lt_debugprintf (__FILE__, __LINE__, + "(main) found exe (before symlink chase) at: %s\n", + tmp_pathspec); + + actual_cwrapper_path = chase_symlinks (tmp_pathspec); + lt_debugprintf (__FILE__, __LINE__, + "(main) found exe (after symlink chase) at: %s\n", + actual_cwrapper_path); + XFREE (tmp_pathspec); + + actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path)); + strendzap (actual_cwrapper_path, actual_cwrapper_name); + + /* wrapper name transforms */ + strendzap (actual_cwrapper_name, ".exe"); + tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1); + XFREE (actual_cwrapper_name); + actual_cwrapper_name = tmp_pathspec; + tmp_pathspec = 0; + + /* target_name transforms -- use actual target program name; might have lt- prefix */ + target_name = xstrdup (base_name (TARGET_PROGRAM_NAME)); + strendzap (target_name, ".exe"); + tmp_pathspec = lt_extend_str (target_name, ".exe", 1); + XFREE (target_name); + target_name = tmp_pathspec; + tmp_pathspec = 0; + + lt_debugprintf (__FILE__, __LINE__, + "(main) libtool target name: %s\n", + target_name); +EOF + + cat <<EOF + newargz[0] = + XMALLOC (char, (strlen (actual_cwrapper_path) + + strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1)); + strcpy (newargz[0], actual_cwrapper_path); + strcat (newargz[0], "$objdir"); + strcat (newargz[0], "/"); +EOF + + cat <<"EOF" + /* stop here, and copy so we don't have to do this twice */ + tmp_pathspec = xstrdup (newargz[0]); + + /* do NOT want the lt- prefix here, so use actual_cwrapper_name */ + strcat (newargz[0], actual_cwrapper_name); + + /* DO want the lt- prefix here if it exists, so use target_name */ + lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1); + XFREE (tmp_pathspec); + tmp_pathspec = NULL; +EOF + + case $host_os in + mingw*) + cat <<"EOF" + { + char* p; + while ((p = strchr (newargz[0], '\\')) != NULL) + { + *p = '/'; + } + while ((p = strchr (lt_argv_zero, '\\')) != NULL) + { + *p = '/'; + } + } +EOF + ;; + esac + + cat <<"EOF" + XFREE (target_name); + XFREE (actual_cwrapper_path); + XFREE (actual_cwrapper_name); + + lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */ + lt_setenv ("DUALCASE", "1"); /* for MSK sh */ + /* Update the DLL searchpath. EXE_PATH_VALUE ($dllsearchpath) must + be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath) + because on Windows, both *_VARNAMEs are PATH but uninstalled + libraries must come first. */ + lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE); + lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE); + + lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n", + nonnull (lt_argv_zero)); + for (i = 0; i < newargc; i++) + { + lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n", + i, nonnull (newargz[i])); + } + +EOF + + case $host_os in + mingw*) + cat <<"EOF" + /* execv doesn't actually work on mingw as expected on unix */ + newargz = prepare_spawn (newargz); + rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); + if (rval == -1) + { + /* failed to start process */ + lt_debugprintf (__FILE__, __LINE__, + "(main) failed to launch target \"%s\": %s\n", + lt_argv_zero, nonnull (strerror (errno))); + return 127; + } + return rval; +EOF + ;; + *) + cat <<"EOF" + execv (lt_argv_zero, newargz); + return rval; /* =127, but avoids unused variable warning */ +EOF + ;; + esac + + cat <<"EOF" +} + +void * +xmalloc (size_t num) +{ + void *p = (void *) malloc (num); + if (!p) + lt_fatal (__FILE__, __LINE__, "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; + + lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +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; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + 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 (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + 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 (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + 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 * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +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; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' + + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_emit_exe_manifest +# emit a Win32 UAC manifest for executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_exe_manifest () +{ + cat <<EOF +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity version="1.0.0.0" +EOF + + case $host in + i?86-*-* ) echo ' processorArchitecture="x86"' ;; + ia64-*-* ) echo ' processorArchitecture="ia64"' ;; + x86_64-*-* ) echo ' processorArchitecture="amd64"' ;; + *) echo ' processorArchitecture="*"' ;; + esac + + cat <<EOF + name="$host_os.$PROGRAM.$outputname" + type="win32"/> + + <!-- Identify the application security requirements. --> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker" uiAccess="false"/> + </requestedPrivileges> + </security> + </trustInfo> +</assembly> +EOF +} + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + 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 + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append 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 + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + 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 + func_append 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. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append 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 + func_append 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" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + 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 + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + 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 + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + 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*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append 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* | *-cegcc* | *-*-haiku*) + # 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 + func_append deplibs " System.ltframework" + 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 + func_append deplibs " $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + 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*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # 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 + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -{shared,static}-libgcc, -static-{libgfortran|libstdc++} + # link against specified runtime library + # -fstack-protector* stack protector flags for GCC + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-flto*|-fwhopr*|-fuse-linker-plugin| \ + -shared-libgcc|-static-libgcc|-static-libgfortran|-static-libstdc++| \ + -fstack-protector*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + 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 + func_append 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. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append 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 + func_append 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" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + 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. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'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\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + 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 $opt_preserve_dup_deps ; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append 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 $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append 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 + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + 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 + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + 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 "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs="$dlprefiles" + 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|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; 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 func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + 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 + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + 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 + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + 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 + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + 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 use here." + else + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + 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. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # 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 + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append 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 + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib="$l" + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + 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. + func_append dlprefiles " $lib $dependency_libs" + else + func_append 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 + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$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 + func_append notinst_path " $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + 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 + func_append 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*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + 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 $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append 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 "$prefer_static_libs,$installed" = "built,yes"; } || + 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 + *"$absdir:"*) ;; + *) func_append 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 "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append 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 + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && 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 "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + 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* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + 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 "$opt_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 (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; 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 + elif test -n "$old_library"; then + 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 && + test "$hardcode_direct_absolute" = no; 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 + [\\/]*) + func_append 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 + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append 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:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$opt_mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; 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:"*) ;; + *) func_append 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 + [\\/]*) + func_append 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*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + func_append 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" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + 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 "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + 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 "*) ;; + *) func_append 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 "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append 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 + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + 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 + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # 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="$1" + number_minor="$2" + number_revision="$3" + # + # 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|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|qnx|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + 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]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + 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]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + 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]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + 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 + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + 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 + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + 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 + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + func_append verstring ":${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + 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 + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + func_append libobjs " $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$opt_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 | *.gcno) + ;; + $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 + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "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 + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append 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 "*) ;; + *) func_append 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 "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-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 + func_append 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. + $opt_dry_run || $RM conftest.c + cat > conftest.c <<EOF + int main() { return 0; } +EOF + $opt_dry_run || $RM conftest + if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then + ldd_output=`ldd conftest` + for i in $deplibs; do + case $i in + -l*) + func_stripname -l '' "$i" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $i "*) + func_append newdeplibs " $i" + i="" + ;; + esac + fi + if test -n "$i" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` + set dummy $deplib_matches; shift + deplib_match=$1 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + func_append newdeplibs " $i" + else + droppeddeps=yes + echo + $ECHO "*** Warning: dynamic linker does not accept needed library $i." + 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 I believe you do not have" + echo "*** because a test_compile did reveal that the linker did not use it for" + echo "*** its dynamic dependency list that programs get resolved with at runtime." + fi + fi + ;; + *) + func_append newdeplibs " $i" + ;; + esac + done + else + # Error occurred in the first compile. Let's try to salvage + # the situation: Compile a separate program for each library. + for i in $deplibs; do + case $i in + -l*) + func_stripname -l '' "$i" + name=$func_stripname_result + $opt_dry_run || $RM conftest + if $LTCC $LTCFLAGS -o conftest conftest.c $i; then + ldd_output=`ldd conftest` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $i "*) + func_append newdeplibs " $i" + i="" + ;; + esac + fi + if test -n "$i" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` + set dummy $deplib_matches; shift + deplib_match=$1 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + func_append newdeplibs " $i" + else + droppeddeps=yes + echo + $ECHO "*** Warning: dynamic linker does not accept needed library $i." + 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 a test_compile did reveal that the linker did not use this one" + echo "*** as a dynamic dependency that programs can get resolved with at runtime." + fi + fi + else + droppeddeps=yes + echo + $ECHO "*** Warning! Library $i is needed by this library but I was not able to" + echo "*** make it link in! You will probably need to install it or some" + echo "*** library that it depends on before this library will be fully" + echo "*** functional. Installing it before continuing would be even better." + fi + ;; + *) + func_append newdeplibs " $i" + ;; + esac + done + fi + ;; + file_magic*) + set dummy $deplibs_check_method; shift + file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + if test -n "$file_magic_glob"; then + libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob` + else + libnameglob=$libname + fi + test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + if test "$want_nocaseglob" = yes; then + shopt -s nocaseglob + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + 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 "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append 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 + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append 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 + func_append 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 + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; 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 " $tmp_deplibs" | $SED "s,$i,,"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + 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 + ;; + esac + ;; + 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 with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + 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 + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + 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 " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append 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 "$opt_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 + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + 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"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_apped 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 + func_append 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 "$opt_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 + shift + realname="$1" + 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 + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd1 in $cmds; do + IFS="$save_ifs" + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test "$try_normal_branch" = yes \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=${output_objdir}/${output_la}.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "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" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$opt_mode" = relink; then + $opt_dry_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:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # 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 + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append 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. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + 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~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "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" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + 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\" + test "X$libobjs" = "X " && libobjs= + 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 + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( 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 "$opt_mode" = relink; then + $opt_dry_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 + func_show_eval '${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 + func_show_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 "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_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 and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${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" + # $opt_dry_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" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + 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 "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + func_append compile_command " $compile_deplibs" + func_append 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 "*) ;; + *) func_append 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"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append 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"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append 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 "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + 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 + func_append 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 + func_append 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 "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + 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" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED '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 "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "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}\" || $lt_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 + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper $cwrapper.manifest; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + # Create the UAC manifests first if necessary (but the + # manifest files must have executable permission regardless). + case $output_name in + *instal*|*patch*|*setup*|*update*) + func_emit_exe_manifest > $cwrapper.manifest + func_emit_exe_manifest > $output_path/$objdir/$output_name.exe.manifest + chmod +x $cwrapper.manifest + chmod +x $output_path/$objdir/$output_name.exe.manifest + ;; + esac + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + 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 $symfileobj" + 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" + if test "$preload" = yes && test -f "$symfileobj"; then + func_append oldobjs " $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append 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 + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # 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 + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$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 + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$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= + len=$len0 + 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 + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "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}\" || $lt_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 + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; 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 "$relink_command" | $SED "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + 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) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# 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' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_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 + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + 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) func_append RM " $arg"; rmforce=yes ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + odir="$objdir" + else + odir="$dir/$objdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$opt_mode" = uninstall && odir="$dir" + + # Remember odir for removal later, being careful to avoid duplicates + if test "$opt_mode" = clean; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + 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 func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case "$opt_mode" in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + func_append 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 + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$opt_mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" + func_append rmfiles " ${name}.manifest $objdir/${name}.manifest" + if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name $objdir/lt-${name}.manifest" + fi + if test "X$noexename" != "X$name" ; then + func_append rmfiles " $odir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$opt_mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# 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 +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/resources/3rdparty/glpk-4.53/m4/libtool.m4 b/resources/3rdparty/glpk-4.53/m4/libtool.m4 new file mode 100644 index 000000000..6aebb63b5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/m4/libtool.m4 @@ -0,0 +1,7831 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file 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. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 57 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +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 + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +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 delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# 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 + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -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 + +Report bugs to <bug-libtool@gnu.org>." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # 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 + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_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 +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # 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) + + _LT_PROG_REPLACE_SHELLFNS + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# 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 +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$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* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$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 -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES +# -------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$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${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed '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${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and in which our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +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 AC_TRY_EVAL(ac_compile); 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 '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); 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-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + 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-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + 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" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + 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 AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +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 + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # 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:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + 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 "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$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>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + 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* | cegcc*) + # 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; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + 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 + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + 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` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # 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. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + 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` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#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 + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 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; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +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* | cegcc*) + 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 + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + 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" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + 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 +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$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:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + 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 "$_lt_compiler_boilerplate" | $SED '/^$/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_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $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 .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + 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 + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[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]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != 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_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; 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 +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +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" + AC_MSG_RESULT([yes]) +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" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # 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. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +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" +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' + ;; + +aix[[4-9]]*) + 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<name>.so + # instead of lib<name>.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*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + 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=`func_echo_all "$lib" | $SED '\''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' + ;; + esac + ;; + +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* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + 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~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + 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}' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + 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 + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + 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 + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # 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' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # 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}${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`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + 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 + ;; + +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 + ;; + *) # from 4.6 on, and DragonFly + 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 + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + 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=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + 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' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + 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* | k*bsd*-gnu | kopensolaris*-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' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # 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>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;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' + ;; + +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=qnx + 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='ldqnx.so' + ;; + +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" + ;; + +rdos*) + dynamic_linker=no + ;; + +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 + 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 + shlibpath_overrides_runpath=yes + 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' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + 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' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/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}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +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 +AC_MSG_RESULT([$dynamic_linker]) +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 + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[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]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[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 +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + 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 <<_LT_EOF 1>&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 + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + 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 + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[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 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$lt_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +_LT_PATH_LD_GNU +AC_SUBST([LD]) + +_LT_TAGDECL([], [LD], [1], [The linker used to build libraries]) +])# LT_PATH_LD + +# Old names: +AU_ALIAS([AM_PROG_LD], [LT_PATH_LD]) +AU_ALIAS([AC_PROG_LD], [LT_PATH_LD]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_LD], []) +dnl AC_DEFUN([AC_PROG_LD], []) + + +# _LT_PATH_LD_GNU +#- -------------- +m4_defun([_LT_PATH_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac]) +with_gnu_ld=$lt_cv_prog_gnu_ld +])# _LT_PATH_LD_GNU + + +# _LT_CMD_RELOAD +# -------------- +# find reload flag for linker +# -- PORTME Some linkers may need a different reload flag. +m4_defun([_LT_CMD_RELOAD], +[AC_CACHE_CHECK([for $LD option to reload object files], + lt_cv_ld_reload_flag, + [lt_cv_ld_reload_flag='-r']) +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 + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + 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 +_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl +_LT_TAGDECL([], [reload_cmds], [2])dnl +])# _LT_CMD_RELOAD + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[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 +aix[[4-9]]*) + 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', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | 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 + ;; + +haiku*) + 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])(-bit)?( [LM]SB)? 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 + ;; + +interix[[3-9]]*) + # 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* | k*bsd*-gnu | kopensolaris*-gnu) + 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=pass_all + ;; + +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 + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + 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 + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +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 + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[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 + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# 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]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + 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 + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \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\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# 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 + +# Try without a prefix underscore, 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. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && 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 <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf 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 +]) +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 + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # 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_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # 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). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # 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_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--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 + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # 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). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+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_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # 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_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # 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). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # 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_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # 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). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # 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 + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # 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'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # 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. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # 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 + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = 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 + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${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 + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[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 + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, 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 install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$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)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$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... + _LT_TAGVAR(archive_expsym_cmds, $1)='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 + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${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. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='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' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$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' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $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 + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&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. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=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 + ;; + *) + # 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. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$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. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + 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 + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$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]].*|aix[[5-9]]*) + 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. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + 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 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=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 + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + 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 + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=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. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$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. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${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. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$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*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$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)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # 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. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # 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. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=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. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_TAGVAR(ld_shlibs, $1)=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*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$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 + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$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 + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$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' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_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 + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='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' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=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. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$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. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) 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. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], + [[If ld is used when linking, flag to hardcode $libdir into a binary + during linking. This must work even if $libdir does not exist]]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## 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... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + 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 + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + 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++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_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 + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${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 + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + 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. + _LT_TAGVAR(archive_cmds, $1)='$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 -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + 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]].*|aix[[5-9]]*) + 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. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + 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 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=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 + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + 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 + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=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. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$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. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${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. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$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 + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # 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. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$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... + _LT_TAGVAR(archive_expsym_cmds, $1)='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 + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=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 + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$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) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${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 + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=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 + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$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; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${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 + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${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. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='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++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-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. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + 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. + _LT_TAGVAR(archive_cmds, $1)='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' + _LT_TAGVAR(archive_expsym_cmds, $1)='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; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # 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."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$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 + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$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' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$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 + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # 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=`func_echo_all "$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; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # 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. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=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::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | 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. + _LT_TAGVAR(archive_cmds, $1)='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' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='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' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # 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=`func_echo_all "$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; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # 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 -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='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' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # 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. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$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. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -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 -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='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 -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$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. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$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 + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$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... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + 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 +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); 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 + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${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 + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} 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 "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${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 "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$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 "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # 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. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + 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 + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$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... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + 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 + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$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... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_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... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# 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. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# 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 +IFS=$as_save_IFS +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 +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) + + +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) + + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) + + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) + + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi + +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) + + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine which file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/resources/3rdparty/glpk-4.53/m4/ltoptions.m4 b/resources/3rdparty/glpk-4.53/m4/ltoptions.m4 new file mode 100644 index 000000000..17cfd51c0 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/m4/ltoptions.m4 @@ -0,0 +1,369 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file 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. + +# serial 7 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [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], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [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], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [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], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/resources/3rdparty/glpk-4.53/m4/ltsugar.m4 b/resources/3rdparty/glpk-4.53/m4/ltsugar.m4 new file mode 100644 index 000000000..9000a057d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/m4/ltsugar.m4 @@ -0,0 +1,123 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file 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. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/resources/3rdparty/glpk-4.53/m4/ltversion.m4 b/resources/3rdparty/glpk-4.53/m4/ltversion.m4 new file mode 100644 index 000000000..9bf776f09 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file 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. + +# @configure_input@ + +# serial 3294 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4]) +m4_define([LT_PACKAGE_REVISION], [1.3294]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4' +macro_revision='1.3294' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/resources/3rdparty/glpk-4.53/m4/lt~obsolete.m4 b/resources/3rdparty/glpk-4.53/m4/lt~obsolete.m4 new file mode 100644 index 000000000..c573da90c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/m4/lt~obsolete.m4 @@ -0,0 +1,98 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file 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. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/resources/3rdparty/glpk-4.53/missing b/resources/3rdparty/glpk-4.53/missing new file mode 100644 index 000000000..9a5564823 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/missing @@ -0,0 +1,330 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2012-01-06.18; # UTC + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 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, see <http://www.gnu.org/licenses/>. + +# 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=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# 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' + autom4te touch the output file, or create a stub one + 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 + yacc create 'y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to <bug-automake@gnu.org>." + 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 + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# 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). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + *) + 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 $program 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 "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + 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 test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -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 test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -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 "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + 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 "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + 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 + ;; + + *) + 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-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/resources/3rdparty/glpk-4.53/resources/FindMySQL.cmake b/resources/3rdparty/glpk-4.53/resources/FindMySQL.cmake new file mode 100644 index 000000000..939582362 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/resources/FindMySQL.cmake @@ -0,0 +1,47 @@ +# - Find mysqlclient +# Find the native MySQL includes and library +# +# MYSQL_INCLUDE_DIR - where to find mysql.h, etc. +# MYSQL_LIBRARIES - List of libraries when using MySQL. +# MYSQL_FOUND - True if MySQL found. + +IF (MYSQL_INCLUDE_DIR) + # Already in cache, be silent + SET(MYSQL_FIND_QUIETLY TRUE) +ENDIF (MYSQL_INCLUDE_DIR) + +FIND_PATH(MYSQL_INCLUDE_DIR mysql.h + /usr/local/include/mysql + /usr/include/mysql +) + +SET(MYSQL_NAMES mysqlclient mysqlclient_r) +FIND_LIBRARY(MYSQL_LIBRARY + NAMES ${MYSQL_NAMES} + PATHS /usr/lib /usr/local/lib + PATH_SUFFIXES mysql +) + +IF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) + SET(MYSQL_FOUND TRUE) + SET( MYSQL_LIBRARIES ${MYSQL_LIBRARY} ) +ELSE (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) + SET(MYSQL_FOUND FALSE) + SET( MYSQL_LIBRARIES ) +ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) + +IF (MYSQL_FOUND) + IF (NOT MYSQL_FIND_QUIETLY) + MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARY}") + ENDIF (NOT MYSQL_FIND_QUIETLY) +ELSE (MYSQL_FOUND) + IF (MYSQL_FIND_REQUIRED) + MESSAGE(STATUS "Looked for MySQL libraries named ${MYSQL_NAMES}.") + MESSAGE(FATAL_ERROR "Could NOT find MySQL library") + ENDIF (MYSQL_FIND_REQUIRED) +ENDIF (MYSQL_FOUND) + +MARK_AS_ADVANCED( + MYSQL_LIBRARY + MYSQL_INCLUDE_DIR +) \ No newline at end of file diff --git a/resources/3rdparty/glpk-4.53/resources/FindODBC.cmake b/resources/3rdparty/glpk-4.53/resources/FindODBC.cmake new file mode 100644 index 000000000..dacb1f6c6 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/resources/FindODBC.cmake @@ -0,0 +1,60 @@ +# +# Find the ODBC driver manager includes and library. +# +# ODBC is an open standard for connecting to different databases in a +# semi-vendor-independent fashion. First you install the ODBC driver +# manager. Then you need a driver for each separate database you want +# to connect to (unless a generic one works). VTK includes neither +# the driver manager nor the vendor-specific drivers: you have to find +# those yourself. +# +# This module defines +# ODBC_INCLUDE_DIRECTORIES, where to find sql.h +# ODBC_LIBRARIES, the libraries to link against to use ODBC +# ODBC_FOUND. If false, you cannot build anything that requires MySQL. + +find_path(ODBC_INCLUDE_DIRECTORIES + NAMES sql.h + HINTS + /usr/include + /usr/include/odbc + /usr/local/include + /usr/local/include/odbc + /usr/local/odbc/include + "C:/Program Files/ODBC/include" + "C:/Program Files/Microsoft SDKs/Windows/v7.0/include" + "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/include" + "C:/Program Files/Microsoft SDKs/Windows/v6.0a/include" + "C:/ODBC/include" + DOC "Specify the directory containing sql.h." +) + +find_library(ODBC_LIBRARIES + NAMES iodbc odbc odbcinst odbc32 + HINTS + /usr/lib + /usr/lib/odbc + /usr/local/lib + /usr/local/lib/odbc + /usr/local/odbc/lib + "C:/Program Files/ODBC/lib" + "C:/ODBC/lib/debug" + "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Lib" + "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib" + DOC "Specify the ODBC driver manager library here." +) + +# MinGW find usually fails +if(MINGW) + set(ODBC_INCLUDE_DIRECTORIES ".") + set(ODBC_LIBRARIES odbc32) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(ODBC + DEFAULT_MSG + ODBC_INCLUDE_DIRECTORIES + ODBC_LIBRARIES + ) + +mark_as_advanced(ODBC_FOUND ODBC_LIBRARIES ODBC_INCLUDE_DIRECTORIES) \ No newline at end of file diff --git a/resources/3rdparty/glpk-4.53/src/Makefile.am b/resources/3rdparty/glpk-4.53/src/Makefile.am new file mode 100644 index 000000000..b4f050f71 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/Makefile.am @@ -0,0 +1,167 @@ +## Process this file with automake to produce Makefile.in ## + +include_HEADERS = glpk.h + +lib_LTLIBRARIES = libglpk.la + +libglpk_la_CPPFLAGS = \ +-I$(srcdir) \ +-I$(srcdir)/amd \ +-I$(srcdir)/bflib \ +-I$(srcdir)/cglib \ +-I$(srcdir)/colamd \ +-I$(srcdir)/env \ +-I$(srcdir)/minisat \ +-I$(srcdir)/misc \ +-I$(srcdir)/proxy \ +-I$(srcdir)/zlib + +libglpk_la_LDFLAGS = \ +-version-info 37:0:1 \ +-export-symbols-regex '^glp_*' + +libglpk_la_SOURCES = \ +avl.c \ +bfd.c \ +bfx.c \ +glpapi01.c \ +glpapi02.c \ +glpapi03.c \ +glpapi04.c \ +glpapi05.c \ +glpapi06.c \ +glpapi07.c \ +glpapi08.c \ +glpapi09.c \ +glpapi10.c \ +glpapi11.c \ +glpapi12.c \ +glpapi13.c \ +glpapi14.c \ +glpapi15.c \ +glpapi16.c \ +glpapi17.c \ +glpapi18.c \ +glpapi19.c \ +glpapi20.c \ +glpapi21.c \ +glpcpx.c \ +glpdmx.c \ +glpgmp.c \ +glphbm.c \ +glpini01.c \ +glpini02.c \ +glpios01.c \ +glpios02.c \ +glpios03.c \ +glpios04.c \ +glpios05.c \ +glpios06.c \ +glpios07.c \ +glpios08.c \ +glpios09.c \ +glpios10.c \ +glpios11.c \ +glpios12.c \ +glpipm.c \ +glplpf.c \ +glpmat.c \ +glpmpl01.c \ +glpmpl02.c \ +glpmpl03.c \ +glpmpl04.c \ +glpmpl05.c \ +glpmpl06.c \ +glpmps.c \ +glpnet03.c \ +glpnet04.c \ +glpnet05.c \ +glpnpp01.c \ +glpnpp02.c \ +glpnpp03.c \ +glpnpp04.c \ +glpnpp05.c \ +glpnpp06.c \ +glprgr.c \ +glpscl.c \ +glpsdf.c \ +glpspm.c \ +glpspx01.c \ +glpspx02.c \ +glpsql.c \ +glpssx01.c \ +glpssx02.c \ +glptsp.c \ +lux.c \ +amd/amd_1.c \ +amd/amd_2.c \ +amd/amd_aat.c \ +amd/amd_control.c \ +amd/amd_defaults.c \ +amd/amd_dump.c \ +amd/amd_info.c \ +amd/amd_order.c \ +amd/amd_post_tree.c \ +amd/amd_postorder.c \ +amd/amd_preprocess.c \ +amd/amd_valid.c \ +bflib/fhv.c \ +bflib/fhvint.c \ +bflib/ifu.c \ +bflib/luf.c \ +bflib/lufint.c \ +bflib/sgf.c \ +bflib/sva.c \ +cglib/cfg.c \ +cglib/cfg1.c \ +colamd/colamd.c \ +env/alloc.c \ +env/dlsup.c \ +env/env.c \ +env/error.c \ +env/stdout.c \ +env/stream.c \ +env/time.c \ +env/tls.c \ +minisat/minisat.c \ +misc/bignum.c \ +misc/dmp.c \ +misc/ffalg.c \ +misc/fp2rat.c \ +misc/gcd.c \ +misc/jd.c \ +misc/keller.c \ +misc/mc13d.c \ +misc/mc21a.c \ +misc/okalg.c \ +misc/qmd.c \ +misc/relax4.c \ +misc/rng.c \ +misc/rng1.c \ +misc/round2n.c \ +misc/str2int.c \ +misc/str2num.c \ +misc/strspx.c \ +misc/strtrim.c \ +misc/triang.c \ +misc/wclique.c \ +misc/wclique1.c \ +proxy/proxy.c \ +proxy/proxy1.c \ +zlib/adler32.c \ +zlib/compress.c \ +zlib/crc32.c \ +zlib/deflate.c \ +zlib/gzclose.c \ +zlib/gzlib.c \ +zlib/gzread.c \ +zlib/gzwrite.c \ +zlib/inffast.c \ +zlib/inflate.c \ +zlib/inftrees.c \ +zlib/trees.c \ +zlib/uncompr.c \ +zlib/zio.c \ +zlib/zutil.c + +## eof ## diff --git a/resources/3rdparty/glpk-4.53/src/Makefile.in b/resources/3rdparty/glpk-4.53/src/Makefile.in new file mode 100644 index 000000000..caab6d29a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/Makefile.in @@ -0,0 +1,1949 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 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@ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +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 +DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libglpk_la_LIBADD = +am_libglpk_la_OBJECTS = libglpk_la-avl.lo libglpk_la-bfd.lo \ + libglpk_la-bfx.lo libglpk_la-glpapi01.lo \ + libglpk_la-glpapi02.lo libglpk_la-glpapi03.lo \ + libglpk_la-glpapi04.lo libglpk_la-glpapi05.lo \ + libglpk_la-glpapi06.lo libglpk_la-glpapi07.lo \ + libglpk_la-glpapi08.lo libglpk_la-glpapi09.lo \ + libglpk_la-glpapi10.lo libglpk_la-glpapi11.lo \ + libglpk_la-glpapi12.lo libglpk_la-glpapi13.lo \ + libglpk_la-glpapi14.lo libglpk_la-glpapi15.lo \ + libglpk_la-glpapi16.lo libglpk_la-glpapi17.lo \ + libglpk_la-glpapi18.lo libglpk_la-glpapi19.lo \ + libglpk_la-glpapi20.lo libglpk_la-glpapi21.lo \ + libglpk_la-glpcpx.lo libglpk_la-glpdmx.lo libglpk_la-glpgmp.lo \ + libglpk_la-glphbm.lo libglpk_la-glpini01.lo \ + libglpk_la-glpini02.lo libglpk_la-glpios01.lo \ + libglpk_la-glpios02.lo libglpk_la-glpios03.lo \ + libglpk_la-glpios04.lo libglpk_la-glpios05.lo \ + libglpk_la-glpios06.lo libglpk_la-glpios07.lo \ + libglpk_la-glpios08.lo libglpk_la-glpios09.lo \ + libglpk_la-glpios10.lo libglpk_la-glpios11.lo \ + libglpk_la-glpios12.lo libglpk_la-glpipm.lo \ + libglpk_la-glplpf.lo libglpk_la-glpmat.lo \ + libglpk_la-glpmpl01.lo libglpk_la-glpmpl02.lo \ + libglpk_la-glpmpl03.lo libglpk_la-glpmpl04.lo \ + libglpk_la-glpmpl05.lo libglpk_la-glpmpl06.lo \ + libglpk_la-glpmps.lo libglpk_la-glpnet03.lo \ + libglpk_la-glpnet04.lo libglpk_la-glpnet05.lo \ + libglpk_la-glpnpp01.lo libglpk_la-glpnpp02.lo \ + libglpk_la-glpnpp03.lo libglpk_la-glpnpp04.lo \ + libglpk_la-glpnpp05.lo libglpk_la-glpnpp06.lo \ + libglpk_la-glprgr.lo libglpk_la-glpscl.lo libglpk_la-glpsdf.lo \ + libglpk_la-glpspm.lo libglpk_la-glpspx01.lo \ + libglpk_la-glpspx02.lo libglpk_la-glpsql.lo \ + libglpk_la-glpssx01.lo libglpk_la-glpssx02.lo \ + libglpk_la-glptsp.lo libglpk_la-lux.lo libglpk_la-amd_1.lo \ + libglpk_la-amd_2.lo libglpk_la-amd_aat.lo \ + libglpk_la-amd_control.lo libglpk_la-amd_defaults.lo \ + libglpk_la-amd_dump.lo libglpk_la-amd_info.lo \ + libglpk_la-amd_order.lo libglpk_la-amd_post_tree.lo \ + libglpk_la-amd_postorder.lo libglpk_la-amd_preprocess.lo \ + libglpk_la-amd_valid.lo libglpk_la-fhv.lo libglpk_la-fhvint.lo \ + libglpk_la-ifu.lo libglpk_la-luf.lo libglpk_la-lufint.lo \ + libglpk_la-sgf.lo libglpk_la-sva.lo libglpk_la-cfg.lo \ + libglpk_la-cfg1.lo libglpk_la-colamd.lo libglpk_la-alloc.lo \ + libglpk_la-dlsup.lo libglpk_la-env.lo libglpk_la-error.lo \ + libglpk_la-stdout.lo libglpk_la-stream.lo libglpk_la-time.lo \ + libglpk_la-tls.lo libglpk_la-minisat.lo libglpk_la-bignum.lo \ + libglpk_la-dmp.lo libglpk_la-ffalg.lo libglpk_la-fp2rat.lo \ + libglpk_la-gcd.lo libglpk_la-jd.lo libglpk_la-keller.lo \ + libglpk_la-mc13d.lo libglpk_la-mc21a.lo libglpk_la-okalg.lo \ + libglpk_la-qmd.lo libglpk_la-relax4.lo libglpk_la-rng.lo \ + libglpk_la-rng1.lo libglpk_la-round2n.lo libglpk_la-str2int.lo \ + libglpk_la-str2num.lo libglpk_la-strspx.lo \ + libglpk_la-strtrim.lo libglpk_la-triang.lo \ + libglpk_la-wclique.lo libglpk_la-wclique1.lo \ + libglpk_la-proxy.lo libglpk_la-proxy1.lo libglpk_la-adler32.lo \ + libglpk_la-compress.lo libglpk_la-crc32.lo \ + libglpk_la-deflate.lo libglpk_la-gzclose.lo \ + libglpk_la-gzlib.lo libglpk_la-gzread.lo libglpk_la-gzwrite.lo \ + libglpk_la-inffast.lo libglpk_la-inflate.lo \ + libglpk_la-inftrees.lo libglpk_la-trees.lo \ + libglpk_la-uncompr.lo libglpk_la-zio.lo libglpk_la-zutil.lo +libglpk_la_OBJECTS = $(am_libglpk_la_OBJECTS) +libglpk_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libglpk_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libglpk_la_SOURCES) +DIST_SOURCES = $(libglpk_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(include_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +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@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +include_HEADERS = glpk.h +lib_LTLIBRARIES = libglpk.la +libglpk_la_CPPFLAGS = \ +-I$(srcdir) \ +-I$(srcdir)/amd \ +-I$(srcdir)/bflib \ +-I$(srcdir)/cglib \ +-I$(srcdir)/colamd \ +-I$(srcdir)/env \ +-I$(srcdir)/minisat \ +-I$(srcdir)/misc \ +-I$(srcdir)/proxy \ +-I$(srcdir)/zlib + +libglpk_la_LDFLAGS = \ +-version-info 37:0:1 \ +-export-symbols-regex '^glp_*' + +libglpk_la_SOURCES = \ +avl.c \ +bfd.c \ +bfx.c \ +glpapi01.c \ +glpapi02.c \ +glpapi03.c \ +glpapi04.c \ +glpapi05.c \ +glpapi06.c \ +glpapi07.c \ +glpapi08.c \ +glpapi09.c \ +glpapi10.c \ +glpapi11.c \ +glpapi12.c \ +glpapi13.c \ +glpapi14.c \ +glpapi15.c \ +glpapi16.c \ +glpapi17.c \ +glpapi18.c \ +glpapi19.c \ +glpapi20.c \ +glpapi21.c \ +glpcpx.c \ +glpdmx.c \ +glpgmp.c \ +glphbm.c \ +glpini01.c \ +glpini02.c \ +glpios01.c \ +glpios02.c \ +glpios03.c \ +glpios04.c \ +glpios05.c \ +glpios06.c \ +glpios07.c \ +glpios08.c \ +glpios09.c \ +glpios10.c \ +glpios11.c \ +glpios12.c \ +glpipm.c \ +glplpf.c \ +glpmat.c \ +glpmpl01.c \ +glpmpl02.c \ +glpmpl03.c \ +glpmpl04.c \ +glpmpl05.c \ +glpmpl06.c \ +glpmps.c \ +glpnet03.c \ +glpnet04.c \ +glpnet05.c \ +glpnpp01.c \ +glpnpp02.c \ +glpnpp03.c \ +glpnpp04.c \ +glpnpp05.c \ +glpnpp06.c \ +glprgr.c \ +glpscl.c \ +glpsdf.c \ +glpspm.c \ +glpspx01.c \ +glpspx02.c \ +glpsql.c \ +glpssx01.c \ +glpssx02.c \ +glptsp.c \ +lux.c \ +amd/amd_1.c \ +amd/amd_2.c \ +amd/amd_aat.c \ +amd/amd_control.c \ +amd/amd_defaults.c \ +amd/amd_dump.c \ +amd/amd_info.c \ +amd/amd_order.c \ +amd/amd_post_tree.c \ +amd/amd_postorder.c \ +amd/amd_preprocess.c \ +amd/amd_valid.c \ +bflib/fhv.c \ +bflib/fhvint.c \ +bflib/ifu.c \ +bflib/luf.c \ +bflib/lufint.c \ +bflib/sgf.c \ +bflib/sva.c \ +cglib/cfg.c \ +cglib/cfg1.c \ +colamd/colamd.c \ +env/alloc.c \ +env/dlsup.c \ +env/env.c \ +env/error.c \ +env/stdout.c \ +env/stream.c \ +env/time.c \ +env/tls.c \ +minisat/minisat.c \ +misc/bignum.c \ +misc/dmp.c \ +misc/ffalg.c \ +misc/fp2rat.c \ +misc/gcd.c \ +misc/jd.c \ +misc/keller.c \ +misc/mc13d.c \ +misc/mc21a.c \ +misc/okalg.c \ +misc/qmd.c \ +misc/relax4.c \ +misc/rng.c \ +misc/rng1.c \ +misc/round2n.c \ +misc/str2int.c \ +misc/str2num.c \ +misc/strspx.c \ +misc/strtrim.c \ +misc/triang.c \ +misc/wclique.c \ +misc/wclique1.c \ +proxy/proxy.c \ +proxy/proxy1.c \ +zlib/adler32.c \ +zlib/compress.c \ +zlib/crc32.c \ +zlib/deflate.c \ +zlib/gzclose.c \ +zlib/gzlib.c \ +zlib/gzread.c \ +zlib/gzwrite.c \ +zlib/inffast.c \ +zlib/inflate.c \ +zlib/inftrees.c \ +zlib/trees.c \ +zlib/uncompr.c \ +zlib/zio.c \ +zlib/zutil.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu 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: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libglpk.la: $(libglpk_la_OBJECTS) $(libglpk_la_DEPENDENCIES) $(EXTRA_libglpk_la_DEPENDENCIES) + $(libglpk_la_LINK) -rpath $(libdir) $(libglpk_la_OBJECTS) $(libglpk_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-adler32.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-alloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_aat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_control.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_defaults.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_dump.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_info.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_order.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_post_tree.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_postorder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_preprocess.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_valid.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-avl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-bfd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-bfx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-bignum.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cfg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cfg1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-colamd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-compress.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-crc32.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-deflate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-dlsup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-dmp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-env.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-error.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-ffalg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-fhv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-fhvint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-fp2rat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gcd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi01.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi02.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi03.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi04.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi05.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi06.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi07.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi08.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi09.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi10.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi12.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi13.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi14.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi15.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi16.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi17.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi18.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi19.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi20.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi21.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpcpx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpdmx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpgmp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glphbm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpini01.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpini02.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios01.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios02.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios03.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios04.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios05.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios06.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios07.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios08.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios09.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios10.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios12.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpipm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glplpf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl01.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl02.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl03.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl04.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl05.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl06.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmps.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnet03.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnet04.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnet05.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp01.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp02.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp03.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp04.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp05.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp06.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glprgr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpscl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpsdf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpspm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpspx01.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpspx02.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpsql.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpssx01.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpssx02.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glptsp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzclose.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzlib.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzread.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzwrite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-ifu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-inffast.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-inflate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-inftrees.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-jd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-keller.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-luf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-lufint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-lux.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mc13d.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mc21a.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-minisat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-okalg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-proxy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-proxy1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-qmd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-relax4.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rng.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rng1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-round2n.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-sgf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-stdout.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-str2int.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-str2num.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-strspx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-strtrim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-sva.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-time.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-tls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-trees.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-triang.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-uncompr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wclique.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wclique1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-zio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-zutil.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libglpk_la-avl.lo: avl.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-avl.lo -MD -MP -MF $(DEPDIR)/libglpk_la-avl.Tpo -c -o libglpk_la-avl.lo `test -f 'avl.c' || echo '$(srcdir)/'`avl.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-avl.Tpo $(DEPDIR)/libglpk_la-avl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='avl.c' object='libglpk_la-avl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-avl.lo `test -f 'avl.c' || echo '$(srcdir)/'`avl.c + +libglpk_la-bfd.lo: bfd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-bfd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-bfd.Tpo -c -o libglpk_la-bfd.lo `test -f 'bfd.c' || echo '$(srcdir)/'`bfd.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-bfd.Tpo $(DEPDIR)/libglpk_la-bfd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bfd.c' object='libglpk_la-bfd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-bfd.lo `test -f 'bfd.c' || echo '$(srcdir)/'`bfd.c + +libglpk_la-bfx.lo: bfx.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-bfx.lo -MD -MP -MF $(DEPDIR)/libglpk_la-bfx.Tpo -c -o libglpk_la-bfx.lo `test -f 'bfx.c' || echo '$(srcdir)/'`bfx.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-bfx.Tpo $(DEPDIR)/libglpk_la-bfx.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bfx.c' object='libglpk_la-bfx.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-bfx.lo `test -f 'bfx.c' || echo '$(srcdir)/'`bfx.c + +libglpk_la-glpapi01.lo: glpapi01.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi01.Tpo -c -o libglpk_la-glpapi01.lo `test -f 'glpapi01.c' || echo '$(srcdir)/'`glpapi01.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi01.Tpo $(DEPDIR)/libglpk_la-glpapi01.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi01.c' object='libglpk_la-glpapi01.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi01.lo `test -f 'glpapi01.c' || echo '$(srcdir)/'`glpapi01.c + +libglpk_la-glpapi02.lo: glpapi02.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi02.Tpo -c -o libglpk_la-glpapi02.lo `test -f 'glpapi02.c' || echo '$(srcdir)/'`glpapi02.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi02.Tpo $(DEPDIR)/libglpk_la-glpapi02.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi02.c' object='libglpk_la-glpapi02.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi02.lo `test -f 'glpapi02.c' || echo '$(srcdir)/'`glpapi02.c + +libglpk_la-glpapi03.lo: glpapi03.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi03.Tpo -c -o libglpk_la-glpapi03.lo `test -f 'glpapi03.c' || echo '$(srcdir)/'`glpapi03.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi03.Tpo $(DEPDIR)/libglpk_la-glpapi03.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi03.c' object='libglpk_la-glpapi03.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi03.lo `test -f 'glpapi03.c' || echo '$(srcdir)/'`glpapi03.c + +libglpk_la-glpapi04.lo: glpapi04.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi04.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi04.Tpo -c -o libglpk_la-glpapi04.lo `test -f 'glpapi04.c' || echo '$(srcdir)/'`glpapi04.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi04.Tpo $(DEPDIR)/libglpk_la-glpapi04.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi04.c' object='libglpk_la-glpapi04.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi04.lo `test -f 'glpapi04.c' || echo '$(srcdir)/'`glpapi04.c + +libglpk_la-glpapi05.lo: glpapi05.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi05.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi05.Tpo -c -o libglpk_la-glpapi05.lo `test -f 'glpapi05.c' || echo '$(srcdir)/'`glpapi05.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi05.Tpo $(DEPDIR)/libglpk_la-glpapi05.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi05.c' object='libglpk_la-glpapi05.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi05.lo `test -f 'glpapi05.c' || echo '$(srcdir)/'`glpapi05.c + +libglpk_la-glpapi06.lo: glpapi06.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi06.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi06.Tpo -c -o libglpk_la-glpapi06.lo `test -f 'glpapi06.c' || echo '$(srcdir)/'`glpapi06.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi06.Tpo $(DEPDIR)/libglpk_la-glpapi06.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi06.c' object='libglpk_la-glpapi06.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi06.lo `test -f 'glpapi06.c' || echo '$(srcdir)/'`glpapi06.c + +libglpk_la-glpapi07.lo: glpapi07.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi07.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi07.Tpo -c -o libglpk_la-glpapi07.lo `test -f 'glpapi07.c' || echo '$(srcdir)/'`glpapi07.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi07.Tpo $(DEPDIR)/libglpk_la-glpapi07.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi07.c' object='libglpk_la-glpapi07.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi07.lo `test -f 'glpapi07.c' || echo '$(srcdir)/'`glpapi07.c + +libglpk_la-glpapi08.lo: glpapi08.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi08.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi08.Tpo -c -o libglpk_la-glpapi08.lo `test -f 'glpapi08.c' || echo '$(srcdir)/'`glpapi08.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi08.Tpo $(DEPDIR)/libglpk_la-glpapi08.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi08.c' object='libglpk_la-glpapi08.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi08.lo `test -f 'glpapi08.c' || echo '$(srcdir)/'`glpapi08.c + +libglpk_la-glpapi09.lo: glpapi09.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi09.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi09.Tpo -c -o libglpk_la-glpapi09.lo `test -f 'glpapi09.c' || echo '$(srcdir)/'`glpapi09.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi09.Tpo $(DEPDIR)/libglpk_la-glpapi09.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi09.c' object='libglpk_la-glpapi09.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi09.lo `test -f 'glpapi09.c' || echo '$(srcdir)/'`glpapi09.c + +libglpk_la-glpapi10.lo: glpapi10.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi10.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi10.Tpo -c -o libglpk_la-glpapi10.lo `test -f 'glpapi10.c' || echo '$(srcdir)/'`glpapi10.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi10.Tpo $(DEPDIR)/libglpk_la-glpapi10.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi10.c' object='libglpk_la-glpapi10.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi10.lo `test -f 'glpapi10.c' || echo '$(srcdir)/'`glpapi10.c + +libglpk_la-glpapi11.lo: glpapi11.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi11.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi11.Tpo -c -o libglpk_la-glpapi11.lo `test -f 'glpapi11.c' || echo '$(srcdir)/'`glpapi11.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi11.Tpo $(DEPDIR)/libglpk_la-glpapi11.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi11.c' object='libglpk_la-glpapi11.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi11.lo `test -f 'glpapi11.c' || echo '$(srcdir)/'`glpapi11.c + +libglpk_la-glpapi12.lo: glpapi12.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi12.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi12.Tpo -c -o libglpk_la-glpapi12.lo `test -f 'glpapi12.c' || echo '$(srcdir)/'`glpapi12.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi12.Tpo $(DEPDIR)/libglpk_la-glpapi12.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi12.c' object='libglpk_la-glpapi12.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi12.lo `test -f 'glpapi12.c' || echo '$(srcdir)/'`glpapi12.c + +libglpk_la-glpapi13.lo: glpapi13.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi13.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi13.Tpo -c -o libglpk_la-glpapi13.lo `test -f 'glpapi13.c' || echo '$(srcdir)/'`glpapi13.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi13.Tpo $(DEPDIR)/libglpk_la-glpapi13.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi13.c' object='libglpk_la-glpapi13.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi13.lo `test -f 'glpapi13.c' || echo '$(srcdir)/'`glpapi13.c + +libglpk_la-glpapi14.lo: glpapi14.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi14.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi14.Tpo -c -o libglpk_la-glpapi14.lo `test -f 'glpapi14.c' || echo '$(srcdir)/'`glpapi14.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi14.Tpo $(DEPDIR)/libglpk_la-glpapi14.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi14.c' object='libglpk_la-glpapi14.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi14.lo `test -f 'glpapi14.c' || echo '$(srcdir)/'`glpapi14.c + +libglpk_la-glpapi15.lo: glpapi15.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi15.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi15.Tpo -c -o libglpk_la-glpapi15.lo `test -f 'glpapi15.c' || echo '$(srcdir)/'`glpapi15.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi15.Tpo $(DEPDIR)/libglpk_la-glpapi15.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi15.c' object='libglpk_la-glpapi15.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi15.lo `test -f 'glpapi15.c' || echo '$(srcdir)/'`glpapi15.c + +libglpk_la-glpapi16.lo: glpapi16.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi16.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi16.Tpo -c -o libglpk_la-glpapi16.lo `test -f 'glpapi16.c' || echo '$(srcdir)/'`glpapi16.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi16.Tpo $(DEPDIR)/libglpk_la-glpapi16.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi16.c' object='libglpk_la-glpapi16.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi16.lo `test -f 'glpapi16.c' || echo '$(srcdir)/'`glpapi16.c + +libglpk_la-glpapi17.lo: glpapi17.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi17.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi17.Tpo -c -o libglpk_la-glpapi17.lo `test -f 'glpapi17.c' || echo '$(srcdir)/'`glpapi17.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi17.Tpo $(DEPDIR)/libglpk_la-glpapi17.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi17.c' object='libglpk_la-glpapi17.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi17.lo `test -f 'glpapi17.c' || echo '$(srcdir)/'`glpapi17.c + +libglpk_la-glpapi18.lo: glpapi18.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi18.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi18.Tpo -c -o libglpk_la-glpapi18.lo `test -f 'glpapi18.c' || echo '$(srcdir)/'`glpapi18.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi18.Tpo $(DEPDIR)/libglpk_la-glpapi18.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi18.c' object='libglpk_la-glpapi18.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi18.lo `test -f 'glpapi18.c' || echo '$(srcdir)/'`glpapi18.c + +libglpk_la-glpapi19.lo: glpapi19.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi19.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi19.Tpo -c -o libglpk_la-glpapi19.lo `test -f 'glpapi19.c' || echo '$(srcdir)/'`glpapi19.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi19.Tpo $(DEPDIR)/libglpk_la-glpapi19.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi19.c' object='libglpk_la-glpapi19.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi19.lo `test -f 'glpapi19.c' || echo '$(srcdir)/'`glpapi19.c + +libglpk_la-glpapi20.lo: glpapi20.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi20.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi20.Tpo -c -o libglpk_la-glpapi20.lo `test -f 'glpapi20.c' || echo '$(srcdir)/'`glpapi20.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi20.Tpo $(DEPDIR)/libglpk_la-glpapi20.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi20.c' object='libglpk_la-glpapi20.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi20.lo `test -f 'glpapi20.c' || echo '$(srcdir)/'`glpapi20.c + +libglpk_la-glpapi21.lo: glpapi21.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi21.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi21.Tpo -c -o libglpk_la-glpapi21.lo `test -f 'glpapi21.c' || echo '$(srcdir)/'`glpapi21.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi21.Tpo $(DEPDIR)/libglpk_la-glpapi21.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi21.c' object='libglpk_la-glpapi21.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi21.lo `test -f 'glpapi21.c' || echo '$(srcdir)/'`glpapi21.c + +libglpk_la-glpcpx.lo: glpcpx.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpcpx.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpcpx.Tpo -c -o libglpk_la-glpcpx.lo `test -f 'glpcpx.c' || echo '$(srcdir)/'`glpcpx.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpcpx.Tpo $(DEPDIR)/libglpk_la-glpcpx.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpcpx.c' object='libglpk_la-glpcpx.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpcpx.lo `test -f 'glpcpx.c' || echo '$(srcdir)/'`glpcpx.c + +libglpk_la-glpdmx.lo: glpdmx.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpdmx.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpdmx.Tpo -c -o libglpk_la-glpdmx.lo `test -f 'glpdmx.c' || echo '$(srcdir)/'`glpdmx.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpdmx.Tpo $(DEPDIR)/libglpk_la-glpdmx.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpdmx.c' object='libglpk_la-glpdmx.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpdmx.lo `test -f 'glpdmx.c' || echo '$(srcdir)/'`glpdmx.c + +libglpk_la-glpgmp.lo: glpgmp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpgmp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpgmp.Tpo -c -o libglpk_la-glpgmp.lo `test -f 'glpgmp.c' || echo '$(srcdir)/'`glpgmp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpgmp.Tpo $(DEPDIR)/libglpk_la-glpgmp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpgmp.c' object='libglpk_la-glpgmp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpgmp.lo `test -f 'glpgmp.c' || echo '$(srcdir)/'`glpgmp.c + +libglpk_la-glphbm.lo: glphbm.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glphbm.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glphbm.Tpo -c -o libglpk_la-glphbm.lo `test -f 'glphbm.c' || echo '$(srcdir)/'`glphbm.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glphbm.Tpo $(DEPDIR)/libglpk_la-glphbm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glphbm.c' object='libglpk_la-glphbm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glphbm.lo `test -f 'glphbm.c' || echo '$(srcdir)/'`glphbm.c + +libglpk_la-glpini01.lo: glpini01.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpini01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpini01.Tpo -c -o libglpk_la-glpini01.lo `test -f 'glpini01.c' || echo '$(srcdir)/'`glpini01.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpini01.Tpo $(DEPDIR)/libglpk_la-glpini01.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpini01.c' object='libglpk_la-glpini01.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpini01.lo `test -f 'glpini01.c' || echo '$(srcdir)/'`glpini01.c + +libglpk_la-glpini02.lo: glpini02.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpini02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpini02.Tpo -c -o libglpk_la-glpini02.lo `test -f 'glpini02.c' || echo '$(srcdir)/'`glpini02.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpini02.Tpo $(DEPDIR)/libglpk_la-glpini02.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpini02.c' object='libglpk_la-glpini02.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpini02.lo `test -f 'glpini02.c' || echo '$(srcdir)/'`glpini02.c + +libglpk_la-glpios01.lo: glpios01.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios01.Tpo -c -o libglpk_la-glpios01.lo `test -f 'glpios01.c' || echo '$(srcdir)/'`glpios01.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios01.Tpo $(DEPDIR)/libglpk_la-glpios01.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios01.c' object='libglpk_la-glpios01.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios01.lo `test -f 'glpios01.c' || echo '$(srcdir)/'`glpios01.c + +libglpk_la-glpios02.lo: glpios02.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios02.Tpo -c -o libglpk_la-glpios02.lo `test -f 'glpios02.c' || echo '$(srcdir)/'`glpios02.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios02.Tpo $(DEPDIR)/libglpk_la-glpios02.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios02.c' object='libglpk_la-glpios02.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios02.lo `test -f 'glpios02.c' || echo '$(srcdir)/'`glpios02.c + +libglpk_la-glpios03.lo: glpios03.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios03.Tpo -c -o libglpk_la-glpios03.lo `test -f 'glpios03.c' || echo '$(srcdir)/'`glpios03.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios03.Tpo $(DEPDIR)/libglpk_la-glpios03.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios03.c' object='libglpk_la-glpios03.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios03.lo `test -f 'glpios03.c' || echo '$(srcdir)/'`glpios03.c + +libglpk_la-glpios04.lo: glpios04.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios04.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios04.Tpo -c -o libglpk_la-glpios04.lo `test -f 'glpios04.c' || echo '$(srcdir)/'`glpios04.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios04.Tpo $(DEPDIR)/libglpk_la-glpios04.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios04.c' object='libglpk_la-glpios04.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios04.lo `test -f 'glpios04.c' || echo '$(srcdir)/'`glpios04.c + +libglpk_la-glpios05.lo: glpios05.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios05.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios05.Tpo -c -o libglpk_la-glpios05.lo `test -f 'glpios05.c' || echo '$(srcdir)/'`glpios05.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios05.Tpo $(DEPDIR)/libglpk_la-glpios05.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios05.c' object='libglpk_la-glpios05.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios05.lo `test -f 'glpios05.c' || echo '$(srcdir)/'`glpios05.c + +libglpk_la-glpios06.lo: glpios06.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios06.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios06.Tpo -c -o libglpk_la-glpios06.lo `test -f 'glpios06.c' || echo '$(srcdir)/'`glpios06.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios06.Tpo $(DEPDIR)/libglpk_la-glpios06.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios06.c' object='libglpk_la-glpios06.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios06.lo `test -f 'glpios06.c' || echo '$(srcdir)/'`glpios06.c + +libglpk_la-glpios07.lo: glpios07.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios07.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios07.Tpo -c -o libglpk_la-glpios07.lo `test -f 'glpios07.c' || echo '$(srcdir)/'`glpios07.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios07.Tpo $(DEPDIR)/libglpk_la-glpios07.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios07.c' object='libglpk_la-glpios07.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios07.lo `test -f 'glpios07.c' || echo '$(srcdir)/'`glpios07.c + +libglpk_la-glpios08.lo: glpios08.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios08.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios08.Tpo -c -o libglpk_la-glpios08.lo `test -f 'glpios08.c' || echo '$(srcdir)/'`glpios08.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios08.Tpo $(DEPDIR)/libglpk_la-glpios08.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios08.c' object='libglpk_la-glpios08.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios08.lo `test -f 'glpios08.c' || echo '$(srcdir)/'`glpios08.c + +libglpk_la-glpios09.lo: glpios09.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios09.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios09.Tpo -c -o libglpk_la-glpios09.lo `test -f 'glpios09.c' || echo '$(srcdir)/'`glpios09.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios09.Tpo $(DEPDIR)/libglpk_la-glpios09.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios09.c' object='libglpk_la-glpios09.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios09.lo `test -f 'glpios09.c' || echo '$(srcdir)/'`glpios09.c + +libglpk_la-glpios10.lo: glpios10.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios10.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios10.Tpo -c -o libglpk_la-glpios10.lo `test -f 'glpios10.c' || echo '$(srcdir)/'`glpios10.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios10.Tpo $(DEPDIR)/libglpk_la-glpios10.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios10.c' object='libglpk_la-glpios10.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios10.lo `test -f 'glpios10.c' || echo '$(srcdir)/'`glpios10.c + +libglpk_la-glpios11.lo: glpios11.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios11.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios11.Tpo -c -o libglpk_la-glpios11.lo `test -f 'glpios11.c' || echo '$(srcdir)/'`glpios11.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios11.Tpo $(DEPDIR)/libglpk_la-glpios11.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios11.c' object='libglpk_la-glpios11.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios11.lo `test -f 'glpios11.c' || echo '$(srcdir)/'`glpios11.c + +libglpk_la-glpios12.lo: glpios12.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios12.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios12.Tpo -c -o libglpk_la-glpios12.lo `test -f 'glpios12.c' || echo '$(srcdir)/'`glpios12.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios12.Tpo $(DEPDIR)/libglpk_la-glpios12.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios12.c' object='libglpk_la-glpios12.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios12.lo `test -f 'glpios12.c' || echo '$(srcdir)/'`glpios12.c + +libglpk_la-glpipm.lo: glpipm.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpipm.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpipm.Tpo -c -o libglpk_la-glpipm.lo `test -f 'glpipm.c' || echo '$(srcdir)/'`glpipm.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpipm.Tpo $(DEPDIR)/libglpk_la-glpipm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpipm.c' object='libglpk_la-glpipm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpipm.lo `test -f 'glpipm.c' || echo '$(srcdir)/'`glpipm.c + +libglpk_la-glplpf.lo: glplpf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glplpf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glplpf.Tpo -c -o libglpk_la-glplpf.lo `test -f 'glplpf.c' || echo '$(srcdir)/'`glplpf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glplpf.Tpo $(DEPDIR)/libglpk_la-glplpf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glplpf.c' object='libglpk_la-glplpf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glplpf.lo `test -f 'glplpf.c' || echo '$(srcdir)/'`glplpf.c + +libglpk_la-glpmat.lo: glpmat.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmat.Tpo -c -o libglpk_la-glpmat.lo `test -f 'glpmat.c' || echo '$(srcdir)/'`glpmat.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmat.Tpo $(DEPDIR)/libglpk_la-glpmat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmat.c' object='libglpk_la-glpmat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmat.lo `test -f 'glpmat.c' || echo '$(srcdir)/'`glpmat.c + +libglpk_la-glpmpl01.lo: glpmpl01.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl01.Tpo -c -o libglpk_la-glpmpl01.lo `test -f 'glpmpl01.c' || echo '$(srcdir)/'`glpmpl01.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl01.Tpo $(DEPDIR)/libglpk_la-glpmpl01.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl01.c' object='libglpk_la-glpmpl01.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl01.lo `test -f 'glpmpl01.c' || echo '$(srcdir)/'`glpmpl01.c + +libglpk_la-glpmpl02.lo: glpmpl02.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl02.Tpo -c -o libglpk_la-glpmpl02.lo `test -f 'glpmpl02.c' || echo '$(srcdir)/'`glpmpl02.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl02.Tpo $(DEPDIR)/libglpk_la-glpmpl02.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl02.c' object='libglpk_la-glpmpl02.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl02.lo `test -f 'glpmpl02.c' || echo '$(srcdir)/'`glpmpl02.c + +libglpk_la-glpmpl03.lo: glpmpl03.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl03.Tpo -c -o libglpk_la-glpmpl03.lo `test -f 'glpmpl03.c' || echo '$(srcdir)/'`glpmpl03.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl03.Tpo $(DEPDIR)/libglpk_la-glpmpl03.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl03.c' object='libglpk_la-glpmpl03.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl03.lo `test -f 'glpmpl03.c' || echo '$(srcdir)/'`glpmpl03.c + +libglpk_la-glpmpl04.lo: glpmpl04.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl04.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl04.Tpo -c -o libglpk_la-glpmpl04.lo `test -f 'glpmpl04.c' || echo '$(srcdir)/'`glpmpl04.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl04.Tpo $(DEPDIR)/libglpk_la-glpmpl04.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl04.c' object='libglpk_la-glpmpl04.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl04.lo `test -f 'glpmpl04.c' || echo '$(srcdir)/'`glpmpl04.c + +libglpk_la-glpmpl05.lo: glpmpl05.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl05.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl05.Tpo -c -o libglpk_la-glpmpl05.lo `test -f 'glpmpl05.c' || echo '$(srcdir)/'`glpmpl05.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl05.Tpo $(DEPDIR)/libglpk_la-glpmpl05.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl05.c' object='libglpk_la-glpmpl05.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl05.lo `test -f 'glpmpl05.c' || echo '$(srcdir)/'`glpmpl05.c + +libglpk_la-glpmpl06.lo: glpmpl06.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl06.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl06.Tpo -c -o libglpk_la-glpmpl06.lo `test -f 'glpmpl06.c' || echo '$(srcdir)/'`glpmpl06.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl06.Tpo $(DEPDIR)/libglpk_la-glpmpl06.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl06.c' object='libglpk_la-glpmpl06.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl06.lo `test -f 'glpmpl06.c' || echo '$(srcdir)/'`glpmpl06.c + +libglpk_la-glpmps.lo: glpmps.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmps.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmps.Tpo -c -o libglpk_la-glpmps.lo `test -f 'glpmps.c' || echo '$(srcdir)/'`glpmps.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmps.Tpo $(DEPDIR)/libglpk_la-glpmps.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmps.c' object='libglpk_la-glpmps.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmps.lo `test -f 'glpmps.c' || echo '$(srcdir)/'`glpmps.c + +libglpk_la-glpnet03.lo: glpnet03.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnet03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnet03.Tpo -c -o libglpk_la-glpnet03.lo `test -f 'glpnet03.c' || echo '$(srcdir)/'`glpnet03.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnet03.Tpo $(DEPDIR)/libglpk_la-glpnet03.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnet03.c' object='libglpk_la-glpnet03.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnet03.lo `test -f 'glpnet03.c' || echo '$(srcdir)/'`glpnet03.c + +libglpk_la-glpnet04.lo: glpnet04.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnet04.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnet04.Tpo -c -o libglpk_la-glpnet04.lo `test -f 'glpnet04.c' || echo '$(srcdir)/'`glpnet04.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnet04.Tpo $(DEPDIR)/libglpk_la-glpnet04.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnet04.c' object='libglpk_la-glpnet04.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnet04.lo `test -f 'glpnet04.c' || echo '$(srcdir)/'`glpnet04.c + +libglpk_la-glpnet05.lo: glpnet05.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnet05.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnet05.Tpo -c -o libglpk_la-glpnet05.lo `test -f 'glpnet05.c' || echo '$(srcdir)/'`glpnet05.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnet05.Tpo $(DEPDIR)/libglpk_la-glpnet05.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnet05.c' object='libglpk_la-glpnet05.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnet05.lo `test -f 'glpnet05.c' || echo '$(srcdir)/'`glpnet05.c + +libglpk_la-glpnpp01.lo: glpnpp01.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp01.Tpo -c -o libglpk_la-glpnpp01.lo `test -f 'glpnpp01.c' || echo '$(srcdir)/'`glpnpp01.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp01.Tpo $(DEPDIR)/libglpk_la-glpnpp01.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp01.c' object='libglpk_la-glpnpp01.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp01.lo `test -f 'glpnpp01.c' || echo '$(srcdir)/'`glpnpp01.c + +libglpk_la-glpnpp02.lo: glpnpp02.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp02.Tpo -c -o libglpk_la-glpnpp02.lo `test -f 'glpnpp02.c' || echo '$(srcdir)/'`glpnpp02.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp02.Tpo $(DEPDIR)/libglpk_la-glpnpp02.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp02.c' object='libglpk_la-glpnpp02.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp02.lo `test -f 'glpnpp02.c' || echo '$(srcdir)/'`glpnpp02.c + +libglpk_la-glpnpp03.lo: glpnpp03.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp03.Tpo -c -o libglpk_la-glpnpp03.lo `test -f 'glpnpp03.c' || echo '$(srcdir)/'`glpnpp03.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp03.Tpo $(DEPDIR)/libglpk_la-glpnpp03.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp03.c' object='libglpk_la-glpnpp03.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp03.lo `test -f 'glpnpp03.c' || echo '$(srcdir)/'`glpnpp03.c + +libglpk_la-glpnpp04.lo: glpnpp04.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp04.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp04.Tpo -c -o libglpk_la-glpnpp04.lo `test -f 'glpnpp04.c' || echo '$(srcdir)/'`glpnpp04.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp04.Tpo $(DEPDIR)/libglpk_la-glpnpp04.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp04.c' object='libglpk_la-glpnpp04.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp04.lo `test -f 'glpnpp04.c' || echo '$(srcdir)/'`glpnpp04.c + +libglpk_la-glpnpp05.lo: glpnpp05.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp05.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp05.Tpo -c -o libglpk_la-glpnpp05.lo `test -f 'glpnpp05.c' || echo '$(srcdir)/'`glpnpp05.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp05.Tpo $(DEPDIR)/libglpk_la-glpnpp05.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp05.c' object='libglpk_la-glpnpp05.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp05.lo `test -f 'glpnpp05.c' || echo '$(srcdir)/'`glpnpp05.c + +libglpk_la-glpnpp06.lo: glpnpp06.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp06.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp06.Tpo -c -o libglpk_la-glpnpp06.lo `test -f 'glpnpp06.c' || echo '$(srcdir)/'`glpnpp06.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp06.Tpo $(DEPDIR)/libglpk_la-glpnpp06.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp06.c' object='libglpk_la-glpnpp06.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp06.lo `test -f 'glpnpp06.c' || echo '$(srcdir)/'`glpnpp06.c + +libglpk_la-glprgr.lo: glprgr.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glprgr.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glprgr.Tpo -c -o libglpk_la-glprgr.lo `test -f 'glprgr.c' || echo '$(srcdir)/'`glprgr.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glprgr.Tpo $(DEPDIR)/libglpk_la-glprgr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glprgr.c' object='libglpk_la-glprgr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glprgr.lo `test -f 'glprgr.c' || echo '$(srcdir)/'`glprgr.c + +libglpk_la-glpscl.lo: glpscl.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpscl.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpscl.Tpo -c -o libglpk_la-glpscl.lo `test -f 'glpscl.c' || echo '$(srcdir)/'`glpscl.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpscl.Tpo $(DEPDIR)/libglpk_la-glpscl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpscl.c' object='libglpk_la-glpscl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpscl.lo `test -f 'glpscl.c' || echo '$(srcdir)/'`glpscl.c + +libglpk_la-glpsdf.lo: glpsdf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpsdf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpsdf.Tpo -c -o libglpk_la-glpsdf.lo `test -f 'glpsdf.c' || echo '$(srcdir)/'`glpsdf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpsdf.Tpo $(DEPDIR)/libglpk_la-glpsdf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpsdf.c' object='libglpk_la-glpsdf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpsdf.lo `test -f 'glpsdf.c' || echo '$(srcdir)/'`glpsdf.c + +libglpk_la-glpspm.lo: glpspm.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpspm.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpspm.Tpo -c -o libglpk_la-glpspm.lo `test -f 'glpspm.c' || echo '$(srcdir)/'`glpspm.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpspm.Tpo $(DEPDIR)/libglpk_la-glpspm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpspm.c' object='libglpk_la-glpspm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpspm.lo `test -f 'glpspm.c' || echo '$(srcdir)/'`glpspm.c + +libglpk_la-glpspx01.lo: glpspx01.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpspx01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpspx01.Tpo -c -o libglpk_la-glpspx01.lo `test -f 'glpspx01.c' || echo '$(srcdir)/'`glpspx01.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpspx01.Tpo $(DEPDIR)/libglpk_la-glpspx01.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpspx01.c' object='libglpk_la-glpspx01.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpspx01.lo `test -f 'glpspx01.c' || echo '$(srcdir)/'`glpspx01.c + +libglpk_la-glpspx02.lo: glpspx02.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpspx02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpspx02.Tpo -c -o libglpk_la-glpspx02.lo `test -f 'glpspx02.c' || echo '$(srcdir)/'`glpspx02.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpspx02.Tpo $(DEPDIR)/libglpk_la-glpspx02.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpspx02.c' object='libglpk_la-glpspx02.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpspx02.lo `test -f 'glpspx02.c' || echo '$(srcdir)/'`glpspx02.c + +libglpk_la-glpsql.lo: glpsql.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpsql.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpsql.Tpo -c -o libglpk_la-glpsql.lo `test -f 'glpsql.c' || echo '$(srcdir)/'`glpsql.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpsql.Tpo $(DEPDIR)/libglpk_la-glpsql.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpsql.c' object='libglpk_la-glpsql.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpsql.lo `test -f 'glpsql.c' || echo '$(srcdir)/'`glpsql.c + +libglpk_la-glpssx01.lo: glpssx01.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpssx01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpssx01.Tpo -c -o libglpk_la-glpssx01.lo `test -f 'glpssx01.c' || echo '$(srcdir)/'`glpssx01.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpssx01.Tpo $(DEPDIR)/libglpk_la-glpssx01.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpssx01.c' object='libglpk_la-glpssx01.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpssx01.lo `test -f 'glpssx01.c' || echo '$(srcdir)/'`glpssx01.c + +libglpk_la-glpssx02.lo: glpssx02.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpssx02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpssx02.Tpo -c -o libglpk_la-glpssx02.lo `test -f 'glpssx02.c' || echo '$(srcdir)/'`glpssx02.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpssx02.Tpo $(DEPDIR)/libglpk_la-glpssx02.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpssx02.c' object='libglpk_la-glpssx02.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpssx02.lo `test -f 'glpssx02.c' || echo '$(srcdir)/'`glpssx02.c + +libglpk_la-glptsp.lo: glptsp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glptsp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glptsp.Tpo -c -o libglpk_la-glptsp.lo `test -f 'glptsp.c' || echo '$(srcdir)/'`glptsp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glptsp.Tpo $(DEPDIR)/libglpk_la-glptsp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glptsp.c' object='libglpk_la-glptsp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glptsp.lo `test -f 'glptsp.c' || echo '$(srcdir)/'`glptsp.c + +libglpk_la-lux.lo: lux.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-lux.lo -MD -MP -MF $(DEPDIR)/libglpk_la-lux.Tpo -c -o libglpk_la-lux.lo `test -f 'lux.c' || echo '$(srcdir)/'`lux.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-lux.Tpo $(DEPDIR)/libglpk_la-lux.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lux.c' object='libglpk_la-lux.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-lux.lo `test -f 'lux.c' || echo '$(srcdir)/'`lux.c + +libglpk_la-amd_1.lo: amd/amd_1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_1.Tpo -c -o libglpk_la-amd_1.lo `test -f 'amd/amd_1.c' || echo '$(srcdir)/'`amd/amd_1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_1.Tpo $(DEPDIR)/libglpk_la-amd_1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_1.c' object='libglpk_la-amd_1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_1.lo `test -f 'amd/amd_1.c' || echo '$(srcdir)/'`amd/amd_1.c + +libglpk_la-amd_2.lo: amd/amd_2.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_2.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_2.Tpo -c -o libglpk_la-amd_2.lo `test -f 'amd/amd_2.c' || echo '$(srcdir)/'`amd/amd_2.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_2.Tpo $(DEPDIR)/libglpk_la-amd_2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_2.c' object='libglpk_la-amd_2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_2.lo `test -f 'amd/amd_2.c' || echo '$(srcdir)/'`amd/amd_2.c + +libglpk_la-amd_aat.lo: amd/amd_aat.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_aat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_aat.Tpo -c -o libglpk_la-amd_aat.lo `test -f 'amd/amd_aat.c' || echo '$(srcdir)/'`amd/amd_aat.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_aat.Tpo $(DEPDIR)/libglpk_la-amd_aat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_aat.c' object='libglpk_la-amd_aat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_aat.lo `test -f 'amd/amd_aat.c' || echo '$(srcdir)/'`amd/amd_aat.c + +libglpk_la-amd_control.lo: amd/amd_control.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_control.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_control.Tpo -c -o libglpk_la-amd_control.lo `test -f 'amd/amd_control.c' || echo '$(srcdir)/'`amd/amd_control.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_control.Tpo $(DEPDIR)/libglpk_la-amd_control.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_control.c' object='libglpk_la-amd_control.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_control.lo `test -f 'amd/amd_control.c' || echo '$(srcdir)/'`amd/amd_control.c + +libglpk_la-amd_defaults.lo: amd/amd_defaults.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_defaults.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_defaults.Tpo -c -o libglpk_la-amd_defaults.lo `test -f 'amd/amd_defaults.c' || echo '$(srcdir)/'`amd/amd_defaults.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_defaults.Tpo $(DEPDIR)/libglpk_la-amd_defaults.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_defaults.c' object='libglpk_la-amd_defaults.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_defaults.lo `test -f 'amd/amd_defaults.c' || echo '$(srcdir)/'`amd/amd_defaults.c + +libglpk_la-amd_dump.lo: amd/amd_dump.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_dump.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_dump.Tpo -c -o libglpk_la-amd_dump.lo `test -f 'amd/amd_dump.c' || echo '$(srcdir)/'`amd/amd_dump.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_dump.Tpo $(DEPDIR)/libglpk_la-amd_dump.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_dump.c' object='libglpk_la-amd_dump.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_dump.lo `test -f 'amd/amd_dump.c' || echo '$(srcdir)/'`amd/amd_dump.c + +libglpk_la-amd_info.lo: amd/amd_info.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_info.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_info.Tpo -c -o libglpk_la-amd_info.lo `test -f 'amd/amd_info.c' || echo '$(srcdir)/'`amd/amd_info.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_info.Tpo $(DEPDIR)/libglpk_la-amd_info.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_info.c' object='libglpk_la-amd_info.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_info.lo `test -f 'amd/amd_info.c' || echo '$(srcdir)/'`amd/amd_info.c + +libglpk_la-amd_order.lo: amd/amd_order.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_order.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_order.Tpo -c -o libglpk_la-amd_order.lo `test -f 'amd/amd_order.c' || echo '$(srcdir)/'`amd/amd_order.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_order.Tpo $(DEPDIR)/libglpk_la-amd_order.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_order.c' object='libglpk_la-amd_order.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_order.lo `test -f 'amd/amd_order.c' || echo '$(srcdir)/'`amd/amd_order.c + +libglpk_la-amd_post_tree.lo: amd/amd_post_tree.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_post_tree.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_post_tree.Tpo -c -o libglpk_la-amd_post_tree.lo `test -f 'amd/amd_post_tree.c' || echo '$(srcdir)/'`amd/amd_post_tree.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_post_tree.Tpo $(DEPDIR)/libglpk_la-amd_post_tree.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_post_tree.c' object='libglpk_la-amd_post_tree.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_post_tree.lo `test -f 'amd/amd_post_tree.c' || echo '$(srcdir)/'`amd/amd_post_tree.c + +libglpk_la-amd_postorder.lo: amd/amd_postorder.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_postorder.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_postorder.Tpo -c -o libglpk_la-amd_postorder.lo `test -f 'amd/amd_postorder.c' || echo '$(srcdir)/'`amd/amd_postorder.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_postorder.Tpo $(DEPDIR)/libglpk_la-amd_postorder.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_postorder.c' object='libglpk_la-amd_postorder.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_postorder.lo `test -f 'amd/amd_postorder.c' || echo '$(srcdir)/'`amd/amd_postorder.c + +libglpk_la-amd_preprocess.lo: amd/amd_preprocess.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_preprocess.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_preprocess.Tpo -c -o libglpk_la-amd_preprocess.lo `test -f 'amd/amd_preprocess.c' || echo '$(srcdir)/'`amd/amd_preprocess.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_preprocess.Tpo $(DEPDIR)/libglpk_la-amd_preprocess.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_preprocess.c' object='libglpk_la-amd_preprocess.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_preprocess.lo `test -f 'amd/amd_preprocess.c' || echo '$(srcdir)/'`amd/amd_preprocess.c + +libglpk_la-amd_valid.lo: amd/amd_valid.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_valid.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_valid.Tpo -c -o libglpk_la-amd_valid.lo `test -f 'amd/amd_valid.c' || echo '$(srcdir)/'`amd/amd_valid.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_valid.Tpo $(DEPDIR)/libglpk_la-amd_valid.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_valid.c' object='libglpk_la-amd_valid.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_valid.lo `test -f 'amd/amd_valid.c' || echo '$(srcdir)/'`amd/amd_valid.c + +libglpk_la-fhv.lo: bflib/fhv.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fhv.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fhv.Tpo -c -o libglpk_la-fhv.lo `test -f 'bflib/fhv.c' || echo '$(srcdir)/'`bflib/fhv.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fhv.Tpo $(DEPDIR)/libglpk_la-fhv.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/fhv.c' object='libglpk_la-fhv.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-fhv.lo `test -f 'bflib/fhv.c' || echo '$(srcdir)/'`bflib/fhv.c + +libglpk_la-fhvint.lo: bflib/fhvint.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fhvint.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fhvint.Tpo -c -o libglpk_la-fhvint.lo `test -f 'bflib/fhvint.c' || echo '$(srcdir)/'`bflib/fhvint.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fhvint.Tpo $(DEPDIR)/libglpk_la-fhvint.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/fhvint.c' object='libglpk_la-fhvint.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-fhvint.lo `test -f 'bflib/fhvint.c' || echo '$(srcdir)/'`bflib/fhvint.c + +libglpk_la-ifu.lo: bflib/ifu.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-ifu.lo -MD -MP -MF $(DEPDIR)/libglpk_la-ifu.Tpo -c -o libglpk_la-ifu.lo `test -f 'bflib/ifu.c' || echo '$(srcdir)/'`bflib/ifu.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-ifu.Tpo $(DEPDIR)/libglpk_la-ifu.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/ifu.c' object='libglpk_la-ifu.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-ifu.lo `test -f 'bflib/ifu.c' || echo '$(srcdir)/'`bflib/ifu.c + +libglpk_la-luf.lo: bflib/luf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-luf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-luf.Tpo -c -o libglpk_la-luf.lo `test -f 'bflib/luf.c' || echo '$(srcdir)/'`bflib/luf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-luf.Tpo $(DEPDIR)/libglpk_la-luf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/luf.c' object='libglpk_la-luf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-luf.lo `test -f 'bflib/luf.c' || echo '$(srcdir)/'`bflib/luf.c + +libglpk_la-lufint.lo: bflib/lufint.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-lufint.lo -MD -MP -MF $(DEPDIR)/libglpk_la-lufint.Tpo -c -o libglpk_la-lufint.lo `test -f 'bflib/lufint.c' || echo '$(srcdir)/'`bflib/lufint.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-lufint.Tpo $(DEPDIR)/libglpk_la-lufint.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/lufint.c' object='libglpk_la-lufint.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-lufint.lo `test -f 'bflib/lufint.c' || echo '$(srcdir)/'`bflib/lufint.c + +libglpk_la-sgf.lo: bflib/sgf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-sgf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-sgf.Tpo -c -o libglpk_la-sgf.lo `test -f 'bflib/sgf.c' || echo '$(srcdir)/'`bflib/sgf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-sgf.Tpo $(DEPDIR)/libglpk_la-sgf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/sgf.c' object='libglpk_la-sgf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-sgf.lo `test -f 'bflib/sgf.c' || echo '$(srcdir)/'`bflib/sgf.c + +libglpk_la-sva.lo: bflib/sva.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-sva.lo -MD -MP -MF $(DEPDIR)/libglpk_la-sva.Tpo -c -o libglpk_la-sva.lo `test -f 'bflib/sva.c' || echo '$(srcdir)/'`bflib/sva.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-sva.Tpo $(DEPDIR)/libglpk_la-sva.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/sva.c' object='libglpk_la-sva.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-sva.lo `test -f 'bflib/sva.c' || echo '$(srcdir)/'`bflib/sva.c + +libglpk_la-cfg.lo: cglib/cfg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-cfg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-cfg.Tpo -c -o libglpk_la-cfg.lo `test -f 'cglib/cfg.c' || echo '$(srcdir)/'`cglib/cfg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-cfg.Tpo $(DEPDIR)/libglpk_la-cfg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cglib/cfg.c' object='libglpk_la-cfg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-cfg.lo `test -f 'cglib/cfg.c' || echo '$(srcdir)/'`cglib/cfg.c + +libglpk_la-cfg1.lo: cglib/cfg1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-cfg1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-cfg1.Tpo -c -o libglpk_la-cfg1.lo `test -f 'cglib/cfg1.c' || echo '$(srcdir)/'`cglib/cfg1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-cfg1.Tpo $(DEPDIR)/libglpk_la-cfg1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cglib/cfg1.c' object='libglpk_la-cfg1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-cfg1.lo `test -f 'cglib/cfg1.c' || echo '$(srcdir)/'`cglib/cfg1.c + +libglpk_la-colamd.lo: colamd/colamd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-colamd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-colamd.Tpo -c -o libglpk_la-colamd.lo `test -f 'colamd/colamd.c' || echo '$(srcdir)/'`colamd/colamd.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-colamd.Tpo $(DEPDIR)/libglpk_la-colamd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='colamd/colamd.c' object='libglpk_la-colamd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-colamd.lo `test -f 'colamd/colamd.c' || echo '$(srcdir)/'`colamd/colamd.c + +libglpk_la-alloc.lo: env/alloc.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-alloc.lo -MD -MP -MF $(DEPDIR)/libglpk_la-alloc.Tpo -c -o libglpk_la-alloc.lo `test -f 'env/alloc.c' || echo '$(srcdir)/'`env/alloc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-alloc.Tpo $(DEPDIR)/libglpk_la-alloc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/alloc.c' object='libglpk_la-alloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-alloc.lo `test -f 'env/alloc.c' || echo '$(srcdir)/'`env/alloc.c + +libglpk_la-dlsup.lo: env/dlsup.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-dlsup.lo -MD -MP -MF $(DEPDIR)/libglpk_la-dlsup.Tpo -c -o libglpk_la-dlsup.lo `test -f 'env/dlsup.c' || echo '$(srcdir)/'`env/dlsup.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-dlsup.Tpo $(DEPDIR)/libglpk_la-dlsup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/dlsup.c' object='libglpk_la-dlsup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-dlsup.lo `test -f 'env/dlsup.c' || echo '$(srcdir)/'`env/dlsup.c + +libglpk_la-env.lo: env/env.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-env.lo -MD -MP -MF $(DEPDIR)/libglpk_la-env.Tpo -c -o libglpk_la-env.lo `test -f 'env/env.c' || echo '$(srcdir)/'`env/env.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-env.Tpo $(DEPDIR)/libglpk_la-env.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/env.c' object='libglpk_la-env.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-env.lo `test -f 'env/env.c' || echo '$(srcdir)/'`env/env.c + +libglpk_la-error.lo: env/error.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-error.lo -MD -MP -MF $(DEPDIR)/libglpk_la-error.Tpo -c -o libglpk_la-error.lo `test -f 'env/error.c' || echo '$(srcdir)/'`env/error.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-error.Tpo $(DEPDIR)/libglpk_la-error.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/error.c' object='libglpk_la-error.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-error.lo `test -f 'env/error.c' || echo '$(srcdir)/'`env/error.c + +libglpk_la-stdout.lo: env/stdout.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-stdout.lo -MD -MP -MF $(DEPDIR)/libglpk_la-stdout.Tpo -c -o libglpk_la-stdout.lo `test -f 'env/stdout.c' || echo '$(srcdir)/'`env/stdout.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-stdout.Tpo $(DEPDIR)/libglpk_la-stdout.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/stdout.c' object='libglpk_la-stdout.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-stdout.lo `test -f 'env/stdout.c' || echo '$(srcdir)/'`env/stdout.c + +libglpk_la-stream.lo: env/stream.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-stream.lo -MD -MP -MF $(DEPDIR)/libglpk_la-stream.Tpo -c -o libglpk_la-stream.lo `test -f 'env/stream.c' || echo '$(srcdir)/'`env/stream.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-stream.Tpo $(DEPDIR)/libglpk_la-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/stream.c' object='libglpk_la-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-stream.lo `test -f 'env/stream.c' || echo '$(srcdir)/'`env/stream.c + +libglpk_la-time.lo: env/time.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-time.lo -MD -MP -MF $(DEPDIR)/libglpk_la-time.Tpo -c -o libglpk_la-time.lo `test -f 'env/time.c' || echo '$(srcdir)/'`env/time.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-time.Tpo $(DEPDIR)/libglpk_la-time.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/time.c' object='libglpk_la-time.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-time.lo `test -f 'env/time.c' || echo '$(srcdir)/'`env/time.c + +libglpk_la-tls.lo: env/tls.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-tls.lo -MD -MP -MF $(DEPDIR)/libglpk_la-tls.Tpo -c -o libglpk_la-tls.lo `test -f 'env/tls.c' || echo '$(srcdir)/'`env/tls.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-tls.Tpo $(DEPDIR)/libglpk_la-tls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/tls.c' object='libglpk_la-tls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-tls.lo `test -f 'env/tls.c' || echo '$(srcdir)/'`env/tls.c + +libglpk_la-minisat.lo: minisat/minisat.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-minisat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-minisat.Tpo -c -o libglpk_la-minisat.lo `test -f 'minisat/minisat.c' || echo '$(srcdir)/'`minisat/minisat.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-minisat.Tpo $(DEPDIR)/libglpk_la-minisat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='minisat/minisat.c' object='libglpk_la-minisat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-minisat.lo `test -f 'minisat/minisat.c' || echo '$(srcdir)/'`minisat/minisat.c + +libglpk_la-bignum.lo: misc/bignum.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-bignum.lo -MD -MP -MF $(DEPDIR)/libglpk_la-bignum.Tpo -c -o libglpk_la-bignum.lo `test -f 'misc/bignum.c' || echo '$(srcdir)/'`misc/bignum.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-bignum.Tpo $(DEPDIR)/libglpk_la-bignum.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/bignum.c' object='libglpk_la-bignum.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-bignum.lo `test -f 'misc/bignum.c' || echo '$(srcdir)/'`misc/bignum.c + +libglpk_la-dmp.lo: misc/dmp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-dmp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-dmp.Tpo -c -o libglpk_la-dmp.lo `test -f 'misc/dmp.c' || echo '$(srcdir)/'`misc/dmp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-dmp.Tpo $(DEPDIR)/libglpk_la-dmp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/dmp.c' object='libglpk_la-dmp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-dmp.lo `test -f 'misc/dmp.c' || echo '$(srcdir)/'`misc/dmp.c + +libglpk_la-ffalg.lo: misc/ffalg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-ffalg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-ffalg.Tpo -c -o libglpk_la-ffalg.lo `test -f 'misc/ffalg.c' || echo '$(srcdir)/'`misc/ffalg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-ffalg.Tpo $(DEPDIR)/libglpk_la-ffalg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/ffalg.c' object='libglpk_la-ffalg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-ffalg.lo `test -f 'misc/ffalg.c' || echo '$(srcdir)/'`misc/ffalg.c + +libglpk_la-fp2rat.lo: misc/fp2rat.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fp2rat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fp2rat.Tpo -c -o libglpk_la-fp2rat.lo `test -f 'misc/fp2rat.c' || echo '$(srcdir)/'`misc/fp2rat.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fp2rat.Tpo $(DEPDIR)/libglpk_la-fp2rat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/fp2rat.c' object='libglpk_la-fp2rat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-fp2rat.lo `test -f 'misc/fp2rat.c' || echo '$(srcdir)/'`misc/fp2rat.c + +libglpk_la-gcd.lo: misc/gcd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gcd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gcd.Tpo -c -o libglpk_la-gcd.lo `test -f 'misc/gcd.c' || echo '$(srcdir)/'`misc/gcd.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gcd.Tpo $(DEPDIR)/libglpk_la-gcd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/gcd.c' object='libglpk_la-gcd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gcd.lo `test -f 'misc/gcd.c' || echo '$(srcdir)/'`misc/gcd.c + +libglpk_la-jd.lo: misc/jd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-jd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-jd.Tpo -c -o libglpk_la-jd.lo `test -f 'misc/jd.c' || echo '$(srcdir)/'`misc/jd.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-jd.Tpo $(DEPDIR)/libglpk_la-jd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/jd.c' object='libglpk_la-jd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-jd.lo `test -f 'misc/jd.c' || echo '$(srcdir)/'`misc/jd.c + +libglpk_la-keller.lo: misc/keller.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-keller.lo -MD -MP -MF $(DEPDIR)/libglpk_la-keller.Tpo -c -o libglpk_la-keller.lo `test -f 'misc/keller.c' || echo '$(srcdir)/'`misc/keller.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-keller.Tpo $(DEPDIR)/libglpk_la-keller.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/keller.c' object='libglpk_la-keller.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-keller.lo `test -f 'misc/keller.c' || echo '$(srcdir)/'`misc/keller.c + +libglpk_la-mc13d.lo: misc/mc13d.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mc13d.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mc13d.Tpo -c -o libglpk_la-mc13d.lo `test -f 'misc/mc13d.c' || echo '$(srcdir)/'`misc/mc13d.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mc13d.Tpo $(DEPDIR)/libglpk_la-mc13d.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/mc13d.c' object='libglpk_la-mc13d.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mc13d.lo `test -f 'misc/mc13d.c' || echo '$(srcdir)/'`misc/mc13d.c + +libglpk_la-mc21a.lo: misc/mc21a.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mc21a.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mc21a.Tpo -c -o libglpk_la-mc21a.lo `test -f 'misc/mc21a.c' || echo '$(srcdir)/'`misc/mc21a.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mc21a.Tpo $(DEPDIR)/libglpk_la-mc21a.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/mc21a.c' object='libglpk_la-mc21a.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mc21a.lo `test -f 'misc/mc21a.c' || echo '$(srcdir)/'`misc/mc21a.c + +libglpk_la-okalg.lo: misc/okalg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-okalg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-okalg.Tpo -c -o libglpk_la-okalg.lo `test -f 'misc/okalg.c' || echo '$(srcdir)/'`misc/okalg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-okalg.Tpo $(DEPDIR)/libglpk_la-okalg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/okalg.c' object='libglpk_la-okalg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-okalg.lo `test -f 'misc/okalg.c' || echo '$(srcdir)/'`misc/okalg.c + +libglpk_la-qmd.lo: misc/qmd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-qmd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-qmd.Tpo -c -o libglpk_la-qmd.lo `test -f 'misc/qmd.c' || echo '$(srcdir)/'`misc/qmd.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-qmd.Tpo $(DEPDIR)/libglpk_la-qmd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/qmd.c' object='libglpk_la-qmd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-qmd.lo `test -f 'misc/qmd.c' || echo '$(srcdir)/'`misc/qmd.c + +libglpk_la-relax4.lo: misc/relax4.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-relax4.lo -MD -MP -MF $(DEPDIR)/libglpk_la-relax4.Tpo -c -o libglpk_la-relax4.lo `test -f 'misc/relax4.c' || echo '$(srcdir)/'`misc/relax4.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-relax4.Tpo $(DEPDIR)/libglpk_la-relax4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/relax4.c' object='libglpk_la-relax4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-relax4.lo `test -f 'misc/relax4.c' || echo '$(srcdir)/'`misc/relax4.c + +libglpk_la-rng.lo: misc/rng.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rng.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rng.Tpo -c -o libglpk_la-rng.lo `test -f 'misc/rng.c' || echo '$(srcdir)/'`misc/rng.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rng.Tpo $(DEPDIR)/libglpk_la-rng.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/rng.c' object='libglpk_la-rng.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rng.lo `test -f 'misc/rng.c' || echo '$(srcdir)/'`misc/rng.c + +libglpk_la-rng1.lo: misc/rng1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rng1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rng1.Tpo -c -o libglpk_la-rng1.lo `test -f 'misc/rng1.c' || echo '$(srcdir)/'`misc/rng1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rng1.Tpo $(DEPDIR)/libglpk_la-rng1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/rng1.c' object='libglpk_la-rng1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rng1.lo `test -f 'misc/rng1.c' || echo '$(srcdir)/'`misc/rng1.c + +libglpk_la-round2n.lo: misc/round2n.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-round2n.lo -MD -MP -MF $(DEPDIR)/libglpk_la-round2n.Tpo -c -o libglpk_la-round2n.lo `test -f 'misc/round2n.c' || echo '$(srcdir)/'`misc/round2n.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-round2n.Tpo $(DEPDIR)/libglpk_la-round2n.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/round2n.c' object='libglpk_la-round2n.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-round2n.lo `test -f 'misc/round2n.c' || echo '$(srcdir)/'`misc/round2n.c + +libglpk_la-str2int.lo: misc/str2int.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-str2int.lo -MD -MP -MF $(DEPDIR)/libglpk_la-str2int.Tpo -c -o libglpk_la-str2int.lo `test -f 'misc/str2int.c' || echo '$(srcdir)/'`misc/str2int.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-str2int.Tpo $(DEPDIR)/libglpk_la-str2int.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/str2int.c' object='libglpk_la-str2int.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-str2int.lo `test -f 'misc/str2int.c' || echo '$(srcdir)/'`misc/str2int.c + +libglpk_la-str2num.lo: misc/str2num.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-str2num.lo -MD -MP -MF $(DEPDIR)/libglpk_la-str2num.Tpo -c -o libglpk_la-str2num.lo `test -f 'misc/str2num.c' || echo '$(srcdir)/'`misc/str2num.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-str2num.Tpo $(DEPDIR)/libglpk_la-str2num.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/str2num.c' object='libglpk_la-str2num.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-str2num.lo `test -f 'misc/str2num.c' || echo '$(srcdir)/'`misc/str2num.c + +libglpk_la-strspx.lo: misc/strspx.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-strspx.lo -MD -MP -MF $(DEPDIR)/libglpk_la-strspx.Tpo -c -o libglpk_la-strspx.lo `test -f 'misc/strspx.c' || echo '$(srcdir)/'`misc/strspx.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-strspx.Tpo $(DEPDIR)/libglpk_la-strspx.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/strspx.c' object='libglpk_la-strspx.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-strspx.lo `test -f 'misc/strspx.c' || echo '$(srcdir)/'`misc/strspx.c + +libglpk_la-strtrim.lo: misc/strtrim.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-strtrim.lo -MD -MP -MF $(DEPDIR)/libglpk_la-strtrim.Tpo -c -o libglpk_la-strtrim.lo `test -f 'misc/strtrim.c' || echo '$(srcdir)/'`misc/strtrim.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-strtrim.Tpo $(DEPDIR)/libglpk_la-strtrim.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/strtrim.c' object='libglpk_la-strtrim.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-strtrim.lo `test -f 'misc/strtrim.c' || echo '$(srcdir)/'`misc/strtrim.c + +libglpk_la-triang.lo: misc/triang.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-triang.lo -MD -MP -MF $(DEPDIR)/libglpk_la-triang.Tpo -c -o libglpk_la-triang.lo `test -f 'misc/triang.c' || echo '$(srcdir)/'`misc/triang.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-triang.Tpo $(DEPDIR)/libglpk_la-triang.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/triang.c' object='libglpk_la-triang.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-triang.lo `test -f 'misc/triang.c' || echo '$(srcdir)/'`misc/triang.c + +libglpk_la-wclique.lo: misc/wclique.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wclique.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wclique.Tpo -c -o libglpk_la-wclique.lo `test -f 'misc/wclique.c' || echo '$(srcdir)/'`misc/wclique.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wclique.Tpo $(DEPDIR)/libglpk_la-wclique.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/wclique.c' object='libglpk_la-wclique.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wclique.lo `test -f 'misc/wclique.c' || echo '$(srcdir)/'`misc/wclique.c + +libglpk_la-wclique1.lo: misc/wclique1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wclique1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wclique1.Tpo -c -o libglpk_la-wclique1.lo `test -f 'misc/wclique1.c' || echo '$(srcdir)/'`misc/wclique1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wclique1.Tpo $(DEPDIR)/libglpk_la-wclique1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/wclique1.c' object='libglpk_la-wclique1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wclique1.lo `test -f 'misc/wclique1.c' || echo '$(srcdir)/'`misc/wclique1.c + +libglpk_la-proxy.lo: proxy/proxy.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-proxy.lo -MD -MP -MF $(DEPDIR)/libglpk_la-proxy.Tpo -c -o libglpk_la-proxy.lo `test -f 'proxy/proxy.c' || echo '$(srcdir)/'`proxy/proxy.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-proxy.Tpo $(DEPDIR)/libglpk_la-proxy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='proxy/proxy.c' object='libglpk_la-proxy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-proxy.lo `test -f 'proxy/proxy.c' || echo '$(srcdir)/'`proxy/proxy.c + +libglpk_la-proxy1.lo: proxy/proxy1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-proxy1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-proxy1.Tpo -c -o libglpk_la-proxy1.lo `test -f 'proxy/proxy1.c' || echo '$(srcdir)/'`proxy/proxy1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-proxy1.Tpo $(DEPDIR)/libglpk_la-proxy1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='proxy/proxy1.c' object='libglpk_la-proxy1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-proxy1.lo `test -f 'proxy/proxy1.c' || echo '$(srcdir)/'`proxy/proxy1.c + +libglpk_la-adler32.lo: zlib/adler32.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-adler32.lo -MD -MP -MF $(DEPDIR)/libglpk_la-adler32.Tpo -c -o libglpk_la-adler32.lo `test -f 'zlib/adler32.c' || echo '$(srcdir)/'`zlib/adler32.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-adler32.Tpo $(DEPDIR)/libglpk_la-adler32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/adler32.c' object='libglpk_la-adler32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-adler32.lo `test -f 'zlib/adler32.c' || echo '$(srcdir)/'`zlib/adler32.c + +libglpk_la-compress.lo: zlib/compress.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-compress.lo -MD -MP -MF $(DEPDIR)/libglpk_la-compress.Tpo -c -o libglpk_la-compress.lo `test -f 'zlib/compress.c' || echo '$(srcdir)/'`zlib/compress.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-compress.Tpo $(DEPDIR)/libglpk_la-compress.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/compress.c' object='libglpk_la-compress.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-compress.lo `test -f 'zlib/compress.c' || echo '$(srcdir)/'`zlib/compress.c + +libglpk_la-crc32.lo: zlib/crc32.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-crc32.lo -MD -MP -MF $(DEPDIR)/libglpk_la-crc32.Tpo -c -o libglpk_la-crc32.lo `test -f 'zlib/crc32.c' || echo '$(srcdir)/'`zlib/crc32.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-crc32.Tpo $(DEPDIR)/libglpk_la-crc32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/crc32.c' object='libglpk_la-crc32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-crc32.lo `test -f 'zlib/crc32.c' || echo '$(srcdir)/'`zlib/crc32.c + +libglpk_la-deflate.lo: zlib/deflate.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-deflate.lo -MD -MP -MF $(DEPDIR)/libglpk_la-deflate.Tpo -c -o libglpk_la-deflate.lo `test -f 'zlib/deflate.c' || echo '$(srcdir)/'`zlib/deflate.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-deflate.Tpo $(DEPDIR)/libglpk_la-deflate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/deflate.c' object='libglpk_la-deflate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-deflate.lo `test -f 'zlib/deflate.c' || echo '$(srcdir)/'`zlib/deflate.c + +libglpk_la-gzclose.lo: zlib/gzclose.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzclose.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzclose.Tpo -c -o libglpk_la-gzclose.lo `test -f 'zlib/gzclose.c' || echo '$(srcdir)/'`zlib/gzclose.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzclose.Tpo $(DEPDIR)/libglpk_la-gzclose.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzclose.c' object='libglpk_la-gzclose.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzclose.lo `test -f 'zlib/gzclose.c' || echo '$(srcdir)/'`zlib/gzclose.c + +libglpk_la-gzlib.lo: zlib/gzlib.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzlib.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzlib.Tpo -c -o libglpk_la-gzlib.lo `test -f 'zlib/gzlib.c' || echo '$(srcdir)/'`zlib/gzlib.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzlib.Tpo $(DEPDIR)/libglpk_la-gzlib.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzlib.c' object='libglpk_la-gzlib.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzlib.lo `test -f 'zlib/gzlib.c' || echo '$(srcdir)/'`zlib/gzlib.c + +libglpk_la-gzread.lo: zlib/gzread.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzread.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzread.Tpo -c -o libglpk_la-gzread.lo `test -f 'zlib/gzread.c' || echo '$(srcdir)/'`zlib/gzread.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzread.Tpo $(DEPDIR)/libglpk_la-gzread.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzread.c' object='libglpk_la-gzread.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzread.lo `test -f 'zlib/gzread.c' || echo '$(srcdir)/'`zlib/gzread.c + +libglpk_la-gzwrite.lo: zlib/gzwrite.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzwrite.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzwrite.Tpo -c -o libglpk_la-gzwrite.lo `test -f 'zlib/gzwrite.c' || echo '$(srcdir)/'`zlib/gzwrite.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzwrite.Tpo $(DEPDIR)/libglpk_la-gzwrite.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzwrite.c' object='libglpk_la-gzwrite.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzwrite.lo `test -f 'zlib/gzwrite.c' || echo '$(srcdir)/'`zlib/gzwrite.c + +libglpk_la-inffast.lo: zlib/inffast.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-inffast.lo -MD -MP -MF $(DEPDIR)/libglpk_la-inffast.Tpo -c -o libglpk_la-inffast.lo `test -f 'zlib/inffast.c' || echo '$(srcdir)/'`zlib/inffast.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-inffast.Tpo $(DEPDIR)/libglpk_la-inffast.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/inffast.c' object='libglpk_la-inffast.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-inffast.lo `test -f 'zlib/inffast.c' || echo '$(srcdir)/'`zlib/inffast.c + +libglpk_la-inflate.lo: zlib/inflate.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-inflate.lo -MD -MP -MF $(DEPDIR)/libglpk_la-inflate.Tpo -c -o libglpk_la-inflate.lo `test -f 'zlib/inflate.c' || echo '$(srcdir)/'`zlib/inflate.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-inflate.Tpo $(DEPDIR)/libglpk_la-inflate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/inflate.c' object='libglpk_la-inflate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-inflate.lo `test -f 'zlib/inflate.c' || echo '$(srcdir)/'`zlib/inflate.c + +libglpk_la-inftrees.lo: zlib/inftrees.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-inftrees.lo -MD -MP -MF $(DEPDIR)/libglpk_la-inftrees.Tpo -c -o libglpk_la-inftrees.lo `test -f 'zlib/inftrees.c' || echo '$(srcdir)/'`zlib/inftrees.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-inftrees.Tpo $(DEPDIR)/libglpk_la-inftrees.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/inftrees.c' object='libglpk_la-inftrees.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-inftrees.lo `test -f 'zlib/inftrees.c' || echo '$(srcdir)/'`zlib/inftrees.c + +libglpk_la-trees.lo: zlib/trees.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-trees.lo -MD -MP -MF $(DEPDIR)/libglpk_la-trees.Tpo -c -o libglpk_la-trees.lo `test -f 'zlib/trees.c' || echo '$(srcdir)/'`zlib/trees.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-trees.Tpo $(DEPDIR)/libglpk_la-trees.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/trees.c' object='libglpk_la-trees.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-trees.lo `test -f 'zlib/trees.c' || echo '$(srcdir)/'`zlib/trees.c + +libglpk_la-uncompr.lo: zlib/uncompr.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-uncompr.lo -MD -MP -MF $(DEPDIR)/libglpk_la-uncompr.Tpo -c -o libglpk_la-uncompr.lo `test -f 'zlib/uncompr.c' || echo '$(srcdir)/'`zlib/uncompr.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-uncompr.Tpo $(DEPDIR)/libglpk_la-uncompr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/uncompr.c' object='libglpk_la-uncompr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-uncompr.lo `test -f 'zlib/uncompr.c' || echo '$(srcdir)/'`zlib/uncompr.c + +libglpk_la-zio.lo: zlib/zio.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-zio.lo -MD -MP -MF $(DEPDIR)/libglpk_la-zio.Tpo -c -o libglpk_la-zio.lo `test -f 'zlib/zio.c' || echo '$(srcdir)/'`zlib/zio.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-zio.Tpo $(DEPDIR)/libglpk_la-zio.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/zio.c' object='libglpk_la-zio.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-zio.lo `test -f 'zlib/zio.c' || echo '$(srcdir)/'`zlib/zio.c + +libglpk_la-zutil.lo: zlib/zutil.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-zutil.lo -MD -MP -MF $(DEPDIR)/libglpk_la-zutil.Tpo -c -o libglpk_la-zutil.lo `test -f 'zlib/zutil.c' || echo '$(srcdir)/'`zlib/zutil.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-zutil.Tpo $(DEPDIR)/libglpk_la-zutil.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/zutil.c' object='libglpk_la-zutil.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-zutil.lo `test -f 'zlib/zutil.c' || echo '$(srcdir)/'`zlib/zutil.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +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)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$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)$(includedir)"; 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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +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-includeHEADERS uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist 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-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-includeHEADERS install-info \ + install-info-am install-libLTLIBRARIES install-man install-pdf \ + install-pdf-am install-ps install-ps-am 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-includeHEADERS \ + 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: diff --git a/resources/3rdparty/glpk-4.53/src/amd/COPYING b/resources/3rdparty/glpk-4.53/src/amd/COPYING new file mode 100644 index 000000000..84bba36d0 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/COPYING @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/resources/3rdparty/glpk-4.53/src/amd/README b/resources/3rdparty/glpk-4.53/src/amd/README new file mode 100644 index 000000000..de950eb48 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/README @@ -0,0 +1,58 @@ +NOTE: Files in this subdirectory are NOT part of the GLPK package, but + are used with GLPK. + + The original code was modified according to GLPK requirements by + Andrew Makhorin <mao@gnu.org>. +************************************************************************ +AMD Version 2.2, Copyright (C) 2007 by Timothy A. Davis, +Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. + +Description: + + AMD is a set of routines for pre-ordering sparse matrices prior to + Cholesky or LU factorization, using the approximate minimum degree + ordering algorithm. Written in ANSI/ISO C with a MATLAB interface, + and in Fortran 77. + +Authors: + + Timothy A. Davis (davis at cise.ufl.edu), University of Florida. + Patrick R. Amestoy, ENSEEIHT, Toulouse, France. + Iain S. Duff, Rutherford Appleton Laboratory, UK. + +AMD License: + + Your use or distribution of AMD or any modified version of AMD + implies that you agree to this License. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA. + + Permission is hereby granted to use or copy this program under the + terms of the GNU LGPL, provided that the Copyright, this License, + and the Availability of the original version is retained on all + copies. User documentation of any code that uses this code or any + modified version of this code must cite the Copyright, this License, + the Availability note, and "Used by permission." Permission to + modify the code and to distribute modified code is granted, provided + the Copyright, this License, and the Availability note are retained, + and a notice that the code was modified is included. + + AMD is available under alternate licences; contact T. Davis for + details. + +Availability: + + http://www.cise.ufl.edu/research/sparse/amd diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd.h b/resources/3rdparty/glpk-4.53/src/amd/amd.h new file mode 100644 index 000000000..be662d954 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd.h @@ -0,0 +1,67 @@ +/* amd.h */ + +/* Written by Andrew Makhorin <mao@gnu.org>. */ + +#ifndef GLPAMD_H +#define GLPAMD_H + +#define AMD_DATE "May 31, 2007" +#define AMD_VERSION_CODE(main, sub) ((main) * 1000 + (sub)) +#define AMD_MAIN_VERSION 2 +#define AMD_SUB_VERSION 2 +#define AMD_SUBSUB_VERSION 0 +#define AMD_VERSION AMD_VERSION_CODE(AMD_MAIN_VERSION, AMD_SUB_VERSION) + +#define AMD_CONTROL 5 +#define AMD_INFO 20 + +#define AMD_DENSE 0 +#define AMD_AGGRESSIVE 1 + +#define AMD_DEFAULT_DENSE 10.0 +#define AMD_DEFAULT_AGGRESSIVE 1 + +#define AMD_STATUS 0 +#define AMD_N 1 +#define AMD_NZ 2 +#define AMD_SYMMETRY 3 +#define AMD_NZDIAG 4 +#define AMD_NZ_A_PLUS_AT 5 +#define AMD_NDENSE 6 +#define AMD_MEMORY 7 +#define AMD_NCMPA 8 +#define AMD_LNZ 9 +#define AMD_NDIV 10 +#define AMD_NMULTSUBS_LDL 11 +#define AMD_NMULTSUBS_LU 12 +#define AMD_DMAX 13 + +#define AMD_OK 0 +#define AMD_OUT_OF_MEMORY (-1) +#define AMD_INVALID (-2) +#define AMD_OK_BUT_JUMBLED 1 + +#define amd_order _glp_amd_order +int amd_order(int n, const int Ap[], const int Ai[], int P[], + double Control[], double Info[]); + +#define amd_2 _glp_amd_2 +void amd_2(int n, int Pe[], int Iw[], int Len[], int iwlen, int pfree, + int Nv[], int Next[], int Last[], int Head[], int Elen[], + int Degree[], int W[], double Control[], double Info[]); + +#define amd_valid _glp_amd_valid +int amd_valid(int n_row, int n_col, const int Ap[], const int Ai[]); + +#define amd_defaults _glp_amd_defaults +void amd_defaults(double Control[]); + +#define amd_control _glp_amd_control +void amd_control(double Control[]); + +#define amd_info _glp_amd_info +void amd_info(double Info[]); + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_1.c b/resources/3rdparty/glpk-4.53/src/amd/amd_1.c new file mode 100644 index 000000000..4f9b07d7c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_1.c @@ -0,0 +1,181 @@ +/* ========================================================================= */ +/* === AMD_1 =============================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* AMD_1: Construct A+A' for a sparse matrix A and perform the AMD ordering. + * + * The n-by-n sparse matrix A can be unsymmetric. It is stored in MATLAB-style + * compressed-column form, with sorted row indices in each column, and no + * duplicate entries. Diagonal entries may be present, but they are ignored. + * Row indices of column j of A are stored in Ai [Ap [j] ... Ap [j+1]-1]. + * Ap [0] must be zero, and nz = Ap [n] is the number of entries in A. The + * size of the matrix, n, must be greater than or equal to zero. + * + * This routine must be preceded by a call to AMD_aat, which computes the + * number of entries in each row/column in A+A', excluding the diagonal. + * Len [j], on input, is the number of entries in row/column j of A+A'. This + * routine constructs the matrix A+A' and then calls AMD_2. No error checking + * is performed (this was done in AMD_valid). + */ + +#include "amd_internal.h" + +GLOBAL void AMD_1 +( + Int n, /* n > 0 */ + const Int Ap [ ], /* input of size n+1, not modified */ + const Int Ai [ ], /* input of size nz = Ap [n], not modified */ + Int P [ ], /* size n output permutation */ + Int Pinv [ ], /* size n output inverse permutation */ + Int Len [ ], /* size n input, undefined on output */ + Int slen, /* slen >= sum (Len [0..n-1]) + 7n, + * ideally slen = 1.2 * sum (Len) + 8n */ + Int S [ ], /* size slen workspace */ + double Control [ ], /* input array of size AMD_CONTROL */ + double Info [ ] /* output array of size AMD_INFO */ +) +{ + Int i, j, k, p, pfree, iwlen, pj, p1, p2, pj2, *Iw, *Pe, *Nv, *Head, + *Elen, *Degree, *s, *W, *Sp, *Tp ; + + /* --------------------------------------------------------------------- */ + /* construct the matrix for AMD_2 */ + /* --------------------------------------------------------------------- */ + + ASSERT (n > 0) ; + + iwlen = slen - 6*n ; + s = S ; + Pe = s ; s += n ; + Nv = s ; s += n ; + Head = s ; s += n ; + Elen = s ; s += n ; + Degree = s ; s += n ; + W = s ; s += n ; + Iw = s ; s += iwlen ; + + ASSERT (AMD_valid (n, n, Ap, Ai) == AMD_OK) ; + + /* construct the pointers for A+A' */ + Sp = Nv ; /* use Nv and W as workspace for Sp and Tp [ */ + Tp = W ; + pfree = 0 ; + for (j = 0 ; j < n ; j++) + { + Pe [j] = pfree ; + Sp [j] = pfree ; + pfree += Len [j] ; + } + + /* Note that this restriction on iwlen is slightly more restrictive than + * what is strictly required in AMD_2. AMD_2 can operate with no elbow + * room at all, but it will be very slow. For better performance, at + * least size-n elbow room is enforced. */ + ASSERT (iwlen >= pfree + n) ; + +#ifndef NDEBUG + for (p = 0 ; p < iwlen ; p++) Iw [p] = EMPTY ; +#endif + + for (k = 0 ; k < n ; k++) + { + AMD_DEBUG1 (("Construct row/column k= "ID" of A+A'\n", k)) ; + p1 = Ap [k] ; + p2 = Ap [k+1] ; + + /* construct A+A' */ + for (p = p1 ; p < p2 ; ) + { + /* scan the upper triangular part of A */ + j = Ai [p] ; + ASSERT (j >= 0 && j < n) ; + if (j < k) + { + /* entry A (j,k) in the strictly upper triangular part */ + ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; + ASSERT (Sp [k] < (k == n-1 ? pfree : Pe [k+1])) ; + Iw [Sp [j]++] = k ; + Iw [Sp [k]++] = j ; + p++ ; + } + else if (j == k) + { + /* skip the diagonal */ + p++ ; + break ; + } + else /* j > k */ + { + /* first entry below the diagonal */ + break ; + } + /* scan lower triangular part of A, in column j until reaching + * row k. Start where last scan left off. */ + ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ; + pj2 = Ap [j+1] ; + for (pj = Tp [j] ; pj < pj2 ; ) + { + i = Ai [pj] ; + ASSERT (i >= 0 && i < n) ; + if (i < k) + { + /* A (i,j) is only in the lower part, not in upper */ + ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ; + ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; + Iw [Sp [i]++] = j ; + Iw [Sp [j]++] = i ; + pj++ ; + } + else if (i == k) + { + /* entry A (k,j) in lower part and A (j,k) in upper */ + pj++ ; + break ; + } + else /* i > k */ + { + /* consider this entry later, when k advances to i */ + break ; + } + } + Tp [j] = pj ; + } + Tp [k] = p ; + } + + /* clean up, for remaining mismatched entries */ + for (j = 0 ; j < n ; j++) + { + for (pj = Tp [j] ; pj < Ap [j+1] ; pj++) + { + i = Ai [pj] ; + ASSERT (i >= 0 && i < n) ; + /* A (i,j) is only in the lower part, not in upper */ + ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ; + ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; + Iw [Sp [i]++] = j ; + Iw [Sp [j]++] = i ; + } + } + +#ifndef NDEBUG + for (j = 0 ; j < n-1 ; j++) ASSERT (Sp [j] == Pe [j+1]) ; + ASSERT (Sp [n-1] == pfree) ; +#endif + + /* Tp and Sp no longer needed ] */ + + /* --------------------------------------------------------------------- */ + /* order the matrix */ + /* --------------------------------------------------------------------- */ + + AMD_2 (n, Pe, Iw, Len, iwlen, pfree, + Nv, Pinv, P, Head, Elen, Degree, W, Control, Info) ; +} diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_2.c b/resources/3rdparty/glpk-4.53/src/amd/amd_2.c new file mode 100644 index 000000000..b448fc93c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_2.c @@ -0,0 +1,1842 @@ +/* ========================================================================= */ +/* === AMD_2 =============================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* AMD_2: performs the AMD ordering on a symmetric sparse matrix A, followed + * by a postordering (via depth-first search) of the assembly tree using the + * AMD_postorder routine. + */ + +#include "amd_internal.h" + +/* ========================================================================= */ +/* === clear_flag ========================================================== */ +/* ========================================================================= */ + +static Int clear_flag (Int wflg, Int wbig, Int W [ ], Int n) +{ + Int x ; + if (wflg < 2 || wflg >= wbig) + { + for (x = 0 ; x < n ; x++) + { + if (W [x] != 0) W [x] = 1 ; + } + wflg = 2 ; + } + /* at this point, W [0..n-1] < wflg holds */ + return (wflg) ; +} + + +/* ========================================================================= */ +/* === AMD_2 =============================================================== */ +/* ========================================================================= */ + +GLOBAL void AMD_2 +( + Int n, /* A is n-by-n, where n > 0 */ + Int Pe [ ], /* Pe [0..n-1]: index in Iw of row i on input */ + Int Iw [ ], /* workspace of size iwlen. Iw [0..pfree-1] + * holds the matrix on input */ + Int Len [ ], /* Len [0..n-1]: length for row/column i on input */ + Int iwlen, /* length of Iw. iwlen >= pfree + n */ + Int pfree, /* Iw [pfree ... iwlen-1] is empty on input */ + + /* 7 size-n workspaces, not defined on input: */ + Int Nv [ ], /* the size of each supernode on output */ + Int Next [ ], /* the output inverse permutation */ + Int Last [ ], /* the output permutation */ + Int Head [ ], + Int Elen [ ], /* the size columns of L for each supernode */ + Int Degree [ ], + Int W [ ], + + /* control parameters and output statistics */ + double Control [ ], /* array of size AMD_CONTROL */ + double Info [ ] /* array of size AMD_INFO */ +) +{ + +/* + * Given a representation of the nonzero pattern of a symmetric matrix, A, + * (excluding the diagonal) perform an approximate minimum (UMFPACK/MA38-style) + * degree ordering to compute a pivot order such that the introduction of + * nonzeros (fill-in) in the Cholesky factors A = LL' is kept low. At each + * step, the pivot selected is the one with the minimum UMFAPACK/MA38-style + * upper-bound on the external degree. This routine can optionally perform + * aggresive absorption (as done by MC47B in the Harwell Subroutine + * Library). + * + * The approximate degree algorithm implemented here is the symmetric analog of + * the degree update algorithm in MA38 and UMFPACK (the Unsymmetric-pattern + * MultiFrontal PACKage, both by Davis and Duff). The routine is based on the + * MA27 minimum degree ordering algorithm by Iain Duff and John Reid. + * + * This routine is a translation of the original AMDBAR and MC47B routines, + * in Fortran, with the following modifications: + * + * (1) dense rows/columns are removed prior to ordering the matrix, and placed + * last in the output order. The presence of a dense row/column can + * increase the ordering time by up to O(n^2), unless they are removed + * prior to ordering. + * + * (2) the minimum degree ordering is followed by a postordering (depth-first + * search) of the assembly tree. Note that mass elimination (discussed + * below) combined with the approximate degree update can lead to the mass + * elimination of nodes with lower exact degree than the current pivot + * element. No additional fill-in is caused in the representation of the + * Schur complement. The mass-eliminated nodes merge with the current + * pivot element. They are ordered prior to the current pivot element. + * Because they can have lower exact degree than the current element, the + * merger of two or more of these nodes in the current pivot element can + * lead to a single element that is not a "fundamental supernode". The + * diagonal block can have zeros in it. Thus, the assembly tree used here + * is not guaranteed to be the precise supernodal elemination tree (with + * "funadmental" supernodes), and the postordering performed by this + * routine is not guaranteed to be a precise postordering of the + * elimination tree. + * + * (3) input parameters are added, to control aggressive absorption and the + * detection of "dense" rows/columns of A. + * + * (4) additional statistical information is returned, such as the number of + * nonzeros in L, and the flop counts for subsequent LDL' and LU + * factorizations. These are slight upper bounds, because of the mass + * elimination issue discussed above. + * + * (5) additional routines are added to interface this routine to MATLAB + * to provide a simple C-callable user-interface, to check inputs for + * errors, compute the symmetry of the pattern of A and the number of + * nonzeros in each row/column of A+A', to compute the pattern of A+A', + * to perform the assembly tree postordering, and to provide debugging + * ouput. Many of these functions are also provided by the Fortran + * Harwell Subroutine Library routine MC47A. + * + * (6) both int and UF_long versions are provided. In the descriptions below + * and integer is and int or UF_long depending on which version is + * being used. + + ********************************************************************** + ***** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ****** + ********************************************************************** + ** If you want error checking, a more versatile input format, and a ** + ** simpler user interface, use amd_order or amd_l_order instead. ** + ** This routine is not meant to be user-callable. ** + ********************************************************************** + + * ---------------------------------------------------------------------------- + * References: + * ---------------------------------------------------------------------------- + * + * [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern multifrontal + * method for sparse LU factorization", SIAM J. Matrix Analysis and + * Applications, vol. 18, no. 1, pp. 140-158. Discusses UMFPACK / MA38, + * which first introduced the approximate minimum degree used by this + * routine. + * + * [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, "An approximate + * minimum degree ordering algorithm," SIAM J. Matrix Analysis and + * Applications, vol. 17, no. 4, pp. 886-905, 1996. Discusses AMDBAR and + * MC47B, which are the Fortran versions of this routine. + * + * [3] Alan George and Joseph Liu, "The evolution of the minimum degree + * ordering algorithm," SIAM Review, vol. 31, no. 1, pp. 1-19, 1989. + * We list below the features mentioned in that paper that this code + * includes: + * + * mass elimination: + * Yes. MA27 relied on supervariable detection for mass elimination. + * + * indistinguishable nodes: + * Yes (we call these "supervariables"). This was also in the MA27 + * code - although we modified the method of detecting them (the + * previous hash was the true degree, which we no longer keep track + * of). A supervariable is a set of rows with identical nonzero + * pattern. All variables in a supervariable are eliminated together. + * Each supervariable has as its numerical name that of one of its + * variables (its principal variable). + * + * quotient graph representation: + * Yes. We use the term "element" for the cliques formed during + * elimination. This was also in the MA27 code. The algorithm can + * operate in place, but it will work more efficiently if given some + * "elbow room." + * + * element absorption: + * Yes. This was also in the MA27 code. + * + * external degree: + * Yes. The MA27 code was based on the true degree. + * + * incomplete degree update and multiple elimination: + * No. This was not in MA27, either. Our method of degree update + * within MC47B is element-based, not variable-based. It is thus + * not well-suited for use with incomplete degree update or multiple + * elimination. + * + * Authors, and Copyright (C) 2004 by: + * Timothy A. Davis, Patrick Amestoy, Iain S. Duff, John K. Reid. + * + * Acknowledgements: This work (and the UMFPACK package) was supported by the + * National Science Foundation (ASC-9111263, DMS-9223088, and CCR-0203270). + * The UMFPACK/MA38 approximate degree update algorithm, the unsymmetric analog + * which forms the basis of AMD, was developed while Tim Davis was supported by + * CERFACS (Toulouse, France) in a post-doctoral position. This C version, and + * the etree postorder, were written while Tim Davis was on sabbatical at + * Stanford University and Lawrence Berkeley National Laboratory. + + * ---------------------------------------------------------------------------- + * INPUT ARGUMENTS (unaltered): + * ---------------------------------------------------------------------------- + + * n: The matrix order. Restriction: n >= 1. + * + * iwlen: The size of the Iw array. On input, the matrix is stored in + * Iw [0..pfree-1]. However, Iw [0..iwlen-1] should be slightly larger + * than what is required to hold the matrix, at least iwlen >= pfree + n. + * Otherwise, excessive compressions will take place. The recommended + * value of iwlen is 1.2 * pfree + n, which is the value used in the + * user-callable interface to this routine (amd_order.c). The algorithm + * will not run at all if iwlen < pfree. Restriction: iwlen >= pfree + n. + * Note that this is slightly more restrictive than the actual minimum + * (iwlen >= pfree), but AMD_2 will be very slow with no elbow room. + * Thus, this routine enforces a bare minimum elbow room of size n. + * + * pfree: On input the tail end of the array, Iw [pfree..iwlen-1], is empty, + * and the matrix is stored in Iw [0..pfree-1]. During execution, + * additional data is placed in Iw, and pfree is modified so that + * Iw [pfree..iwlen-1] is always the unused part of Iw. + * + * Control: A double array of size AMD_CONTROL containing input parameters + * that affect how the ordering is computed. If NULL, then default + * settings are used. + * + * Control [AMD_DENSE] is used to determine whether or not a given input + * row is "dense". A row is "dense" if the number of entries in the row + * exceeds Control [AMD_DENSE] times sqrt (n), except that rows with 16 or + * fewer entries are never considered "dense". To turn off the detection + * of dense rows, set Control [AMD_DENSE] to a negative number, or to a + * number larger than sqrt (n). The default value of Control [AMD_DENSE] + * is AMD_DEFAULT_DENSE, which is defined in amd.h as 10. + * + * Control [AMD_AGGRESSIVE] is used to determine whether or not aggressive + * absorption is to be performed. If nonzero, then aggressive absorption + * is performed (this is the default). + + * ---------------------------------------------------------------------------- + * INPUT/OUPUT ARGUMENTS: + * ---------------------------------------------------------------------------- + * + * Pe: An integer array of size n. On input, Pe [i] is the index in Iw of + * the start of row i. Pe [i] is ignored if row i has no off-diagonal + * entries. Thus Pe [i] must be in the range 0 to pfree-1 for non-empty + * rows. + * + * During execution, it is used for both supervariables and elements: + * + * Principal supervariable i: index into Iw of the description of + * supervariable i. A supervariable represents one or more rows of + * the matrix with identical nonzero pattern. In this case, + * Pe [i] >= 0. + * + * Non-principal supervariable i: if i has been absorbed into another + * supervariable j, then Pe [i] = FLIP (j), where FLIP (j) is defined + * as (-(j)-2). Row j has the same pattern as row i. Note that j + * might later be absorbed into another supervariable j2, in which + * case Pe [i] is still FLIP (j), and Pe [j] = FLIP (j2) which is + * < EMPTY, where EMPTY is defined as (-1) in amd_internal.h. + * + * Unabsorbed element e: the index into Iw of the description of element + * e, if e has not yet been absorbed by a subsequent element. Element + * e is created when the supervariable of the same name is selected as + * the pivot. In this case, Pe [i] >= 0. + * + * Absorbed element e: if element e is absorbed into element e2, then + * Pe [e] = FLIP (e2). This occurs when the pattern of e (which we + * refer to as Le) is found to be a subset of the pattern of e2 (that + * is, Le2). In this case, Pe [i] < EMPTY. If element e is "null" + * (it has no nonzeros outside its pivot block), then Pe [e] = EMPTY, + * and e is the root of an assembly subtree (or the whole tree if + * there is just one such root). + * + * Dense variable i: if i is "dense", then Pe [i] = EMPTY. + * + * On output, Pe holds the assembly tree/forest, which implicitly + * represents a pivot order with identical fill-in as the actual order + * (via a depth-first search of the tree), as follows. If Nv [i] > 0, + * then i represents a node in the assembly tree, and the parent of i is + * Pe [i], or EMPTY if i is a root. If Nv [i] = 0, then (i, Pe [i]) + * represents an edge in a subtree, the root of which is a node in the + * assembly tree. Note that i refers to a row/column in the original + * matrix, not the permuted matrix. + * + * Info: A double array of size AMD_INFO. If present, (that is, not NULL), + * then statistics about the ordering are returned in the Info array. + * See amd.h for a description. + + * ---------------------------------------------------------------------------- + * INPUT/MODIFIED (undefined on output): + * ---------------------------------------------------------------------------- + * + * Len: An integer array of size n. On input, Len [i] holds the number of + * entries in row i of the matrix, excluding the diagonal. The contents + * of Len are undefined on output. + * + * Iw: An integer array of size iwlen. On input, Iw [0..pfree-1] holds the + * description of each row i in the matrix. The matrix must be symmetric, + * and both upper and lower triangular parts must be present. The + * diagonal must not be present. Row i is held as follows: + * + * Len [i]: the length of the row i data structure in the Iw array. + * Iw [Pe [i] ... Pe [i] + Len [i] - 1]: + * the list of column indices for nonzeros in row i (simple + * supervariables), excluding the diagonal. All supervariables + * start with one row/column each (supervariable i is just row i). + * If Len [i] is zero on input, then Pe [i] is ignored on input. + * + * Note that the rows need not be in any particular order, and there + * may be empty space between the rows. + * + * During execution, the supervariable i experiences fill-in. This is + * represented by placing in i a list of the elements that cause fill-in + * in supervariable i: + * + * Len [i]: the length of supervariable i in the Iw array. + * Iw [Pe [i] ... Pe [i] + Elen [i] - 1]: + * the list of elements that contain i. This list is kept short + * by removing absorbed elements. + * Iw [Pe [i] + Elen [i] ... Pe [i] + Len [i] - 1]: + * the list of supervariables in i. This list is kept short by + * removing nonprincipal variables, and any entry j that is also + * contained in at least one of the elements (j in Le) in the list + * for i (e in row i). + * + * When supervariable i is selected as pivot, we create an element e of + * the same name (e=i): + * + * Len [e]: the length of element e in the Iw array. + * Iw [Pe [e] ... Pe [e] + Len [e] - 1]: + * the list of supervariables in element e. + * + * An element represents the fill-in that occurs when supervariable i is + * selected as pivot (which represents the selection of row i and all + * non-principal variables whose principal variable is i). We use the + * term Le to denote the set of all supervariables in element e. Absorbed + * supervariables and elements are pruned from these lists when + * computationally convenient. + * + * CAUTION: THE INPUT MATRIX IS OVERWRITTEN DURING COMPUTATION. + * The contents of Iw are undefined on output. + + * ---------------------------------------------------------------------------- + * OUTPUT (need not be set on input): + * ---------------------------------------------------------------------------- + * + * Nv: An integer array of size n. During execution, ABS (Nv [i]) is equal to + * the number of rows that are represented by the principal supervariable + * i. If i is a nonprincipal or dense variable, then Nv [i] = 0. + * Initially, Nv [i] = 1 for all i. Nv [i] < 0 signifies that i is a + * principal variable in the pattern Lme of the current pivot element me. + * After element me is constructed, Nv [i] is set back to a positive + * value. + * + * On output, Nv [i] holds the number of pivots represented by super + * row/column i of the original matrix, or Nv [i] = 0 for non-principal + * rows/columns. Note that i refers to a row/column in the original + * matrix, not the permuted matrix. + * + * Elen: An integer array of size n. See the description of Iw above. At the + * start of execution, Elen [i] is set to zero for all rows i. During + * execution, Elen [i] is the number of elements in the list for + * supervariable i. When e becomes an element, Elen [e] = FLIP (esize) is + * set, where esize is the size of the element (the number of pivots, plus + * the number of nonpivotal entries). Thus Elen [e] < EMPTY. + * Elen (i) = EMPTY set when variable i becomes nonprincipal. + * + * For variables, Elen (i) >= EMPTY holds until just before the + * postordering and permutation vectors are computed. For elements, + * Elen [e] < EMPTY holds. + * + * On output, Elen [i] is the degree of the row/column in the Cholesky + * factorization of the permuted matrix, corresponding to the original row + * i, if i is a super row/column. It is equal to EMPTY if i is + * non-principal. Note that i refers to a row/column in the original + * matrix, not the permuted matrix. + * + * Note that the contents of Elen on output differ from the Fortran + * version (Elen holds the inverse permutation in the Fortran version, + * which is instead returned in the Next array in this C version, + * described below). + * + * Last: In a degree list, Last [i] is the supervariable preceding i, or EMPTY + * if i is the head of the list. In a hash bucket, Last [i] is the hash + * key for i. + * + * Last [Head [hash]] is also used as the head of a hash bucket if + * Head [hash] contains a degree list (see the description of Head, + * below). + * + * On output, Last [0..n-1] holds the permutation. That is, if + * i = Last [k], then row i is the kth pivot row (where k ranges from 0 to + * n-1). Row Last [k] of A is the kth row in the permuted matrix, PAP'. + * + * Next: Next [i] is the supervariable following i in a link list, or EMPTY if + * i is the last in the list. Used for two kinds of lists: degree lists + * and hash buckets (a supervariable can be in only one kind of list at a + * time). + * + * On output Next [0..n-1] holds the inverse permutation. That is, if + * k = Next [i], then row i is the kth pivot row. Row i of A appears as + * the (Next[i])-th row in the permuted matrix, PAP'. + * + * Note that the contents of Next on output differ from the Fortran + * version (Next is undefined on output in the Fortran version). + + * ---------------------------------------------------------------------------- + * LOCAL WORKSPACE (not input or output - used only during execution): + * ---------------------------------------------------------------------------- + * + * Degree: An integer array of size n. If i is a supervariable, then + * Degree [i] holds the current approximation of the external degree of + * row i (an upper bound). The external degree is the number of nonzeros + * in row i, minus ABS (Nv [i]), the diagonal part. The bound is equal to + * the exact external degree if Elen [i] is less than or equal to two. + * + * We also use the term "external degree" for elements e to refer to + * |Le \ Lme|. If e is an element, then Degree [e] is |Le|, which is the + * degree of the off-diagonal part of the element e (not including the + * diagonal part). + * + * Head: An integer array of size n. Head is used for degree lists. + * Head [deg] is the first supervariable in a degree list. All + * supervariables i in a degree list Head [deg] have the same approximate + * degree, namely, deg = Degree [i]. If the list Head [deg] is empty then + * Head [deg] = EMPTY. + * + * During supervariable detection Head [hash] also serves as a pointer to + * a hash bucket. If Head [hash] >= 0, there is a degree list of degree + * hash. The hash bucket head pointer is Last [Head [hash]]. If + * Head [hash] = EMPTY, then the degree list and hash bucket are both + * empty. If Head [hash] < EMPTY, then the degree list is empty, and + * FLIP (Head [hash]) is the head of the hash bucket. After supervariable + * detection is complete, all hash buckets are empty, and the + * (Last [Head [hash]] = EMPTY) condition is restored for the non-empty + * degree lists. + * + * W: An integer array of size n. The flag array W determines the status of + * elements and variables, and the external degree of elements. + * + * for elements: + * if W [e] = 0, then the element e is absorbed. + * if W [e] >= wflg, then W [e] - wflg is the size of the set + * |Le \ Lme|, in terms of nonzeros (the sum of ABS (Nv [i]) for + * each principal variable i that is both in the pattern of + * element e and NOT in the pattern of the current pivot element, + * me). + * if wflg > W [e] > 0, then e is not absorbed and has not yet been + * seen in the scan of the element lists in the computation of + * |Le\Lme| in Scan 1 below. + * + * for variables: + * during supervariable detection, if W [j] != wflg then j is + * not in the pattern of variable i. + * + * The W array is initialized by setting W [i] = 1 for all i, and by + * setting wflg = 2. It is reinitialized if wflg becomes too large (to + * ensure that wflg+n does not cause integer overflow). + + * ---------------------------------------------------------------------------- + * LOCAL INTEGERS: + * ---------------------------------------------------------------------------- + */ + + Int deg, degme, dext, lemax, e, elenme, eln, i, ilast, inext, j, + jlast, jnext, k, knt1, knt2, knt3, lenj, ln, me, mindeg, nel, nleft, + nvi, nvj, nvpiv, slenme, wbig, we, wflg, wnvi, ok, ndense, ncmpa, + dense, aggressive ; + + unsigned Int hash ; /* unsigned, so that hash % n is well defined.*/ + +/* + * deg: the degree of a variable or element + * degme: size, |Lme|, of the current element, me (= Degree [me]) + * dext: external degree, |Le \ Lme|, of some element e + * lemax: largest |Le| seen so far (called dmax in Fortran version) + * e: an element + * elenme: the length, Elen [me], of element list of pivotal variable + * eln: the length, Elen [...], of an element list + * hash: the computed value of the hash function + * i: a supervariable + * ilast: the entry in a link list preceding i + * inext: the entry in a link list following i + * j: a supervariable + * jlast: the entry in a link list preceding j + * jnext: the entry in a link list, or path, following j + * k: the pivot order of an element or variable + * knt1: loop counter used during element construction + * knt2: loop counter used during element construction + * knt3: loop counter used during compression + * lenj: Len [j] + * ln: length of a supervariable list + * me: current supervariable being eliminated, and the current + * element created by eliminating that supervariable + * mindeg: current minimum degree + * nel: number of pivots selected so far + * nleft: n - nel, the number of nonpivotal rows/columns remaining + * nvi: the number of variables in a supervariable i (= Nv [i]) + * nvj: the number of variables in a supervariable j (= Nv [j]) + * nvpiv: number of pivots in current element + * slenme: number of variables in variable list of pivotal variable + * wbig: = INT_MAX - n for the int version, UF_long_max - n for the + * UF_long version. wflg is not allowed to be >= wbig. + * we: W [e] + * wflg: used for flagging the W array. See description of Iw. + * wnvi: wflg - Nv [i] + * x: either a supervariable or an element + * + * ok: true if supervariable j can be absorbed into i + * ndense: number of "dense" rows/columns + * dense: rows/columns with initial degree > dense are considered "dense" + * aggressive: true if aggressive absorption is being performed + * ncmpa: number of garbage collections + + * ---------------------------------------------------------------------------- + * LOCAL DOUBLES, used for statistical output only (except for alpha): + * ---------------------------------------------------------------------------- + */ + + double f, r, ndiv, s, nms_lu, nms_ldl, dmax, alpha, lnz, lnzme ; + +/* + * f: nvpiv + * r: degme + nvpiv + * ndiv: number of divisions for LU or LDL' factorizations + * s: number of multiply-subtract pairs for LU factorization, for the + * current element me + * nms_lu number of multiply-subtract pairs for LU factorization + * nms_ldl number of multiply-subtract pairs for LDL' factorization + * dmax: the largest number of entries in any column of L, including the + * diagonal + * alpha: "dense" degree ratio + * lnz: the number of nonzeros in L (excluding the diagonal) + * lnzme: the number of nonzeros in L (excl. the diagonal) for the + * current element me + + * ---------------------------------------------------------------------------- + * LOCAL "POINTERS" (indices into the Iw array) + * ---------------------------------------------------------------------------- +*/ + + Int p, p1, p2, p3, p4, pdst, pend, pj, pme, pme1, pme2, pn, psrc ; + +/* + * Any parameter (Pe [...] or pfree) or local variable starting with "p" (for + * Pointer) is an index into Iw, and all indices into Iw use variables starting + * with "p." The only exception to this rule is the iwlen input argument. + * + * p: pointer into lots of things + * p1: Pe [i] for some variable i (start of element list) + * p2: Pe [i] + Elen [i] - 1 for some variable i + * p3: index of first supervariable in clean list + * p4: + * pdst: destination pointer, for compression + * pend: end of memory to compress + * pj: pointer into an element or variable + * pme: pointer into the current element (pme1...pme2) + * pme1: the current element, me, is stored in Iw [pme1...pme2] + * pme2: the end of the current element + * pn: pointer into a "clean" variable, also used to compress + * psrc: source pointer, for compression +*/ + +/* ========================================================================= */ +/* INITIALIZATIONS */ +/* ========================================================================= */ + + /* Note that this restriction on iwlen is slightly more restrictive than + * what is actually required in AMD_2. AMD_2 can operate with no elbow + * room at all, but it will be slow. For better performance, at least + * size-n elbow room is enforced. */ + ASSERT (iwlen >= pfree + n) ; + ASSERT (n > 0) ; + + /* initialize output statistics */ + lnz = 0 ; + ndiv = 0 ; + nms_lu = 0 ; + nms_ldl = 0 ; + dmax = 1 ; + me = EMPTY ; + + mindeg = 0 ; + ncmpa = 0 ; + nel = 0 ; + lemax = 0 ; + + /* get control parameters */ + if (Control != (double *) NULL) + { + alpha = Control [AMD_DENSE] ; + aggressive = (Control [AMD_AGGRESSIVE] != 0) ; + } + else + { + alpha = AMD_DEFAULT_DENSE ; + aggressive = AMD_DEFAULT_AGGRESSIVE ; + } + /* Note: if alpha is NaN, this is undefined: */ + if (alpha < 0) + { + /* only remove completely dense rows/columns */ + dense = n-2 ; + } + else + { + dense = alpha * sqrt ((double) n) ; + } + dense = MAX (16, dense) ; + dense = MIN (n, dense) ; + AMD_DEBUG1 (("\n\nAMD (debug), alpha %g, aggr. "ID"\n", + alpha, aggressive)) ; + + for (i = 0 ; i < n ; i++) + { + Last [i] = EMPTY ; + Head [i] = EMPTY ; + Next [i] = EMPTY ; + /* if separate Hhead array is used for hash buckets: * + Hhead [i] = EMPTY ; + */ + Nv [i] = 1 ; + W [i] = 1 ; + Elen [i] = 0 ; + Degree [i] = Len [i] ; + } + +#ifndef NDEBUG + AMD_DEBUG1 (("\n======Nel "ID" initial\n", nel)) ; + AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, Last, + Head, Elen, Degree, W, -1) ; +#endif + + /* initialize wflg */ + wbig = Int_MAX - n ; + wflg = clear_flag (0, wbig, W, n) ; + + /* --------------------------------------------------------------------- */ + /* initialize degree lists and eliminate dense and empty rows */ + /* --------------------------------------------------------------------- */ + + ndense = 0 ; + + for (i = 0 ; i < n ; i++) + { + deg = Degree [i] ; + ASSERT (deg >= 0 && deg < n) ; + if (deg == 0) + { + + /* ------------------------------------------------------------- + * we have a variable that can be eliminated at once because + * there is no off-diagonal non-zero in its row. Note that + * Nv [i] = 1 for an empty variable i. It is treated just + * the same as an eliminated element i. + * ------------------------------------------------------------- */ + + Elen [i] = FLIP (1) ; + nel++ ; + Pe [i] = EMPTY ; + W [i] = 0 ; + + } + else if (deg > dense) + { + + /* ------------------------------------------------------------- + * Dense variables are not treated as elements, but as unordered, + * non-principal variables that have no parent. They do not take + * part in the postorder, since Nv [i] = 0. Note that the Fortran + * version does not have this option. + * ------------------------------------------------------------- */ + + AMD_DEBUG1 (("Dense node "ID" degree "ID"\n", i, deg)) ; + ndense++ ; + Nv [i] = 0 ; /* do not postorder this node */ + Elen [i] = EMPTY ; + nel++ ; + Pe [i] = EMPTY ; + + } + else + { + + /* ------------------------------------------------------------- + * place i in the degree list corresponding to its degree + * ------------------------------------------------------------- */ + + inext = Head [deg] ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = i ; + Next [i] = inext ; + Head [deg] = i ; + + } + } + +/* ========================================================================= */ +/* WHILE (selecting pivots) DO */ +/* ========================================================================= */ + + while (nel < n) + { + +#ifndef NDEBUG + AMD_DEBUG1 (("\n======Nel "ID"\n", nel)) ; + if (AMD_debug >= 2) + { + AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, + Last, Head, Elen, Degree, W, nel) ; + } +#endif + +/* ========================================================================= */ +/* GET PIVOT OF MINIMUM DEGREE */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- */ + /* find next supervariable for elimination */ + /* ----------------------------------------------------------------- */ + + ASSERT (mindeg >= 0 && mindeg < n) ; + for (deg = mindeg ; deg < n ; deg++) + { + me = Head [deg] ; + if (me != EMPTY) break ; + } + mindeg = deg ; + ASSERT (me >= 0 && me < n) ; + AMD_DEBUG1 (("=================me: "ID"\n", me)) ; + + /* ----------------------------------------------------------------- */ + /* remove chosen variable from link list */ + /* ----------------------------------------------------------------- */ + + inext = Next [me] ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = EMPTY ; + Head [deg] = inext ; + + /* ----------------------------------------------------------------- */ + /* me represents the elimination of pivots nel to nel+Nv[me]-1. */ + /* place me itself as the first in this set. */ + /* ----------------------------------------------------------------- */ + + elenme = Elen [me] ; + nvpiv = Nv [me] ; + ASSERT (nvpiv > 0) ; + nel += nvpiv ; + +/* ========================================================================= */ +/* CONSTRUCT NEW ELEMENT */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- + * At this point, me is the pivotal supervariable. It will be + * converted into the current element. Scan list of the pivotal + * supervariable, me, setting tree pointers and constructing new list + * of supervariables for the new element, me. p is a pointer to the + * current position in the old list. + * ----------------------------------------------------------------- */ + + /* flag the variable "me" as being in Lme by negating Nv [me] */ + Nv [me] = -nvpiv ; + degme = 0 ; + ASSERT (Pe [me] >= 0 && Pe [me] < iwlen) ; + + if (elenme == 0) + { + + /* ------------------------------------------------------------- */ + /* construct the new element in place */ + /* ------------------------------------------------------------- */ + + pme1 = Pe [me] ; + pme2 = pme1 - 1 ; + + for (p = pme1 ; p <= pme1 + Len [me] - 1 ; p++) + { + i = Iw [p] ; + ASSERT (i >= 0 && i < n && Nv [i] >= 0) ; + nvi = Nv [i] ; + if (nvi > 0) + { + + /* ----------------------------------------------------- */ + /* i is a principal variable not yet placed in Lme. */ + /* store i in new list */ + /* ----------------------------------------------------- */ + + /* flag i as being in Lme by negating Nv [i] */ + degme += nvi ; + Nv [i] = -nvi ; + Iw [++pme2] = i ; + + /* ----------------------------------------------------- */ + /* remove variable i from degree list. */ + /* ----------------------------------------------------- */ + + ilast = Last [i] ; + inext = Next [i] ; + ASSERT (ilast >= EMPTY && ilast < n) ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = ilast ; + if (ilast != EMPTY) + { + Next [ilast] = inext ; + } + else + { + /* i is at the head of the degree list */ + ASSERT (Degree [i] >= 0 && Degree [i] < n) ; + Head [Degree [i]] = inext ; + } + } + } + } + else + { + + /* ------------------------------------------------------------- */ + /* construct the new element in empty space, Iw [pfree ...] */ + /* ------------------------------------------------------------- */ + + p = Pe [me] ; + pme1 = pfree ; + slenme = Len [me] - elenme ; + + for (knt1 = 1 ; knt1 <= elenme + 1 ; knt1++) + { + + if (knt1 > elenme) + { + /* search the supervariables in me. */ + e = me ; + pj = p ; + ln = slenme ; + AMD_DEBUG2 (("Search sv: "ID" "ID" "ID"\n", me,pj,ln)) ; + } + else + { + /* search the elements in me. */ + e = Iw [p++] ; + ASSERT (e >= 0 && e < n) ; + pj = Pe [e] ; + ln = Len [e] ; + AMD_DEBUG2 (("Search element e "ID" in me "ID"\n", e,me)) ; + ASSERT (Elen [e] < EMPTY && W [e] > 0 && pj >= 0) ; + } + ASSERT (ln >= 0 && (ln == 0 || (pj >= 0 && pj < iwlen))) ; + + /* --------------------------------------------------------- + * search for different supervariables and add them to the + * new list, compressing when necessary. this loop is + * executed once for each element in the list and once for + * all the supervariables in the list. + * --------------------------------------------------------- */ + + for (knt2 = 1 ; knt2 <= ln ; knt2++) + { + i = Iw [pj++] ; + ASSERT (i >= 0 && i < n && (i == me || Elen [i] >= EMPTY)); + nvi = Nv [i] ; + AMD_DEBUG2 ((": "ID" "ID" "ID" "ID"\n", + i, Elen [i], Nv [i], wflg)) ; + + if (nvi > 0) + { + + /* ------------------------------------------------- */ + /* compress Iw, if necessary */ + /* ------------------------------------------------- */ + + if (pfree >= iwlen) + { + + AMD_DEBUG1 (("GARBAGE COLLECTION\n")) ; + + /* prepare for compressing Iw by adjusting pointers + * and lengths so that the lists being searched in + * the inner and outer loops contain only the + * remaining entries. */ + + Pe [me] = p ; + Len [me] -= knt1 ; + /* check if nothing left of supervariable me */ + if (Len [me] == 0) Pe [me] = EMPTY ; + Pe [e] = pj ; + Len [e] = ln - knt2 ; + /* nothing left of element e */ + if (Len [e] == 0) Pe [e] = EMPTY ; + + ncmpa++ ; /* one more garbage collection */ + + /* store first entry of each object in Pe */ + /* FLIP the first entry in each object */ + for (j = 0 ; j < n ; j++) + { + pn = Pe [j] ; + if (pn >= 0) + { + ASSERT (pn >= 0 && pn < iwlen) ; + Pe [j] = Iw [pn] ; + Iw [pn] = FLIP (j) ; + } + } + + /* psrc/pdst point to source/destination */ + psrc = 0 ; + pdst = 0 ; + pend = pme1 - 1 ; + + while (psrc <= pend) + { + /* search for next FLIP'd entry */ + j = FLIP (Iw [psrc++]) ; + if (j >= 0) + { + AMD_DEBUG2 (("Got object j: "ID"\n", j)) ; + Iw [pdst] = Pe [j] ; + Pe [j] = pdst++ ; + lenj = Len [j] ; + /* copy from source to destination */ + for (knt3 = 0 ; knt3 <= lenj - 2 ; knt3++) + { + Iw [pdst++] = Iw [psrc++] ; + } + } + } + + /* move the new partially-constructed element */ + p1 = pdst ; + for (psrc = pme1 ; psrc <= pfree-1 ; psrc++) + { + Iw [pdst++] = Iw [psrc] ; + } + pme1 = p1 ; + pfree = pdst ; + pj = Pe [e] ; + p = Pe [me] ; + + } + + /* ------------------------------------------------- */ + /* i is a principal variable not yet placed in Lme */ + /* store i in new list */ + /* ------------------------------------------------- */ + + /* flag i as being in Lme by negating Nv [i] */ + degme += nvi ; + Nv [i] = -nvi ; + Iw [pfree++] = i ; + AMD_DEBUG2 ((" s: "ID" nv "ID"\n", i, Nv [i])); + + /* ------------------------------------------------- */ + /* remove variable i from degree link list */ + /* ------------------------------------------------- */ + + ilast = Last [i] ; + inext = Next [i] ; + ASSERT (ilast >= EMPTY && ilast < n) ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = ilast ; + if (ilast != EMPTY) + { + Next [ilast] = inext ; + } + else + { + /* i is at the head of the degree list */ + ASSERT (Degree [i] >= 0 && Degree [i] < n) ; + Head [Degree [i]] = inext ; + } + } + } + + if (e != me) + { + /* set tree pointer and flag to indicate element e is + * absorbed into new element me (the parent of e is me) */ + AMD_DEBUG1 ((" Element "ID" => "ID"\n", e, me)) ; + Pe [e] = FLIP (me) ; + W [e] = 0 ; + } + } + + pme2 = pfree - 1 ; + } + + /* ----------------------------------------------------------------- */ + /* me has now been converted into an element in Iw [pme1..pme2] */ + /* ----------------------------------------------------------------- */ + + /* degme holds the external degree of new element */ + Degree [me] = degme ; + Pe [me] = pme1 ; + Len [me] = pme2 - pme1 + 1 ; + ASSERT (Pe [me] >= 0 && Pe [me] < iwlen) ; + + Elen [me] = FLIP (nvpiv + degme) ; + /* FLIP (Elen (me)) is now the degree of pivot (including + * diagonal part). */ + +#ifndef NDEBUG + AMD_DEBUG2 (("New element structure: length= "ID"\n", pme2-pme1+1)) ; + for (pme = pme1 ; pme <= pme2 ; pme++) AMD_DEBUG3 ((" "ID"", Iw[pme])); + AMD_DEBUG3 (("\n")) ; +#endif + + /* ----------------------------------------------------------------- */ + /* make sure that wflg is not too large. */ + /* ----------------------------------------------------------------- */ + + /* With the current value of wflg, wflg+n must not cause integer + * overflow */ + + wflg = clear_flag (wflg, wbig, W, n) ; + +/* ========================================================================= */ +/* COMPUTE (W [e] - wflg) = |Le\Lme| FOR ALL ELEMENTS */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- + * Scan 1: compute the external degrees of previous elements with + * respect to the current element. That is: + * (W [e] - wflg) = |Le \ Lme| + * for each element e that appears in any supervariable in Lme. The + * notation Le refers to the pattern (list of supervariables) of a + * previous element e, where e is not yet absorbed, stored in + * Iw [Pe [e] + 1 ... Pe [e] + Len [e]]. The notation Lme + * refers to the pattern of the current element (stored in + * Iw [pme1..pme2]). If aggressive absorption is enabled, and + * (W [e] - wflg) becomes zero, then the element e will be absorbed + * in Scan 2. + * ----------------------------------------------------------------- */ + + AMD_DEBUG2 (("me: ")) ; + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n) ; + eln = Elen [i] ; + AMD_DEBUG3 ((""ID" Elen "ID": \n", i, eln)) ; + if (eln > 0) + { + /* note that Nv [i] has been negated to denote i in Lme: */ + nvi = -Nv [i] ; + ASSERT (nvi > 0 && Pe [i] >= 0 && Pe [i] < iwlen) ; + wnvi = wflg - nvi ; + for (p = Pe [i] ; p <= Pe [i] + eln - 1 ; p++) + { + e = Iw [p] ; + ASSERT (e >= 0 && e < n) ; + we = W [e] ; + AMD_DEBUG4 ((" e "ID" we "ID" ", e, we)) ; + if (we >= wflg) + { + /* unabsorbed element e has been seen in this loop */ + AMD_DEBUG4 ((" unabsorbed, first time seen")) ; + we -= nvi ; + } + else if (we != 0) + { + /* e is an unabsorbed element */ + /* this is the first we have seen e in all of Scan 1 */ + AMD_DEBUG4 ((" unabsorbed")) ; + we = Degree [e] + wnvi ; + } + AMD_DEBUG4 (("\n")) ; + W [e] = we ; + } + } + } + AMD_DEBUG2 (("\n")) ; + +/* ========================================================================= */ +/* DEGREE UPDATE AND ELEMENT ABSORPTION */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- + * Scan 2: for each i in Lme, sum up the degree of Lme (which is + * degme), plus the sum of the external degrees of each Le for the + * elements e appearing within i, plus the supervariables in i. + * Place i in hash list. + * ----------------------------------------------------------------- */ + + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n && Nv [i] < 0 && Elen [i] >= 0) ; + AMD_DEBUG2 (("Updating: i "ID" "ID" "ID"\n", i, Elen[i], Len [i])); + p1 = Pe [i] ; + p2 = p1 + Elen [i] - 1 ; + pn = p1 ; + hash = 0 ; + deg = 0 ; + ASSERT (p1 >= 0 && p1 < iwlen && p2 >= -1 && p2 < iwlen) ; + + /* ------------------------------------------------------------- */ + /* scan the element list associated with supervariable i */ + /* ------------------------------------------------------------- */ + + /* UMFPACK/MA38-style approximate degree: */ + if (aggressive) + { + for (p = p1 ; p <= p2 ; p++) + { + e = Iw [p] ; + ASSERT (e >= 0 && e < n) ; + we = W [e] ; + if (we != 0) + { + /* e is an unabsorbed element */ + /* dext = | Le \ Lme | */ + dext = we - wflg ; + if (dext > 0) + { + deg += dext ; + Iw [pn++] = e ; + hash += e ; + AMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; + } + else + { + /* external degree of e is zero, absorb e into me*/ + AMD_DEBUG1 ((" Element "ID" =>"ID" (aggressive)\n", + e, me)) ; + ASSERT (dext == 0) ; + Pe [e] = FLIP (me) ; + W [e] = 0 ; + } + } + } + } + else + { + for (p = p1 ; p <= p2 ; p++) + { + e = Iw [p] ; + ASSERT (e >= 0 && e < n) ; + we = W [e] ; + if (we != 0) + { + /* e is an unabsorbed element */ + dext = we - wflg ; + ASSERT (dext >= 0) ; + deg += dext ; + Iw [pn++] = e ; + hash += e ; + AMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; + } + } + } + + /* count the number of elements in i (including me): */ + Elen [i] = pn - p1 + 1 ; + + /* ------------------------------------------------------------- */ + /* scan the supervariables in the list associated with i */ + /* ------------------------------------------------------------- */ + + /* The bulk of the AMD run time is typically spent in this loop, + * particularly if the matrix has many dense rows that are not + * removed prior to ordering. */ + p3 = pn ; + p4 = p1 + Len [i] ; + for (p = p2 + 1 ; p < p4 ; p++) + { + j = Iw [p] ; + ASSERT (j >= 0 && j < n) ; + nvj = Nv [j] ; + if (nvj > 0) + { + /* j is unabsorbed, and not in Lme. */ + /* add to degree and add to new list */ + deg += nvj ; + Iw [pn++] = j ; + hash += j ; + AMD_DEBUG4 ((" s: "ID" hash "ID" Nv[j]= "ID"\n", + j, hash, nvj)) ; + } + } + + /* ------------------------------------------------------------- */ + /* update the degree and check for mass elimination */ + /* ------------------------------------------------------------- */ + + /* with aggressive absorption, deg==0 is identical to the + * Elen [i] == 1 && p3 == pn test, below. */ + ASSERT (IMPLIES (aggressive, (deg==0) == (Elen[i]==1 && p3==pn))) ; + + if (Elen [i] == 1 && p3 == pn) + { + + /* --------------------------------------------------------- */ + /* mass elimination */ + /* --------------------------------------------------------- */ + + /* There is nothing left of this node except for an edge to + * the current pivot element. Elen [i] is 1, and there are + * no variables adjacent to node i. Absorb i into the + * current pivot element, me. Note that if there are two or + * more mass eliminations, fillin due to mass elimination is + * possible within the nvpiv-by-nvpiv pivot block. It is this + * step that causes AMD's analysis to be an upper bound. + * + * The reason is that the selected pivot has a lower + * approximate degree than the true degree of the two mass + * eliminated nodes. There is no edge between the two mass + * eliminated nodes. They are merged with the current pivot + * anyway. + * + * No fillin occurs in the Schur complement, in any case, + * and this effect does not decrease the quality of the + * ordering itself, just the quality of the nonzero and + * flop count analysis. It also means that the post-ordering + * is not an exact elimination tree post-ordering. */ + + AMD_DEBUG1 ((" MASS i "ID" => parent e "ID"\n", i, me)) ; + Pe [i] = FLIP (me) ; + nvi = -Nv [i] ; + degme -= nvi ; + nvpiv += nvi ; + nel += nvi ; + Nv [i] = 0 ; + Elen [i] = EMPTY ; + + } + else + { + + /* --------------------------------------------------------- */ + /* update the upper-bound degree of i */ + /* --------------------------------------------------------- */ + + /* the following degree does not yet include the size + * of the current element, which is added later: */ + + Degree [i] = MIN (Degree [i], deg) ; + + /* --------------------------------------------------------- */ + /* add me to the list for i */ + /* --------------------------------------------------------- */ + + /* move first supervariable to end of list */ + Iw [pn] = Iw [p3] ; + /* move first element to end of element part of list */ + Iw [p3] = Iw [p1] ; + /* add new element, me, to front of list. */ + Iw [p1] = me ; + /* store the new length of the list in Len [i] */ + Len [i] = pn - p1 + 1 ; + + /* --------------------------------------------------------- */ + /* place in hash bucket. Save hash key of i in Last [i]. */ + /* --------------------------------------------------------- */ + + /* NOTE: this can fail if hash is negative, because the ANSI C + * standard does not define a % b when a and/or b are negative. + * That's why hash is defined as an unsigned Int, to avoid this + * problem. */ + hash = hash % n ; + ASSERT (((Int) hash) >= 0 && ((Int) hash) < n) ; + + /* if the Hhead array is not used: */ + j = Head [hash] ; + if (j <= EMPTY) + { + /* degree list is empty, hash head is FLIP (j) */ + Next [i] = FLIP (j) ; + Head [hash] = FLIP (i) ; + } + else + { + /* degree list is not empty, use Last [Head [hash]] as + * hash head. */ + Next [i] = Last [j] ; + Last [j] = i ; + } + + /* if a separate Hhead array is used: * + Next [i] = Hhead [hash] ; + Hhead [hash] = i ; + */ + + Last [i] = hash ; + } + } + + Degree [me] = degme ; + + /* ----------------------------------------------------------------- */ + /* Clear the counter array, W [...], by incrementing wflg. */ + /* ----------------------------------------------------------------- */ + + /* make sure that wflg+n does not cause integer overflow */ + lemax = MAX (lemax, degme) ; + wflg += lemax ; + wflg = clear_flag (wflg, wbig, W, n) ; + /* at this point, W [0..n-1] < wflg holds */ + +/* ========================================================================= */ +/* SUPERVARIABLE DETECTION */ +/* ========================================================================= */ + + AMD_DEBUG1 (("Detecting supervariables:\n")) ; + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n) ; + AMD_DEBUG2 (("Consider i "ID" nv "ID"\n", i, Nv [i])) ; + if (Nv [i] < 0) + { + /* i is a principal variable in Lme */ + + /* --------------------------------------------------------- + * examine all hash buckets with 2 or more variables. We do + * this by examing all unique hash keys for supervariables in + * the pattern Lme of the current element, me + * --------------------------------------------------------- */ + + /* let i = head of hash bucket, and empty the hash bucket */ + ASSERT (Last [i] >= 0 && Last [i] < n) ; + hash = Last [i] ; + + /* if Hhead array is not used: */ + j = Head [hash] ; + if (j == EMPTY) + { + /* hash bucket and degree list are both empty */ + i = EMPTY ; + } + else if (j < EMPTY) + { + /* degree list is empty */ + i = FLIP (j) ; + Head [hash] = EMPTY ; + } + else + { + /* degree list is not empty, restore Last [j] of head j */ + i = Last [j] ; + Last [j] = EMPTY ; + } + + /* if separate Hhead array is used: * + i = Hhead [hash] ; + Hhead [hash] = EMPTY ; + */ + + ASSERT (i >= EMPTY && i < n) ; + AMD_DEBUG2 (("----i "ID" hash "ID"\n", i, hash)) ; + + while (i != EMPTY && Next [i] != EMPTY) + { + + /* ----------------------------------------------------- + * this bucket has one or more variables following i. + * scan all of them to see if i can absorb any entries + * that follow i in hash bucket. Scatter i into w. + * ----------------------------------------------------- */ + + ln = Len [i] ; + eln = Elen [i] ; + ASSERT (ln >= 0 && eln >= 0) ; + ASSERT (Pe [i] >= 0 && Pe [i] < iwlen) ; + /* do not flag the first element in the list (me) */ + for (p = Pe [i] + 1 ; p <= Pe [i] + ln - 1 ; p++) + { + ASSERT (Iw [p] >= 0 && Iw [p] < n) ; + W [Iw [p]] = wflg ; + } + + /* ----------------------------------------------------- */ + /* scan every other entry j following i in bucket */ + /* ----------------------------------------------------- */ + + jlast = i ; + j = Next [i] ; + ASSERT (j >= EMPTY && j < n) ; + + while (j != EMPTY) + { + /* ------------------------------------------------- */ + /* check if j and i have identical nonzero pattern */ + /* ------------------------------------------------- */ + + AMD_DEBUG3 (("compare i "ID" and j "ID"\n", i,j)) ; + + /* check if i and j have the same Len and Elen */ + ASSERT (Len [j] >= 0 && Elen [j] >= 0) ; + ASSERT (Pe [j] >= 0 && Pe [j] < iwlen) ; + ok = (Len [j] == ln) && (Elen [j] == eln) ; + /* skip the first element in the list (me) */ + for (p = Pe [j] + 1 ; ok && p <= Pe [j] + ln - 1 ; p++) + { + ASSERT (Iw [p] >= 0 && Iw [p] < n) ; + if (W [Iw [p]] != wflg) ok = 0 ; + } + if (ok) + { + /* --------------------------------------------- */ + /* found it! j can be absorbed into i */ + /* --------------------------------------------- */ + + AMD_DEBUG1 (("found it! j "ID" => i "ID"\n", j,i)); + Pe [j] = FLIP (i) ; + /* both Nv [i] and Nv [j] are negated since they */ + /* are in Lme, and the absolute values of each */ + /* are the number of variables in i and j: */ + Nv [i] += Nv [j] ; + Nv [j] = 0 ; + Elen [j] = EMPTY ; + /* delete j from hash bucket */ + ASSERT (j != Next [j]) ; + j = Next [j] ; + Next [jlast] = j ; + + } + else + { + /* j cannot be absorbed into i */ + jlast = j ; + ASSERT (j != Next [j]) ; + j = Next [j] ; + } + ASSERT (j >= EMPTY && j < n) ; + } + + /* ----------------------------------------------------- + * no more variables can be absorbed into i + * go to next i in bucket and clear flag array + * ----------------------------------------------------- */ + + wflg++ ; + i = Next [i] ; + ASSERT (i >= EMPTY && i < n) ; + + } + } + } + AMD_DEBUG2 (("detect done\n")) ; + +/* ========================================================================= */ +/* RESTORE DEGREE LISTS AND REMOVE NONPRINCIPAL SUPERVARIABLES FROM ELEMENT */ +/* ========================================================================= */ + + p = pme1 ; + nleft = n - nel ; + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n) ; + nvi = -Nv [i] ; + AMD_DEBUG3 (("Restore i "ID" "ID"\n", i, nvi)) ; + if (nvi > 0) + { + /* i is a principal variable in Lme */ + /* restore Nv [i] to signify that i is principal */ + Nv [i] = nvi ; + + /* --------------------------------------------------------- */ + /* compute the external degree (add size of current element) */ + /* --------------------------------------------------------- */ + + deg = Degree [i] + degme - nvi ; + deg = MIN (deg, nleft - nvi) ; + ASSERT (IMPLIES (aggressive, deg > 0) && deg >= 0 && deg < n) ; + + /* --------------------------------------------------------- */ + /* place the supervariable at the head of the degree list */ + /* --------------------------------------------------------- */ + + inext = Head [deg] ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = i ; + Next [i] = inext ; + Last [i] = EMPTY ; + Head [deg] = i ; + + /* --------------------------------------------------------- */ + /* save the new degree, and find the minimum degree */ + /* --------------------------------------------------------- */ + + mindeg = MIN (mindeg, deg) ; + Degree [i] = deg ; + + /* --------------------------------------------------------- */ + /* place the supervariable in the element pattern */ + /* --------------------------------------------------------- */ + + Iw [p++] = i ; + + } + } + AMD_DEBUG2 (("restore done\n")) ; + +/* ========================================================================= */ +/* FINALIZE THE NEW ELEMENT */ +/* ========================================================================= */ + + AMD_DEBUG2 (("ME = "ID" DONE\n", me)) ; + Nv [me] = nvpiv ; + /* save the length of the list for the new element me */ + Len [me] = p - pme1 ; + if (Len [me] == 0) + { + /* there is nothing left of the current pivot element */ + /* it is a root of the assembly tree */ + Pe [me] = EMPTY ; + W [me] = 0 ; + } + if (elenme != 0) + { + /* element was not constructed in place: deallocate part of */ + /* it since newly nonprincipal variables may have been removed */ + pfree = p ; + } + + /* The new element has nvpiv pivots and the size of the contribution + * block for a multifrontal method is degme-by-degme, not including + * the "dense" rows/columns. If the "dense" rows/columns are included, + * the frontal matrix is no larger than + * (degme+ndense)-by-(degme+ndense). + */ + + if (Info != (double *) NULL) + { + f = nvpiv ; + r = degme + ndense ; + dmax = MAX (dmax, f + r) ; + + /* number of nonzeros in L (excluding the diagonal) */ + lnzme = f*r + (f-1)*f/2 ; + lnz += lnzme ; + + /* number of divide operations for LDL' and for LU */ + ndiv += lnzme ; + + /* number of multiply-subtract pairs for LU */ + s = f*r*r + r*(f-1)*f + (f-1)*f*(2*f-1)/6 ; + nms_lu += s ; + + /* number of multiply-subtract pairs for LDL' */ + nms_ldl += (s + lnzme)/2 ; + } + +#ifndef NDEBUG + AMD_DEBUG2 (("finalize done nel "ID" n "ID"\n ::::\n", nel, n)) ; + for (pme = Pe [me] ; pme <= Pe [me] + Len [me] - 1 ; pme++) + { + AMD_DEBUG3 ((" "ID"", Iw [pme])) ; + } + AMD_DEBUG3 (("\n")) ; +#endif + + } + +/* ========================================================================= */ +/* DONE SELECTING PIVOTS */ +/* ========================================================================= */ + + if (Info != (double *) NULL) + { + + /* count the work to factorize the ndense-by-ndense submatrix */ + f = ndense ; + dmax = MAX (dmax, (double) ndense) ; + + /* number of nonzeros in L (excluding the diagonal) */ + lnzme = (f-1)*f/2 ; + lnz += lnzme ; + + /* number of divide operations for LDL' and for LU */ + ndiv += lnzme ; + + /* number of multiply-subtract pairs for LU */ + s = (f-1)*f*(2*f-1)/6 ; + nms_lu += s ; + + /* number of multiply-subtract pairs for LDL' */ + nms_ldl += (s + lnzme)/2 ; + + /* number of nz's in L (excl. diagonal) */ + Info [AMD_LNZ] = lnz ; + + /* number of divide ops for LU and LDL' */ + Info [AMD_NDIV] = ndiv ; + + /* number of multiply-subtract pairs for LDL' */ + Info [AMD_NMULTSUBS_LDL] = nms_ldl ; + + /* number of multiply-subtract pairs for LU */ + Info [AMD_NMULTSUBS_LU] = nms_lu ; + + /* number of "dense" rows/columns */ + Info [AMD_NDENSE] = ndense ; + + /* largest front is dmax-by-dmax */ + Info [AMD_DMAX] = dmax ; + + /* number of garbage collections in AMD */ + Info [AMD_NCMPA] = ncmpa ; + + /* successful ordering */ + Info [AMD_STATUS] = AMD_OK ; + } + +/* ========================================================================= */ +/* POST-ORDERING */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- + * Variables at this point: + * + * Pe: holds the elimination tree. The parent of j is FLIP (Pe [j]), + * or EMPTY if j is a root. The tree holds both elements and + * non-principal (unordered) variables absorbed into them. + * Dense variables are non-principal and unordered. + * + * Elen: holds the size of each element, including the diagonal part. + * FLIP (Elen [e]) > 0 if e is an element. For unordered + * variables i, Elen [i] is EMPTY. + * + * Nv: Nv [e] > 0 is the number of pivots represented by the element e. + * For unordered variables i, Nv [i] is zero. + * + * Contents no longer needed: + * W, Iw, Len, Degree, Head, Next, Last. + * + * The matrix itself has been destroyed. + * + * n: the size of the matrix. + * No other scalars needed (pfree, iwlen, etc.) + * ------------------------------------------------------------------------- */ + + /* restore Pe */ + for (i = 0 ; i < n ; i++) + { + Pe [i] = FLIP (Pe [i]) ; + } + + /* restore Elen, for output information, and for postordering */ + for (i = 0 ; i < n ; i++) + { + Elen [i] = FLIP (Elen [i]) ; + } + +/* Now the parent of j is Pe [j], or EMPTY if j is a root. Elen [e] > 0 + * is the size of element e. Elen [i] is EMPTY for unordered variable i. */ + +#ifndef NDEBUG + AMD_DEBUG2 (("\nTree:\n")) ; + for (i = 0 ; i < n ; i++) + { + AMD_DEBUG2 ((" "ID" parent: "ID" ", i, Pe [i])) ; + ASSERT (Pe [i] >= EMPTY && Pe [i] < n) ; + if (Nv [i] > 0) + { + /* this is an element */ + e = i ; + AMD_DEBUG2 ((" element, size is "ID"\n", Elen [i])) ; + ASSERT (Elen [e] > 0) ; + } + AMD_DEBUG2 (("\n")) ; + } + AMD_DEBUG2 (("\nelements:\n")) ; + for (e = 0 ; e < n ; e++) + { + if (Nv [e] > 0) + { + AMD_DEBUG3 (("Element e= "ID" size "ID" nv "ID" \n", e, + Elen [e], Nv [e])) ; + } + } + AMD_DEBUG2 (("\nvariables:\n")) ; + for (i = 0 ; i < n ; i++) + { + Int cnt ; + if (Nv [i] == 0) + { + AMD_DEBUG3 (("i unordered: "ID"\n", i)) ; + j = Pe [i] ; + cnt = 0 ; + AMD_DEBUG3 ((" j: "ID"\n", j)) ; + if (j == EMPTY) + { + AMD_DEBUG3 ((" i is a dense variable\n")) ; + } + else + { + ASSERT (j >= 0 && j < n) ; + while (Nv [j] == 0) + { + AMD_DEBUG3 ((" j : "ID"\n", j)) ; + j = Pe [j] ; + AMD_DEBUG3 ((" j:: "ID"\n", j)) ; + cnt++ ; + if (cnt > n) break ; + } + e = j ; + AMD_DEBUG3 ((" got to e: "ID"\n", e)) ; + } + } + } +#endif + +/* ========================================================================= */ +/* compress the paths of the variables */ +/* ========================================================================= */ + + for (i = 0 ; i < n ; i++) + { + if (Nv [i] == 0) + { + + /* ------------------------------------------------------------- + * i is an un-ordered row. Traverse the tree from i until + * reaching an element, e. The element, e, was the principal + * supervariable of i and all nodes in the path from i to when e + * was selected as pivot. + * ------------------------------------------------------------- */ + + AMD_DEBUG1 (("Path compression, i unordered: "ID"\n", i)) ; + j = Pe [i] ; + ASSERT (j >= EMPTY && j < n) ; + AMD_DEBUG3 ((" j: "ID"\n", j)) ; + if (j == EMPTY) + { + /* Skip a dense variable. It has no parent. */ + AMD_DEBUG3 ((" i is a dense variable\n")) ; + continue ; + } + + /* while (j is a variable) */ + while (Nv [j] == 0) + { + AMD_DEBUG3 ((" j : "ID"\n", j)) ; + j = Pe [j] ; + AMD_DEBUG3 ((" j:: "ID"\n", j)) ; + ASSERT (j >= 0 && j < n) ; + } + /* got to an element e */ + e = j ; + AMD_DEBUG3 (("got to e: "ID"\n", e)) ; + + /* ------------------------------------------------------------- + * traverse the path again from i to e, and compress the path + * (all nodes point to e). Path compression allows this code to + * compute in O(n) time. + * ------------------------------------------------------------- */ + + j = i ; + /* while (j is a variable) */ + while (Nv [j] == 0) + { + jnext = Pe [j] ; + AMD_DEBUG3 (("j "ID" jnext "ID"\n", j, jnext)) ; + Pe [j] = e ; + j = jnext ; + ASSERT (j >= 0 && j < n) ; + } + } + } + +/* ========================================================================= */ +/* postorder the assembly tree */ +/* ========================================================================= */ + + AMD_postorder (n, Pe, Nv, Elen, + W, /* output order */ + Head, Next, Last) ; /* workspace */ + +/* ========================================================================= */ +/* compute output permutation and inverse permutation */ +/* ========================================================================= */ + + /* W [e] = k means that element e is the kth element in the new + * order. e is in the range 0 to n-1, and k is in the range 0 to + * the number of elements. Use Head for inverse order. */ + + for (k = 0 ; k < n ; k++) + { + Head [k] = EMPTY ; + Next [k] = EMPTY ; + } + for (e = 0 ; e < n ; e++) + { + k = W [e] ; + ASSERT ((k == EMPTY) == (Nv [e] == 0)) ; + if (k != EMPTY) + { + ASSERT (k >= 0 && k < n) ; + Head [k] = e ; + } + } + + /* construct output inverse permutation in Next, + * and permutation in Last */ + nel = 0 ; + for (k = 0 ; k < n ; k++) + { + e = Head [k] ; + if (e == EMPTY) break ; + ASSERT (e >= 0 && e < n && Nv [e] > 0) ; + Next [e] = nel ; + nel += Nv [e] ; + } + ASSERT (nel == n - ndense) ; + + /* order non-principal variables (dense, & those merged into supervar's) */ + for (i = 0 ; i < n ; i++) + { + if (Nv [i] == 0) + { + e = Pe [i] ; + ASSERT (e >= EMPTY && e < n) ; + if (e != EMPTY) + { + /* This is an unordered variable that was merged + * into element e via supernode detection or mass + * elimination of i when e became the pivot element. + * Place i in order just before e. */ + ASSERT (Next [i] == EMPTY && Nv [e] > 0) ; + Next [i] = Next [e] ; + Next [e]++ ; + } + else + { + /* This is a dense unordered variable, with no parent. + * Place it last in the output order. */ + Next [i] = nel++ ; + } + } + } + ASSERT (nel == n) ; + + AMD_DEBUG2 (("\n\nPerm:\n")) ; + for (i = 0 ; i < n ; i++) + { + k = Next [i] ; + ASSERT (k >= 0 && k < n) ; + Last [k] = i ; + AMD_DEBUG2 ((" perm ["ID"] = "ID"\n", k, i)) ; + } +} diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_aat.c b/resources/3rdparty/glpk-4.53/src/amd/amd_aat.c new file mode 100644 index 000000000..63bf55f52 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_aat.c @@ -0,0 +1,185 @@ +/* ========================================================================= */ +/* === AMD_aat ============================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* AMD_aat: compute the symmetry of the pattern of A, and count the number of + * nonzeros each column of A+A' (excluding the diagonal). Assumes the input + * matrix has no errors, with sorted columns and no duplicates + * (AMD_valid (n, n, Ap, Ai) must be AMD_OK, but this condition is not + * checked). + */ + +#include "amd_internal.h" + +GLOBAL size_t AMD_aat /* returns nz in A+A' */ +( + Int n, + const Int Ap [ ], + const Int Ai [ ], + Int Len [ ], /* Len [j]: length of column j of A+A', excl diagonal*/ + Int Tp [ ], /* workspace of size n */ + double Info [ ] +) +{ + Int p1, p2, p, i, j, pj, pj2, k, nzdiag, nzboth, nz ; + double sym ; + size_t nzaat ; + +#ifndef NDEBUG + AMD_debug_init ("AMD AAT") ; + for (k = 0 ; k < n ; k++) Tp [k] = EMPTY ; + ASSERT (AMD_valid (n, n, Ap, Ai) == AMD_OK) ; +#endif + + if (Info != (double *) NULL) + { + /* clear the Info array, if it exists */ + for (i = 0 ; i < AMD_INFO ; i++) + { + Info [i] = EMPTY ; + } + Info [AMD_STATUS] = AMD_OK ; + } + + for (k = 0 ; k < n ; k++) + { + Len [k] = 0 ; + } + + nzdiag = 0 ; + nzboth = 0 ; + nz = Ap [n] ; + + for (k = 0 ; k < n ; k++) + { + p1 = Ap [k] ; + p2 = Ap [k+1] ; + AMD_DEBUG2 (("\nAAT Column: "ID" p1: "ID" p2: "ID"\n", k, p1, p2)) ; + + /* construct A+A' */ + for (p = p1 ; p < p2 ; ) + { + /* scan the upper triangular part of A */ + j = Ai [p] ; + if (j < k) + { + /* entry A (j,k) is in the strictly upper triangular part, + * add both A (j,k) and A (k,j) to the matrix A+A' */ + Len [j]++ ; + Len [k]++ ; + AMD_DEBUG3 ((" upper ("ID","ID") ("ID","ID")\n", j,k, k,j)); + p++ ; + } + else if (j == k) + { + /* skip the diagonal */ + p++ ; + nzdiag++ ; + break ; + } + else /* j > k */ + { + /* first entry below the diagonal */ + break ; + } + /* scan lower triangular part of A, in column j until reaching + * row k. Start where last scan left off. */ + ASSERT (Tp [j] != EMPTY) ; + ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ; + pj2 = Ap [j+1] ; + for (pj = Tp [j] ; pj < pj2 ; ) + { + i = Ai [pj] ; + if (i < k) + { + /* A (i,j) is only in the lower part, not in upper. + * add both A (i,j) and A (j,i) to the matrix A+A' */ + Len [i]++ ; + Len [j]++ ; + AMD_DEBUG3 ((" lower ("ID","ID") ("ID","ID")\n", + i,j, j,i)) ; + pj++ ; + } + else if (i == k) + { + /* entry A (k,j) in lower part and A (j,k) in upper */ + pj++ ; + nzboth++ ; + break ; + } + else /* i > k */ + { + /* consider this entry later, when k advances to i */ + break ; + } + } + Tp [j] = pj ; + } + /* Tp [k] points to the entry just below the diagonal in column k */ + Tp [k] = p ; + } + + /* clean up, for remaining mismatched entries */ + for (j = 0 ; j < n ; j++) + { + for (pj = Tp [j] ; pj < Ap [j+1] ; pj++) + { + i = Ai [pj] ; + /* A (i,j) is only in the lower part, not in upper. + * add both A (i,j) and A (j,i) to the matrix A+A' */ + Len [i]++ ; + Len [j]++ ; + AMD_DEBUG3 ((" lower cleanup ("ID","ID") ("ID","ID")\n", + i,j, j,i)) ; + } + } + + /* --------------------------------------------------------------------- */ + /* compute the symmetry of the nonzero pattern of A */ + /* --------------------------------------------------------------------- */ + + /* Given a matrix A, the symmetry of A is: + * B = tril (spones (A), -1) + triu (spones (A), 1) ; + * sym = nnz (B & B') / nnz (B) ; + * or 1 if nnz (B) is zero. + */ + + if (nz == nzdiag) + { + sym = 1 ; + } + else + { + sym = (2 * (double) nzboth) / ((double) (nz - nzdiag)) ; + } + + nzaat = 0 ; + for (k = 0 ; k < n ; k++) + { + nzaat += Len [k] ; + } + + AMD_DEBUG1 (("AMD nz in A+A', excluding diagonal (nzaat) = %g\n", + (double) nzaat)) ; + AMD_DEBUG1 ((" nzboth: "ID" nz: "ID" nzdiag: "ID" symmetry: %g\n", + nzboth, nz, nzdiag, sym)) ; + + if (Info != (double *) NULL) + { + Info [AMD_STATUS] = AMD_OK ; + Info [AMD_N] = n ; + Info [AMD_NZ] = nz ; + Info [AMD_SYMMETRY] = sym ; /* symmetry of pattern of A */ + Info [AMD_NZDIAG] = nzdiag ; /* nonzeros on diagonal of A */ + Info [AMD_NZ_A_PLUS_AT] = nzaat ; /* nonzeros in A+A' */ + } + + return (nzaat) ; +} diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_control.c b/resources/3rdparty/glpk-4.53/src/amd/amd_control.c new file mode 100644 index 000000000..f4d4f0dfa --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_control.c @@ -0,0 +1,64 @@ +/* ========================================================================= */ +/* === AMD_control ========================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable. Prints the control parameters for AMD. See amd.h + * for details. If the Control array is not present, the defaults are + * printed instead. + */ + +#include "amd_internal.h" + +GLOBAL void AMD_control +( + double Control [ ] +) +{ + double alpha ; + Int aggressive ; + + if (Control != (double *) NULL) + { + alpha = Control [AMD_DENSE] ; + aggressive = Control [AMD_AGGRESSIVE] != 0 ; + } + else + { + alpha = AMD_DEFAULT_DENSE ; + aggressive = AMD_DEFAULT_AGGRESSIVE ; + } + + PRINTF (("\nAMD version %d.%d.%d, %s: approximate minimum degree ordering\n" + " dense row parameter: %g\n", AMD_MAIN_VERSION, AMD_SUB_VERSION, + AMD_SUBSUB_VERSION, AMD_DATE, alpha)) ; + + if (alpha < 0) + { + PRINTF ((" no rows treated as dense\n")) ; + } + else + { + PRINTF (( + " (rows with more than max (%g * sqrt (n), 16) entries are\n" + " considered \"dense\", and placed last in output permutation)\n", + alpha)) ; + } + + if (aggressive) + { + PRINTF ((" aggressive absorption: yes\n")) ; + } + else + { + PRINTF ((" aggressive absorption: no\n")) ; + } + + PRINTF ((" size of AMD integer: %d\n\n", sizeof (Int))) ; +} diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_defaults.c b/resources/3rdparty/glpk-4.53/src/amd/amd_defaults.c new file mode 100644 index 000000000..820e89420 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_defaults.c @@ -0,0 +1,38 @@ +/* ========================================================================= */ +/* === AMD_defaults ======================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable. Sets default control parameters for AMD. See amd.h + * for details. + */ + +#include "amd_internal.h" + +/* ========================================================================= */ +/* === AMD defaults ======================================================== */ +/* ========================================================================= */ + +GLOBAL void AMD_defaults +( + double Control [ ] +) +{ + Int i ; + + if (Control != (double *) NULL) + { + for (i = 0 ; i < AMD_CONTROL ; i++) + { + Control [i] = 0 ; + } + Control [AMD_DENSE] = AMD_DEFAULT_DENSE ; + Control [AMD_AGGRESSIVE] = AMD_DEFAULT_AGGRESSIVE ; + } +} diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_dump.c b/resources/3rdparty/glpk-4.53/src/amd/amd_dump.c new file mode 100644 index 000000000..39bbe1d8e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_dump.c @@ -0,0 +1,180 @@ +/* ========================================================================= */ +/* === AMD_dump ============================================================ */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Debugging routines for AMD. Not used if NDEBUG is not defined at compile- + * time (the default). See comments in amd_internal.h on how to enable + * debugging. Not user-callable. + */ + +#include "amd_internal.h" + +#ifndef NDEBUG + +/* This global variable is present only when debugging */ +GLOBAL Int AMD_debug = -999 ; /* default is no debug printing */ + +/* ========================================================================= */ +/* === AMD_debug_init ====================================================== */ +/* ========================================================================= */ + +/* Sets the debug print level, by reading the file debug.amd (if it exists) */ + +GLOBAL void AMD_debug_init ( char *s ) +{ + FILE *f ; + f = fopen ("debug.amd", "r") ; + if (f == (FILE *) NULL) + { + AMD_debug = -999 ; + } + else + { + fscanf (f, ID, &AMD_debug) ; + fclose (f) ; + } + if (AMD_debug >= 0) + { + printf ("%s: AMD_debug_init, D= "ID"\n", s, AMD_debug) ; + } +} + +/* ========================================================================= */ +/* === AMD_dump ============================================================ */ +/* ========================================================================= */ + +/* Dump AMD's data structure, except for the hash buckets. This routine + * cannot be called when the hash buckets are non-empty. + */ + +GLOBAL void AMD_dump ( + Int n, /* A is n-by-n */ + Int Pe [ ], /* pe [0..n-1]: index in iw of start of row i */ + Int Iw [ ], /* workspace of size iwlen, iwlen [0..pfree-1] + * holds the matrix on input */ + Int Len [ ], /* len [0..n-1]: length for row i */ + Int iwlen, /* length of iw */ + Int pfree, /* iw [pfree ... iwlen-1] is empty on input */ + Int Nv [ ], /* nv [0..n-1] */ + Int Next [ ], /* next [0..n-1] */ + Int Last [ ], /* last [0..n-1] */ + Int Head [ ], /* head [0..n-1] */ + Int Elen [ ], /* size n */ + Int Degree [ ], /* size n */ + Int W [ ], /* size n */ + Int nel +) +{ + Int i, pe, elen, nv, len, e, p, k, j, deg, w, cnt, ilast ; + + if (AMD_debug < 0) return ; + ASSERT (pfree <= iwlen) ; + AMD_DEBUG3 (("\nAMD dump, pfree: "ID"\n", pfree)) ; + for (i = 0 ; i < n ; i++) + { + pe = Pe [i] ; + elen = Elen [i] ; + nv = Nv [i] ; + len = Len [i] ; + w = W [i] ; + + if (elen >= EMPTY) + { + if (nv == 0) + { + AMD_DEBUG3 (("\nI "ID": nonprincipal: ", i)) ; + ASSERT (elen == EMPTY) ; + if (pe == EMPTY) + { + AMD_DEBUG3 ((" dense node\n")) ; + ASSERT (w == 1) ; + } + else + { + ASSERT (pe < EMPTY) ; + AMD_DEBUG3 ((" i "ID" -> parent "ID"\n", i, FLIP (Pe[i]))); + } + } + else + { + AMD_DEBUG3 (("\nI "ID": active principal supervariable:\n",i)); + AMD_DEBUG3 ((" nv(i): "ID" Flag: %d\n", nv, (nv < 0))) ; + ASSERT (elen >= 0) ; + ASSERT (nv > 0 && pe >= 0) ; + p = pe ; + AMD_DEBUG3 ((" e/s: ")) ; + if (elen == 0) AMD_DEBUG3 ((" : ")) ; + ASSERT (pe + len <= pfree) ; + for (k = 0 ; k < len ; k++) + { + j = Iw [p] ; + AMD_DEBUG3 ((" "ID"", j)) ; + ASSERT (j >= 0 && j < n) ; + if (k == elen-1) AMD_DEBUG3 ((" : ")) ; + p++ ; + } + AMD_DEBUG3 (("\n")) ; + } + } + else + { + e = i ; + if (w == 0) + { + AMD_DEBUG3 (("\nE "ID": absorbed element: w "ID"\n", e, w)) ; + ASSERT (nv > 0 && pe < 0) ; + AMD_DEBUG3 ((" e "ID" -> parent "ID"\n", e, FLIP (Pe [e]))) ; + } + else + { + AMD_DEBUG3 (("\nE "ID": unabsorbed element: w "ID"\n", e, w)) ; + ASSERT (nv > 0 && pe >= 0) ; + p = pe ; + AMD_DEBUG3 ((" : ")) ; + ASSERT (pe + len <= pfree) ; + for (k = 0 ; k < len ; k++) + { + j = Iw [p] ; + AMD_DEBUG3 ((" "ID"", j)) ; + ASSERT (j >= 0 && j < n) ; + p++ ; + } + AMD_DEBUG3 (("\n")) ; + } + } + } + + /* this routine cannot be called when the hash buckets are non-empty */ + AMD_DEBUG3 (("\nDegree lists:\n")) ; + if (nel >= 0) + { + cnt = 0 ; + for (deg = 0 ; deg < n ; deg++) + { + if (Head [deg] == EMPTY) continue ; + ilast = EMPTY ; + AMD_DEBUG3 ((ID": \n", deg)) ; + for (i = Head [deg] ; i != EMPTY ; i = Next [i]) + { + AMD_DEBUG3 ((" "ID" : next "ID" last "ID" deg "ID"\n", + i, Next [i], Last [i], Degree [i])) ; + ASSERT (i >= 0 && i < n && ilast == Last [i] && + deg == Degree [i]) ; + cnt += Nv [i] ; + ilast = i ; + } + AMD_DEBUG3 (("\n")) ; + } + ASSERT (cnt == n - nel) ; + } + +} + +#endif diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_info.c b/resources/3rdparty/glpk-4.53/src/amd/amd_info.c new file mode 100644 index 000000000..e7b806a97 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_info.c @@ -0,0 +1,120 @@ +/* ========================================================================= */ +/* === AMD_info ============================================================ */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable. Prints the output statistics for AMD. See amd.h + * for details. If the Info array is not present, nothing is printed. + */ + +#include "amd_internal.h" + +#define PRI(format,x) { if (x >= 0) { PRINTF ((format, x)) ; }} + +GLOBAL void AMD_info +( + double Info [ ] +) +{ + double n, ndiv, nmultsubs_ldl, nmultsubs_lu, lnz, lnzd ; + + PRINTF (("\nAMD version %d.%d.%d, %s, results:\n", + AMD_MAIN_VERSION, AMD_SUB_VERSION, AMD_SUBSUB_VERSION, AMD_DATE)) ; + + if (!Info) + { + return ; + } + + n = Info [AMD_N] ; + ndiv = Info [AMD_NDIV] ; + nmultsubs_ldl = Info [AMD_NMULTSUBS_LDL] ; + nmultsubs_lu = Info [AMD_NMULTSUBS_LU] ; + lnz = Info [AMD_LNZ] ; + lnzd = (n >= 0 && lnz >= 0) ? (n + lnz) : (-1) ; + + /* AMD return status */ + PRINTF ((" status: ")) ; + if (Info [AMD_STATUS] == AMD_OK) + { + PRINTF (("OK\n")) ; + } + else if (Info [AMD_STATUS] == AMD_OUT_OF_MEMORY) + { + PRINTF (("out of memory\n")) ; + } + else if (Info [AMD_STATUS] == AMD_INVALID) + { + PRINTF (("invalid matrix\n")) ; + } + else if (Info [AMD_STATUS] == AMD_OK_BUT_JUMBLED) + { + PRINTF (("OK, but jumbled\n")) ; + } + else + { + PRINTF (("unknown\n")) ; + } + + /* statistics about the input matrix */ + PRI (" n, dimension of A: %.20g\n", n); + PRI (" nz, number of nonzeros in A: %.20g\n", + Info [AMD_NZ]) ; + PRI (" symmetry of A: %.4f\n", + Info [AMD_SYMMETRY]) ; + PRI (" number of nonzeros on diagonal: %.20g\n", + Info [AMD_NZDIAG]) ; + PRI (" nonzeros in pattern of A+A' (excl. diagonal): %.20g\n", + Info [AMD_NZ_A_PLUS_AT]) ; + PRI (" # dense rows/columns of A+A': %.20g\n", + Info [AMD_NDENSE]) ; + + /* statistics about AMD's behavior */ + PRI (" memory used, in bytes: %.20g\n", + Info [AMD_MEMORY]) ; + PRI (" # of memory compactions: %.20g\n", + Info [AMD_NCMPA]) ; + + /* statistics about the ordering quality */ + PRINTF (("\n" + " The following approximate statistics are for a subsequent\n" + " factorization of A(P,P) + A(P,P)'. They are slight upper\n" + " bounds if there are no dense rows/columns in A+A', and become\n" + " looser if dense rows/columns exist.\n\n")) ; + + PRI (" nonzeros in L (excluding diagonal): %.20g\n", + lnz) ; + PRI (" nonzeros in L (including diagonal): %.20g\n", + lnzd) ; + PRI (" # divide operations for LDL' or LU: %.20g\n", + ndiv) ; + PRI (" # multiply-subtract operations for LDL': %.20g\n", + nmultsubs_ldl) ; + PRI (" # multiply-subtract operations for LU: %.20g\n", + nmultsubs_lu) ; + PRI (" max nz. in any column of L (incl. diagonal): %.20g\n", + Info [AMD_DMAX]) ; + + /* total flop counts for various factorizations */ + + if (n >= 0 && ndiv >= 0 && nmultsubs_ldl >= 0 && nmultsubs_lu >= 0) + { + PRINTF (("\n" + " chol flop count for real A, sqrt counted as 1 flop: %.20g\n" + " LDL' flop count for real A: %.20g\n" + " LDL' flop count for complex A: %.20g\n" + " LU flop count for real A (with no pivoting): %.20g\n" + " LU flop count for complex A (with no pivoting): %.20g\n\n", + n + ndiv + 2*nmultsubs_ldl, + ndiv + 2*nmultsubs_ldl, + 9*ndiv + 8*nmultsubs_ldl, + ndiv + 2*nmultsubs_lu, + 9*ndiv + 8*nmultsubs_lu)) ; + } +} diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_internal.h b/resources/3rdparty/glpk-4.53/src/amd/amd_internal.h new file mode 100644 index 000000000..b08f8436b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_internal.h @@ -0,0 +1,117 @@ +/* amd_internal.h */ + +/* Written by Andrew Makhorin <mao@gnu.org>. */ + +#ifndef AMD_INTERNAL_H +#define AMD_INTERNAL_H + +/* AMD will be exceedingly slow when running in debug mode. */ +#if 1 +#define NDEBUG +#endif + +#include "amd.h" +#define _GLPSTD_STDIO +#include "env.h" + +#define Int int +#define ID "%d" +#define Int_MAX INT_MAX + +#if 0 /* 15/II-2012 */ +/* now this macro is defined in glpenv.h; besides, the definiton below + depends on implementation, because size_t is an unsigned type */ +#define SIZE_T_MAX ((size_t)(-1)) +#endif + +#define EMPTY (-1) +#define FLIP(i) (-(i)-2) +#define UNFLIP(i) ((i < EMPTY) ? FLIP (i) : (i)) + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +#define IMPLIES(p, q) (!(p) || (q)) + +#define GLOBAL + +#define AMD_order amd_order +#define AMD_defaults amd_defaults +#define AMD_control amd_control +#define AMD_info amd_info +#define AMD_1 amd_1 +#define AMD_2 amd_2 +#define AMD_valid amd_valid +#define AMD_aat amd_aat +#define AMD_postorder amd_postorder +#define AMD_post_tree amd_post_tree +#define AMD_dump amd_dump +#define AMD_debug amd_debug +#define AMD_debug_init amd_debug_init +#define AMD_preprocess amd_preprocess + +#define amd_malloc xmalloc +#if 0 /* 24/V-2009 */ +#define amd_free xfree +#else +#define amd_free(ptr) { if ((ptr) != NULL) xfree(ptr); } +#endif +#define amd_printf xprintf + +#define PRINTF(params) { amd_printf params; } + +#ifndef NDEBUG +#define ASSERT(expr) xassert(expr) +#define AMD_DEBUG0(params) { PRINTF(params); } +#define AMD_DEBUG1(params) { if (AMD_debug >= 1) PRINTF(params); } +#define AMD_DEBUG2(params) { if (AMD_debug >= 2) PRINTF(params); } +#define AMD_DEBUG3(params) { if (AMD_debug >= 3) PRINTF(params); } +#define AMD_DEBUG4(params) { if (AMD_debug >= 4) PRINTF(params); } +#else +#define ASSERT(expression) +#define AMD_DEBUG0(params) +#define AMD_DEBUG1(params) +#define AMD_DEBUG2(params) +#define AMD_DEBUG3(params) +#define AMD_DEBUG4(params) +#endif + +#define amd_aat _glp_amd_aat +size_t AMD_aat(Int n, const Int Ap[], const Int Ai[], Int Len[], + Int Tp[], double Info[]); + +#define amd_1 _glp_amd_1 +void AMD_1(Int n, const Int Ap[], const Int Ai[], Int P[], Int Pinv[], + Int Len[], Int slen, Int S[], double Control[], double Info[]); + +#define amd_postorder _glp_amd_postorder +void AMD_postorder(Int nn, Int Parent[], Int Npiv[], Int Fsize[], + Int Order[], Int Child[], Int Sibling[], Int Stack[]); + +#define amd_post_tree _glp_amd_post_tree +#ifndef NDEBUG +Int AMD_post_tree(Int root, Int k, Int Child[], const Int Sibling[], + Int Order[], Int Stack[], Int nn); +#else +Int AMD_post_tree(Int root, Int k, Int Child[], const Int Sibling[], + Int Order[], Int Stack[]); +#endif + +#define amd_preprocess _glp_amd_preprocess +void AMD_preprocess(Int n, const Int Ap[], const Int Ai[], Int Rp[], + Int Ri[], Int W[], Int Flag[]); + +#define amd_debug _glp_amd_debug +extern Int AMD_debug; + +#define amd_debug_init _glp_amd_debug_init +void AMD_debug_init(char *s); + +#define amd_dump _glp_amd_dump +void AMD_dump(Int n, Int Pe[], Int Iw[], Int Len[], Int iwlen, + Int pfree, Int Nv[], Int Next[], Int Last[], Int Head[], + Int Elen[], Int Degree[], Int W[], Int nel); + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_order.c b/resources/3rdparty/glpk-4.53/src/amd/amd_order.c new file mode 100644 index 000000000..332d56637 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_order.c @@ -0,0 +1,200 @@ +/* ========================================================================= */ +/* === AMD_order =========================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable AMD minimum degree ordering routine. See amd.h for + * documentation. + */ + +#include "amd_internal.h" + +/* ========================================================================= */ +/* === AMD_order =========================================================== */ +/* ========================================================================= */ + +GLOBAL Int AMD_order +( + Int n, + const Int Ap [ ], + const Int Ai [ ], + Int P [ ], + double Control [ ], + double Info [ ] +) +{ + Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ; + size_t nzaat, slen ; + double mem = 0 ; + +#ifndef NDEBUG + AMD_debug_init ("amd") ; +#endif + + /* clear the Info array, if it exists */ + info = Info != (double *) NULL ; + if (info) + { + for (i = 0 ; i < AMD_INFO ; i++) + { + Info [i] = EMPTY ; + } + Info [AMD_N] = n ; + Info [AMD_STATUS] = AMD_OK ; + } + + /* make sure inputs exist and n is >= 0 */ + if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0) + { + if (info) Info [AMD_STATUS] = AMD_INVALID ; + return (AMD_INVALID) ; /* arguments are invalid */ + } + + if (n == 0) + { + return (AMD_OK) ; /* n is 0 so there's nothing to do */ + } + + nz = Ap [n] ; + if (info) + { + Info [AMD_NZ] = nz ; + } + if (nz < 0) + { + if (info) Info [AMD_STATUS] = AMD_INVALID ; + return (AMD_INVALID) ; + } + + /* check if n or nz will cause size_t overflow */ + if (((size_t) n) >= SIZE_T_MAX / sizeof (Int) + || ((size_t) nz) >= SIZE_T_MAX / sizeof (Int)) + { + if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; /* problem too large */ + } + + /* check the input matrix: AMD_OK, AMD_INVALID, or AMD_OK_BUT_JUMBLED */ + status = AMD_valid (n, n, Ap, Ai) ; + + if (status == AMD_INVALID) + { + if (info) Info [AMD_STATUS] = AMD_INVALID ; + return (AMD_INVALID) ; /* matrix is invalid */ + } + + /* allocate two size-n integer workspaces */ + Len = amd_malloc (n * sizeof (Int)) ; + Pinv = amd_malloc (n * sizeof (Int)) ; + mem += n ; + mem += n ; + if (!Len || !Pinv) + { + /* :: out of memory :: */ + amd_free (Len) ; + amd_free (Pinv) ; + if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; + } + + if (status == AMD_OK_BUT_JUMBLED) + { + /* sort the input matrix and remove duplicate entries */ + AMD_DEBUG1 (("Matrix is jumbled\n")) ; + Rp = amd_malloc ((n+1) * sizeof (Int)) ; + Ri = amd_malloc (MAX (nz,1) * sizeof (Int)) ; + mem += (n+1) ; + mem += MAX (nz,1) ; + if (!Rp || !Ri) + { + /* :: out of memory :: */ + amd_free (Rp) ; + amd_free (Ri) ; + amd_free (Len) ; + amd_free (Pinv) ; + if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; + } + /* use Len and Pinv as workspace to create R = A' */ + AMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ; + Cp = Rp ; + Ci = Ri ; + } + else + { + /* order the input matrix as-is. No need to compute R = A' first */ + Rp = NULL ; + Ri = NULL ; + Cp = (Int *) Ap ; + Ci = (Int *) Ai ; + } + + /* --------------------------------------------------------------------- */ + /* determine the symmetry and count off-diagonal nonzeros in A+A' */ + /* --------------------------------------------------------------------- */ + + nzaat = AMD_aat (n, Cp, Ci, Len, P, Info) ; + AMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ; + ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ; + + /* --------------------------------------------------------------------- */ + /* allocate workspace for matrix, elbow room, and 6 size-n vectors */ + /* --------------------------------------------------------------------- */ + + S = NULL ; + slen = nzaat ; /* space for matrix */ + ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */ + slen += nzaat/5 ; /* add elbow room */ + for (i = 0 ; ok && i < 7 ; i++) + { + ok = ((slen + n) > slen) ; /* check for size_t overflow */ + slen += n ; /* size-n elbow room, 6 size-n work */ + } + mem += slen ; + ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */ + ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */ + if (ok) + { + S = amd_malloc (slen * sizeof (Int)) ; + } + AMD_DEBUG1 (("slen %g\n", (double) slen)) ; + if (!S) + { + /* :: out of memory :: (or problem too large) */ + amd_free (Rp) ; + amd_free (Ri) ; + amd_free (Len) ; + amd_free (Pinv) ; + if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; + } + if (info) + { + /* memory usage, in bytes. */ + Info [AMD_MEMORY] = mem * sizeof (Int) ; + } + + /* --------------------------------------------------------------------- */ + /* order the matrix */ + /* --------------------------------------------------------------------- */ + + AMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info) ; + + /* --------------------------------------------------------------------- */ + /* free the workspace */ + /* --------------------------------------------------------------------- */ + + amd_free (Rp) ; + amd_free (Ri) ; + amd_free (Len) ; + amd_free (Pinv) ; + amd_free (S) ; + if (info) Info [AMD_STATUS] = status ; + return (status) ; /* successful ordering */ +} diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_post_tree.c b/resources/3rdparty/glpk-4.53/src/amd/amd_post_tree.c new file mode 100644 index 000000000..bff0e263a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_post_tree.c @@ -0,0 +1,121 @@ +/* ========================================================================= */ +/* === AMD_post_tree ======================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Post-ordering of a supernodal elimination tree. */ + +#include "amd_internal.h" + +GLOBAL Int AMD_post_tree +( + Int root, /* root of the tree */ + Int k, /* start numbering at k */ + Int Child [ ], /* input argument of size nn, undefined on + * output. Child [i] is the head of a link + * list of all nodes that are children of node + * i in the tree. */ + const Int Sibling [ ], /* input argument of size nn, not modified. + * If f is a node in the link list of the + * children of node i, then Sibling [f] is the + * next child of node i. + */ + Int Order [ ], /* output order, of size nn. Order [i] = k + * if node i is the kth node of the reordered + * tree. */ + Int Stack [ ] /* workspace of size nn */ +#ifndef NDEBUG + , Int nn /* nodes are in the range 0..nn-1. */ +#endif +) +{ + Int f, head, h, i ; + +#if 0 + /* --------------------------------------------------------------------- */ + /* recursive version (Stack [ ] is not used): */ + /* --------------------------------------------------------------------- */ + + /* this is simple, but can caouse stack overflow if nn is large */ + i = root ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ; + } + Order [i] = k++ ; + return (k) ; +#endif + + /* --------------------------------------------------------------------- */ + /* non-recursive version, using an explicit stack */ + /* --------------------------------------------------------------------- */ + + /* push root on the stack */ + head = 0 ; + Stack [0] = root ; + + while (head >= 0) + { + /* get head of stack */ + ASSERT (head < nn) ; + i = Stack [head] ; + AMD_DEBUG1 (("head of stack "ID" \n", i)) ; + ASSERT (i >= 0 && i < nn) ; + + if (Child [i] != EMPTY) + { + /* the children of i are not yet ordered */ + /* push each child onto the stack in reverse order */ + /* so that small ones at the head of the list get popped first */ + /* and the biggest one at the end of the list gets popped last */ + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + head++ ; + ASSERT (head < nn) ; + ASSERT (f >= 0 && f < nn) ; + } + h = head ; + ASSERT (head < nn) ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (h > 0) ; + Stack [h--] = f ; + AMD_DEBUG1 (("push "ID" on stack\n", f)) ; + ASSERT (f >= 0 && f < nn) ; + } + ASSERT (Stack [h] == i) ; + + /* delete child list so that i gets ordered next time we see it */ + Child [i] = EMPTY ; + } + else + { + /* the children of i (if there were any) are already ordered */ + /* remove i from the stack and order it. Front i is kth front */ + head-- ; + AMD_DEBUG1 (("pop "ID" order "ID"\n", i, k)) ; + Order [i] = k++ ; + ASSERT (k <= nn) ; + } + +#ifndef NDEBUG + AMD_DEBUG1 (("\nStack:")) ; + for (h = head ; h >= 0 ; h--) + { + Int j = Stack [h] ; + AMD_DEBUG1 ((" "ID, j)) ; + ASSERT (j >= 0 && j < nn) ; + } + AMD_DEBUG1 (("\n\n")) ; + ASSERT (head < nn) ; +#endif + + } + return (k) ; +} diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_postorder.c b/resources/3rdparty/glpk-4.53/src/amd/amd_postorder.c new file mode 100644 index 000000000..a3ece915c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_postorder.c @@ -0,0 +1,207 @@ +/* ========================================================================= */ +/* === AMD_postorder ======================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Perform a postordering (via depth-first search) of an assembly tree. */ + +#include "amd_internal.h" + +GLOBAL void AMD_postorder +( + /* inputs, not modified on output: */ + Int nn, /* nodes are in the range 0..nn-1 */ + Int Parent [ ], /* Parent [j] is the parent of j, or EMPTY if root */ + Int Nv [ ], /* Nv [j] > 0 number of pivots represented by node j, + * or zero if j is not a node. */ + Int Fsize [ ], /* Fsize [j]: size of node j */ + + /* output, not defined on input: */ + Int Order [ ], /* output post-order */ + + /* workspaces of size nn: */ + Int Child [ ], + Int Sibling [ ], + Int Stack [ ] +) +{ + Int i, j, k, parent, frsize, f, fprev, maxfrsize, bigfprev, bigf, fnext ; + + for (j = 0 ; j < nn ; j++) + { + Child [j] = EMPTY ; + Sibling [j] = EMPTY ; + } + + /* --------------------------------------------------------------------- */ + /* place the children in link lists - bigger elements tend to be last */ + /* --------------------------------------------------------------------- */ + + for (j = nn-1 ; j >= 0 ; j--) + { + if (Nv [j] > 0) + { + /* this is an element */ + parent = Parent [j] ; + if (parent != EMPTY) + { + /* place the element in link list of the children its parent */ + /* bigger elements will tend to be at the end of the list */ + Sibling [j] = Child [parent] ; + Child [parent] = j ; + } + } + } + +#ifndef NDEBUG + { + Int nels, ff, nchild ; + AMD_DEBUG1 (("\n\n================================ AMD_postorder:\n")); + nels = 0 ; + for (j = 0 ; j < nn ; j++) + { + if (Nv [j] > 0) + { + AMD_DEBUG1 (( ""ID" : nels "ID" npiv "ID" size "ID + " parent "ID" maxfr "ID"\n", j, nels, + Nv [j], Fsize [j], Parent [j], Fsize [j])) ; + /* this is an element */ + /* dump the link list of children */ + nchild = 0 ; + AMD_DEBUG1 ((" Children: ")) ; + for (ff = Child [j] ; ff != EMPTY ; ff = Sibling [ff]) + { + AMD_DEBUG1 ((ID" ", ff)) ; + ASSERT (Parent [ff] == j) ; + nchild++ ; + ASSERT (nchild < nn) ; + } + AMD_DEBUG1 (("\n")) ; + parent = Parent [j] ; + if (parent != EMPTY) + { + ASSERT (Nv [parent] > 0) ; + } + nels++ ; + } + } + } + AMD_DEBUG1 (("\n\nGo through the children of each node, and put\n" + "the biggest child last in each list:\n")) ; +#endif + + /* --------------------------------------------------------------------- */ + /* place the largest child last in the list of children for each node */ + /* --------------------------------------------------------------------- */ + + for (i = 0 ; i < nn ; i++) + { + if (Nv [i] > 0 && Child [i] != EMPTY) + { + +#ifndef NDEBUG + Int nchild ; + AMD_DEBUG1 (("Before partial sort, element "ID"\n", i)) ; + nchild = 0 ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (f >= 0 && f < nn) ; + AMD_DEBUG1 ((" f: "ID" size: "ID"\n", f, Fsize [f])) ; + nchild++ ; + ASSERT (nchild <= nn) ; + } +#endif + + /* find the biggest element in the child list */ + fprev = EMPTY ; + maxfrsize = EMPTY ; + bigfprev = EMPTY ; + bigf = EMPTY ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (f >= 0 && f < nn) ; + frsize = Fsize [f] ; + if (frsize >= maxfrsize) + { + /* this is the biggest seen so far */ + maxfrsize = frsize ; + bigfprev = fprev ; + bigf = f ; + } + fprev = f ; + } + ASSERT (bigf != EMPTY) ; + + fnext = Sibling [bigf] ; + + AMD_DEBUG1 (("bigf "ID" maxfrsize "ID" bigfprev "ID" fnext "ID + " fprev " ID"\n", bigf, maxfrsize, bigfprev, fnext, fprev)) ; + + if (fnext != EMPTY) + { + /* if fnext is EMPTY then bigf is already at the end of list */ + + if (bigfprev == EMPTY) + { + /* delete bigf from the element of the list */ + Child [i] = fnext ; + } + else + { + /* delete bigf from the middle of the list */ + Sibling [bigfprev] = fnext ; + } + + /* put bigf at the end of the list */ + Sibling [bigf] = EMPTY ; + ASSERT (Child [i] != EMPTY) ; + ASSERT (fprev != bigf) ; + ASSERT (fprev != EMPTY) ; + Sibling [fprev] = bigf ; + } + +#ifndef NDEBUG + AMD_DEBUG1 (("After partial sort, element "ID"\n", i)) ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (f >= 0 && f < nn) ; + AMD_DEBUG1 ((" "ID" "ID"\n", f, Fsize [f])) ; + ASSERT (Nv [f] > 0) ; + nchild-- ; + } + ASSERT (nchild == 0) ; +#endif + + } + } + + /* --------------------------------------------------------------------- */ + /* postorder the assembly tree */ + /* --------------------------------------------------------------------- */ + + for (i = 0 ; i < nn ; i++) + { + Order [i] = EMPTY ; + } + + k = 0 ; + + for (i = 0 ; i < nn ; i++) + { + if (Parent [i] == EMPTY && Nv [i] > 0) + { + AMD_DEBUG1 (("Root of assembly tree "ID"\n", i)) ; + k = AMD_post_tree (i, k, Child, Sibling, Order, Stack +#ifndef NDEBUG + , nn +#endif + ) ; + } + } +} diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_preprocess.c b/resources/3rdparty/glpk-4.53/src/amd/amd_preprocess.c new file mode 100644 index 000000000..fc223fb51 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_preprocess.c @@ -0,0 +1,119 @@ +/* ========================================================================= */ +/* === AMD_preprocess ====================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Sorts, removes duplicate entries, and transposes from the nonzero pattern of + * a column-form matrix A, to obtain the matrix R. The input matrix can have + * duplicate entries and/or unsorted columns (AMD_valid (n,Ap,Ai) must not be + * AMD_INVALID). + * + * This input condition is NOT checked. This routine is not user-callable. + */ + +#include "amd_internal.h" + +/* ========================================================================= */ +/* === AMD_preprocess ====================================================== */ +/* ========================================================================= */ + +/* AMD_preprocess does not check its input for errors or allocate workspace. + * On input, the condition (AMD_valid (n,n,Ap,Ai) != AMD_INVALID) must hold. + */ + +GLOBAL void AMD_preprocess +( + Int n, /* input matrix: A is n-by-n */ + const Int Ap [ ], /* size n+1 */ + const Int Ai [ ], /* size nz = Ap [n] */ + + /* output matrix R: */ + Int Rp [ ], /* size n+1 */ + Int Ri [ ], /* size nz (or less, if duplicates present) */ + + Int W [ ], /* workspace of size n */ + Int Flag [ ] /* workspace of size n */ +) +{ + + /* --------------------------------------------------------------------- */ + /* local variables */ + /* --------------------------------------------------------------------- */ + + Int i, j, p, p2 ; + + ASSERT (AMD_valid (n, n, Ap, Ai) != AMD_INVALID) ; + + /* --------------------------------------------------------------------- */ + /* count the entries in each row of A (excluding duplicates) */ + /* --------------------------------------------------------------------- */ + + for (i = 0 ; i < n ; i++) + { + W [i] = 0 ; /* # of nonzeros in row i (excl duplicates) */ + Flag [i] = EMPTY ; /* Flag [i] = j if i appears in column j */ + } + for (j = 0 ; j < n ; j++) + { + p2 = Ap [j+1] ; + for (p = Ap [j] ; p < p2 ; p++) + { + i = Ai [p] ; + if (Flag [i] != j) + { + /* row index i has not yet appeared in column j */ + W [i]++ ; /* one more entry in row i */ + Flag [i] = j ; /* flag row index i as appearing in col j*/ + } + } + } + + /* --------------------------------------------------------------------- */ + /* compute the row pointers for R */ + /* --------------------------------------------------------------------- */ + + Rp [0] = 0 ; + for (i = 0 ; i < n ; i++) + { + Rp [i+1] = Rp [i] + W [i] ; + } + for (i = 0 ; i < n ; i++) + { + W [i] = Rp [i] ; + Flag [i] = EMPTY ; + } + + /* --------------------------------------------------------------------- */ + /* construct the row form matrix R */ + /* --------------------------------------------------------------------- */ + + /* R = row form of pattern of A */ + for (j = 0 ; j < n ; j++) + { + p2 = Ap [j+1] ; + for (p = Ap [j] ; p < p2 ; p++) + { + i = Ai [p] ; + if (Flag [i] != j) + { + /* row index i has not yet appeared in column j */ + Ri [W [i]++] = j ; /* put col j in row i */ + Flag [i] = j ; /* flag row index i as appearing in col j*/ + } + } + } + +#ifndef NDEBUG + ASSERT (AMD_valid (n, n, Rp, Ri) == AMD_OK) ; + for (j = 0 ; j < n ; j++) + { + ASSERT (W [j] == Rp [j+1]) ; + } +#endif +} diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_valid.c b/resources/3rdparty/glpk-4.53/src/amd/amd_valid.c new file mode 100644 index 000000000..e9e2e5ab6 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/amd/amd_valid.c @@ -0,0 +1,93 @@ +/* ========================================================================= */ +/* === AMD_valid =========================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Check if a column-form matrix is valid or not. The matrix A is + * n_row-by-n_col. The row indices of entries in column j are in + * Ai [Ap [j] ... Ap [j+1]-1]. Required conditions are: + * + * n_row >= 0 + * n_col >= 0 + * nz = Ap [n_col] >= 0 number of entries in the matrix + * Ap [0] == 0 + * Ap [j] <= Ap [j+1] for all j in the range 0 to n_col. + * Ai [0 ... nz-1] must be in the range 0 to n_row-1. + * + * If any of the above conditions hold, AMD_INVALID is returned. If the + * following condition holds, AMD_OK_BUT_JUMBLED is returned (a warning, + * not an error): + * + * row indices in Ai [Ap [j] ... Ap [j+1]-1] are not sorted in ascending + * order, and/or duplicate entries exist. + * + * Otherwise, AMD_OK is returned. + * + * In v1.2 and earlier, this function returned TRUE if the matrix was valid + * (now returns AMD_OK), or FALSE otherwise (now returns AMD_INVALID or + * AMD_OK_BUT_JUMBLED). + */ + +#include "amd_internal.h" + +GLOBAL Int AMD_valid +( + /* inputs, not modified on output: */ + Int n_row, /* A is n_row-by-n_col */ + Int n_col, + const Int Ap [ ], /* column pointers of A, of size n_col+1 */ + const Int Ai [ ] /* row indices of A, of size nz = Ap [n_col] */ +) +{ + Int nz, j, p1, p2, ilast, i, p, result = AMD_OK ; + + if (n_row < 0 || n_col < 0 || Ap == NULL || Ai == NULL) + { + return (AMD_INVALID) ; + } + nz = Ap [n_col] ; + if (Ap [0] != 0 || nz < 0) + { + /* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */ + AMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ; + return (AMD_INVALID) ; + } + for (j = 0 ; j < n_col ; j++) + { + p1 = Ap [j] ; + p2 = Ap [j+1] ; + AMD_DEBUG2 (("\nColumn: "ID" p1: "ID" p2: "ID"\n", j, p1, p2)) ; + if (p1 > p2) + { + /* column pointers must be ascending */ + AMD_DEBUG0 (("column "ID" pointer bad\n", j)) ; + return (AMD_INVALID) ; + } + ilast = EMPTY ; + for (p = p1 ; p < p2 ; p++) + { + i = Ai [p] ; + AMD_DEBUG3 (("row: "ID"\n", i)) ; + if (i < 0 || i >= n_row) + { + /* row index out of range */ + AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)); + return (AMD_INVALID) ; + } + if (i <= ilast) + { + /* row index unsorted, or duplicate entry present */ + AMD_DEBUG1 (("index unsorted/dupl col "ID" row "ID"\n", j, i)); + result = AMD_OK_BUT_JUMBLED ; + } + ilast = i ; + } + } + return (result) ; +} diff --git a/resources/3rdparty/glpk-4.53/src/avl.c b/resources/3rdparty/glpk-4.53/src/avl.c new file mode 100644 index 000000000..c9b7f2203 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/avl.c @@ -0,0 +1,406 @@ +/* avl.c (binary search tree) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "avl.h" +#include "dmp.h" +#include "env.h" + +struct AVL +{ /* AVL tree (Adelson-Velsky & Landis binary search tree) */ + DMP *pool; + /* memory pool for allocating nodes */ + AVLNODE *root; + /* pointer to the root node */ + int (*fcmp)(void *info, const void *key1, const void *key2); + /* application-defined key comparison routine */ + void *info; + /* transit pointer passed to the routine fcmp */ + int size; + /* the tree size (the total number of nodes) */ + int height; + /* the tree height */ +}; + +struct AVLNODE +{ /* node of AVL tree */ + const void *key; + /* pointer to the node key (data structure for representing keys + is supplied by the application) */ + int rank; + /* node rank = relative position of the node in its own subtree = + the number of nodes in the left subtree plus one */ + int type; + /* reserved for the application specific information */ + void *link; + /* reserved for the application specific information */ + AVLNODE *up; + /* pointer to the parent node */ + short int flag; + /* node flag: + 0 - this node is the left child of its parent (or this node is + the root of the tree and has no parent) + 1 - this node is the right child of its parent */ + short int bal; + /* node balance = the difference between heights of the right and + left subtrees: + -1 - the left subtree is higher than the right one; + 0 - the left and right subtrees have the same height; + +1 - the left subtree is lower than the right one */ + AVLNODE *left; + /* pointer to the root of the left subtree */ + AVLNODE *right; + /* pointer to the root of the right subtree */ +}; + +AVL *avl_create_tree(int (*fcmp)(void *info, const void *key1, + const void *key2), void *info) +{ /* create AVL tree */ + AVL *tree; + tree = xmalloc(sizeof(AVL)); + tree->pool = dmp_create_pool(); + tree->root = NULL; + tree->fcmp = fcmp; + tree->info = info; + tree->size = 0; + tree->height = 0; + return tree; +} + +int avl_strcmp(void *info, const void *key1, const void *key2) +{ /* compare character string keys */ + xassert(info == info); + return strcmp(key1, key2); +} + +static AVLNODE *rotate_subtree(AVL *tree, AVLNODE *node); + +AVLNODE *avl_insert_node(AVL *tree, const void *key) +{ /* insert new node into AVL tree */ + AVLNODE *p, *q, *r; + short int flag; + /* find an appropriate point for insertion */ + p = NULL; q = tree->root; + while (q != NULL) + { p = q; + if (tree->fcmp(tree->info, key, p->key) <= 0) + { flag = 0; + q = p->left; + p->rank++; + } + else + { flag = 1; + q = p->right; + } + } + /* create new node and insert it into the tree */ + r = dmp_get_atom(tree->pool, sizeof(AVLNODE)); + r->key = key; r->type = 0; r->link = NULL; + r->rank = 1; r->up = p; + r->flag = (short int)(p == NULL ? 0 : flag); + r->bal = 0; r->left = NULL; r->right = NULL; + tree->size++; + if (p == NULL) + tree->root = r; + else + if (flag == 0) p->left = r; else p->right = r; + /* go upstairs to the root and correct all subtrees affected by + insertion */ + while (p != NULL) + { if (flag == 0) + { /* the height of the left subtree of [p] is increased */ + if (p->bal > 0) + { p->bal = 0; + break; + } + if (p->bal < 0) + { rotate_subtree(tree, p); + break; + } + p->bal = -1; flag = p->flag; p = p->up; + } + else + { /* the height of the right subtree of [p] is increased */ + if (p->bal < 0) + { p->bal = 0; + break; + } + if (p->bal > 0) + { rotate_subtree(tree, p); + break; + } + p->bal = +1; flag = p->flag; p = p->up; + } + } + /* if the root has been reached, the height of the entire tree is + increased */ + if (p == NULL) tree->height++; + return r; +} + +void avl_set_node_type(AVLNODE *node, int type) +{ /* assign the type field of specified node */ + node->type = type; + return; +} + +void avl_set_node_link(AVLNODE *node, void *link) +{ /* assign the link field of specified node */ + node->link = link; + return; +} + +AVLNODE *avl_find_node(AVL *tree, const void *key) +{ /* find node in AVL tree */ + AVLNODE *p; + int c; + p = tree->root; + while (p != NULL) + { c = tree->fcmp(tree->info, key, p->key); + if (c == 0) break; + p = (c < 0 ? p->left : p->right); + } + return p; +} + +int avl_get_node_type(AVLNODE *node) +{ /* retrieve the type field of specified node */ + return node->type; +} + +void *avl_get_node_link(AVLNODE *node) +{ /* retrieve the link field of specified node */ + return node->link; +} + +static AVLNODE *find_next_node(AVL *tree, AVLNODE *node) +{ /* find next node in AVL tree */ + AVLNODE *p, *q; + if (tree->root == NULL) return NULL; + p = node; + q = (p == NULL ? tree->root : p->right); + if (q == NULL) + { /* go upstairs from the left subtree */ + for (;;) + { q = p->up; + if (q == NULL) break; + if (p->flag == 0) break; + p = q; + } + } + else + { /* go downstairs into the right subtree */ + for (;;) + { p = q->left; + if (p == NULL) break; + q = p; + } + } + return q; +} + +void avl_delete_node(AVL *tree, AVLNODE *node) +{ /* delete specified node from AVL tree */ + AVLNODE *f, *p, *q, *r, *s, *x, *y; + short int flag; + p = node; + /* if both subtrees of the specified node are non-empty, the node + should be interchanged with the next one, at least one subtree + of which is always empty */ + if (p->left == NULL || p->right == NULL) goto skip; + f = p->up; q = p->left; + r = find_next_node(tree, p); s = r->right; + if (p->right == r) + { if (f == NULL) + tree->root = r; + else + if (p->flag == 0) f->left = r; else f->right = r; + r->rank = p->rank; r->up = f; + r->flag = p->flag; r->bal = p->bal; + r->left = q; r->right = p; + q->up = r; + p->rank = 1; p->up = r; p->flag = 1; + p->bal = (short int)(s == NULL ? 0 : +1); + p->left = NULL; p->right = s; + if (s != NULL) s->up = p; + } + else + { x = p->right; y = r->up; + if (f == NULL) + tree->root = r; + else + if (p->flag == 0) f->left = r; else f->right = r; + r->rank = p->rank; r->up = f; + r->flag = p->flag; r->bal = p->bal; + r->left = q; r->right = x; + q->up = r; x->up = r; y->left = p; + p->rank = 1; p->up = y; p->flag = 0; + p->bal = (short int)(s == NULL ? 0 : +1); + p->left = NULL; p->right = s; + if (s != NULL) s->up = p; + } +skip: /* now the specified node [p] has at least one empty subtree; + go upstairs to the root and adjust the rank field of all nodes + affected by deletion */ + q = p; f = q->up; + while (f != NULL) + { if (q->flag == 0) f->rank--; + q = f; f = q->up; + } + /* delete the specified node from the tree */ + f = p->up; flag = p->flag; + q = p->left != NULL ? p->left : p->right; + if (f == NULL) + tree->root = q; + else + if (flag == 0) f->left = q; else f->right = q; + if (q != NULL) q->up = f, q->flag = flag; + tree->size--; + /* go upstairs to the root and correct all subtrees affected by + deletion */ + while (f != NULL) + { if (flag == 0) + { /* the height of the left subtree of [f] is decreased */ + if (f->bal == 0) + { f->bal = +1; + break; + } + if (f->bal < 0) + f->bal = 0; + else + { f = rotate_subtree(tree, f); + if (f->bal < 0) break; + } + flag = f->flag; f = f->up; + } + else + { /* the height of the right subtree of [f] is decreased */ + if (f->bal == 0) + { f->bal = -1; + break; + } + if (f->bal > 0) + f->bal = 0; + else + { f = rotate_subtree(tree, f); + if (f->bal > 0) break; + } + flag = f->flag; f = f->up; + } + } + /* if the root has been reached, the height of the entire tree is + decreased */ + if (f == NULL) tree->height--; + /* returns the deleted node to the memory pool */ + dmp_free_atom(tree->pool, p, sizeof(AVLNODE)); + return; +} + +static AVLNODE *rotate_subtree(AVL *tree, AVLNODE *node) +{ /* restore balance of AVL subtree */ + AVLNODE *f, *p, *q, *r, *x, *y; + xassert(node != NULL); + p = node; + if (p->bal < 0) + { /* perform negative (left) rotation */ + f = p->up; q = p->left; r = q->right; + if (q->bal <= 0) + { /* perform single negative rotation */ + if (f == NULL) + tree->root = q; + else + if (p->flag == 0) f->left = q; else f->right = q; + p->rank -= q->rank; + q->up = f; q->flag = p->flag; q->bal++; q->right = p; + p->up = q; p->flag = 1; + p->bal = (short int)(-q->bal); p->left = r; + if (r != NULL) r->up = p, r->flag = 0; + node = q; + } + else + { /* perform double negative rotation */ + x = r->left; y = r->right; + if (f == NULL) + tree->root = r; + else + if (p->flag == 0) f->left = r; else f->right = r; + p->rank -= (q->rank + r->rank); + r->rank += q->rank; + p->bal = (short int)(r->bal >= 0 ? 0 : +1); + q->bal = (short int)(r->bal <= 0 ? 0 : -1); + r->up = f; r->flag = p->flag; r->bal = 0; + r->left = q; r->right = p; + p->up = r; p->flag = 1; p->left = y; + q->up = r; q->flag = 0; q->right = x; + if (x != NULL) x->up = q, x->flag = 1; + if (y != NULL) y->up = p, y->flag = 0; + node = r; + } + } + else + { /* perform positive (right) rotation */ + f = p->up; q = p->right; r = q->left; + if (q->bal >= 0) + { /* perform single positive rotation */ + if (f == NULL) + tree->root = q; + else + if (p->flag == 0) f->left = q; else f->right = q; + q->rank += p->rank; + q->up = f; q->flag = p->flag; q->bal--; q->left = p; + p->up = q; p->flag = 0; + p->bal = (short int)(-q->bal); p->right = r; + if (r != NULL) r->up = p, r->flag = 1; + node = q; + } + else + { /* perform double positive rotation */ + x = r->left; y = r->right; + if (f == NULL) + tree->root = r; + else + if (p->flag == 0) f->left = r; else f->right = r; + q->rank -= r->rank; + r->rank += p->rank; + p->bal = (short int)(r->bal <= 0 ? 0 : -1); + q->bal = (short int)(r->bal >= 0 ? 0 : +1); + r->up = f; r->flag = p->flag; r->bal = 0; + r->left = p; r->right = q; + p->up = r; p->flag = 0; p->right = x; + q->up = r; q->flag = 1; q->left = y; + if (x != NULL) x->up = p, x->flag = 1; + if (y != NULL) y->up = q, y->flag = 0; + node = r; + } + } + return node; +} + +void avl_delete_tree(AVL *tree) +{ /* delete AVL tree */ + dmp_delete_pool(tree->pool); + xfree(tree); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/avl.h b/resources/3rdparty/glpk-4.53/src/avl.h new file mode 100644 index 000000000..c4144c293 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/avl.h @@ -0,0 +1,74 @@ +/* avl.h (binary search tree) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef AVL_H +#define AVL_H + +typedef struct AVL AVL; +typedef struct AVLNODE AVLNODE; + +#define avl_create_tree _glp_avl_create_tree +AVL *avl_create_tree(int (*fcmp)(void *info, const void *key1, + const void *key2), void *info); +/* create AVL tree */ + +#define avl_strcmp _glp_avl_strcmp +int avl_strcmp(void *info, const void *key1, const void *key2); +/* compare character string keys */ + +#define avl_insert_node _glp_avl_insert_node +AVLNODE *avl_insert_node(AVL *tree, const void *key); +/* insert new node into AVL tree */ + +#define avl_set_node_type _glp_avl_set_node_type +void avl_set_node_type(AVLNODE *node, int type); +/* assign the type field of specified node */ + +#define avl_set_node_link _glp_avl_set_node_link +void avl_set_node_link(AVLNODE *node, void *link); +/* assign the link field of specified node */ + +#define avl_find_node _glp_avl_find_node +AVLNODE *avl_find_node(AVL *tree, const void *key); +/* find node in AVL tree */ + +#define avl_get_node_type _glp_avl_get_node_type +int avl_get_node_type(AVLNODE *node); +/* retrieve the type field of specified node */ + +#define avl_get_node_link _glp_avl_get_node_link +void *avl_get_node_link(AVLNODE *node); +/* retrieve the link field of specified node */ + +#define avl_delete_node _glp_avl_delete_node +void avl_delete_node(AVL *tree, AVLNODE *node); +/* delete specified node from AVL tree */ + +#define avl_delete_tree _glp_avl_delete_tree +void avl_delete_tree(AVL *tree); +/* delete AVL tree */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bfd.c b/resources/3rdparty/glpk-4.53/src/bfd.c new file mode 100644 index 000000000..2ce5dcd37 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bfd.c @@ -0,0 +1,576 @@ +/* bfd.c (LP basis factorization driver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#if 0 /* 27/IV-2013 */ +#include "glpfhv.h" +#else +#include "fhvint.h" +#endif +#include "glplpf.h" +#include "prob.h" + +/* CAUTION: DO NOT CHANGE THE LIMIT BELOW */ + +#define M_MAX 100000000 /* = 100*10^6 */ +/* maximal order of the basis matrix */ + +struct BFD +{ /* LP basis factorization */ + int valid; + /* factorization is valid only if this flag is set */ + int type; + /* factorization type: + GLP_BF_FT - LUF + Forrest-Tomlin + GLP_BF_BG - LUF + Schur compl. + Bartels-Golub + GLP_BF_GR - LUF + Schur compl. + Givens rotation */ +#if 0 /* 27/IV-2013 */ + FHV *fhv; + /* LP basis factorization (GLP_BF_FT) */ +#else + FHVINT *fi; + /* interface to FHV-factorization (GLP_BF_FT) */ +#endif + LPF *lpf; + /* LP basis factorization (GLP_BF_BG, GLP_BF_GR) */ + int lu_size; /* luf.sv_size */ + double piv_tol; /* luf.piv_tol */ + int piv_lim; /* luf.piv_lim */ + int suhl; /* luf.suhl */ + double eps_tol; /* luf.eps_tol */ + double max_gro; /* luf.max_gro */ + int nfs_max; /* fhv.hh_max */ + double upd_tol; /* fhv.upd_tol */ + int nrs_max; /* lpf.n_max */ + int rs_size; /* lpf.v_size */ + /* internal control parameters */ + int upd_lim; + /* the factorization update limit */ + int upd_cnt; + /* the factorization update count */ +}; + +/*********************************************************************** +* NAME +* +* bfd_create_it - create LP basis factorization +* +* SYNOPSIS +* +* #include "glpbfd.h" +* BFD *bfd_create_it(void); +* +* DESCRIPTION +* +* The routine bfd_create_it creates a program object, which represents +* a factorization of LP basis. +* +* RETURNS +* +* The routine bfd_create_it returns a pointer to the object created. */ + +BFD *bfd_create_it(void) +{ BFD *bfd; + bfd = xmalloc(sizeof(BFD)); + bfd->valid = 0; + bfd->type = GLP_BF_FT; +#if 0 /* 27/IV-2013 */ + bfd->fhv = NULL; +#else + bfd->fi = NULL; +#endif + bfd->lpf = NULL; + bfd->lu_size = 0; + bfd->piv_tol = 0.10; + bfd->piv_lim = 4; + bfd->suhl = 1; + bfd->eps_tol = 1e-15; + bfd->max_gro = 1e+10; + bfd->nfs_max = 100; + bfd->upd_tol = 1e-6; + bfd->nrs_max = 100; + bfd->rs_size = 1000; + bfd->upd_lim = -1; + bfd->upd_cnt = 0; + return bfd; +} + +/**********************************************************************/ + +void bfd_set_parm(BFD *bfd, const void *_parm) +{ /* change LP basis factorization control parameters */ + const glp_bfcp *parm = _parm; + xassert(bfd != NULL); + bfd->type = parm->type; + bfd->lu_size = parm->lu_size; + bfd->piv_tol = parm->piv_tol; + bfd->piv_lim = parm->piv_lim; + bfd->suhl = parm->suhl; + bfd->eps_tol = parm->eps_tol; + bfd->max_gro = parm->max_gro; + bfd->nfs_max = parm->nfs_max; + bfd->upd_tol = parm->upd_tol; + bfd->nrs_max = parm->nrs_max; + bfd->rs_size = parm->rs_size; + return; +} + +/*********************************************************************** +* NAME +* +* bfd_factorize - compute LP basis factorization +* +* SYNOPSIS +* +* #include "glpbfd.h" +* int bfd_factorize(BFD *bfd, int m, int bh[], int (*col)(void *info, +* int j, int ind[], double val[]), void *info); +* +* DESCRIPTION +* +* The routine bfd_factorize computes the factorization of the basis +* matrix B specified by the routine col. +* +* The parameter bfd specified the basis factorization data structure +* created with the routine bfd_create_it. +* +* The parameter m specifies the order of B, m > 0. +* +* The array bh specifies the basis header: bh[j], 1 <= j <= m, is the +* number of j-th column of B in some original matrix. The array bh is +* optional and can be specified as NULL. +* +* The formal routine col specifies the matrix B to be factorized. To +* obtain j-th column of A the routine bfd_factorize calls the routine +* col with the parameter j (1 <= j <= n). In response the routine col +* should store row indices and numerical values of non-zero elements +* of j-th column of B to locations ind[1,...,len] and val[1,...,len], +* respectively, where len is the number of non-zeros in j-th column +* returned on exit. Neither zero nor duplicate elements are allowed. +* +* The parameter info is a transit pointer passed to the routine col. +* +* RETURNS +* +* 0 The factorization has been successfully computed. +* +* BFD_ESING +* The specified matrix is singular within the working precision. +* +* BFD_ECOND +* The specified matrix is ill-conditioned. +* +* For more details see comments to the routine luf_factorize. */ + +int bfd_factorize(BFD *bfd, int m, const int bh[], int (*col) + (void *info, int j, int ind[], double val[]), void *info) +#if 0 /* 06/VI-2013 */ +{ LUF *luf; +#else +{ +#endif + int nov, ret; + xassert(bfd != NULL); + xassert(1 <= m && m <= M_MAX); + /* invalidate the factorization */ + bfd->valid = 0; + /* create the factorization, if necessary */ + nov = 0; + switch (bfd->type) + { case GLP_BF_FT: + if (bfd->lpf != NULL) + lpf_delete_it(bfd->lpf), bfd->lpf = NULL; +#if 0 /* 27/IV-2013 */ + if (bfd->fhv == NULL) + bfd->fhv = fhv_create_it(), nov = 1; +#else + if (bfd->fi == NULL) + bfd->fi = fhvint_create(), nov = 1; +#endif + break; + case GLP_BF_BG: + case GLP_BF_GR: +#if 0 /* 27/IV-2013 */ + if (bfd->fhv != NULL) + fhv_delete_it(bfd->fhv), bfd->fhv = NULL; +#else + if (bfd->fi != NULL) + fhvint_delete(bfd->fi), bfd->fi = NULL; +#endif + if (bfd->lpf == NULL) + bfd->lpf = lpf_create_it(), nov = 1; + break; + default: + xassert(bfd != bfd); + } +#if 0 /* 06/VI-2013 */ + /* set control parameters specific to LUF */ +#if 0 /* 27/IV-2013 */ + if (bfd->fhv != NULL) + luf = bfd->fhv->luf; +#else + if (bfd->fi != NULL) + goto skip; +#endif + else if (bfd->lpf != NULL) + luf = bfd->lpf->luf; + else + xassert(bfd != bfd); + if (nov) luf->new_sva = bfd->lu_size; + luf->piv_tol = bfd->piv_tol; + luf->piv_lim = bfd->piv_lim; + luf->suhl = bfd->suhl; + luf->eps_tol = bfd->eps_tol; + luf->max_gro = bfd->max_gro; +#endif +#if 0 /* 27/IV-2013 */ + /* set control parameters specific to FHV */ + if (bfd->fhv != NULL) + { if (nov) bfd->fhv->hh_max = bfd->nfs_max; + bfd->fhv->upd_tol = bfd->upd_tol; + } +#endif + /* set control parameters specific to LPF */ + if (bfd->lpf != NULL) + { if (nov) bfd->lpf->n_max = bfd->nrs_max; + if (nov) bfd->lpf->v_size = bfd->rs_size; + } +#if 0 /* 27/IV-2013 */ + /* try to factorize the basis matrix */ + if (bfd->fhv != NULL) + { switch (fhv_factorize(bfd->fhv, m, col, info)) + { case 0: + break; + case FHV_ESING: + ret = BFD_ESING; + goto done; + case FHV_ECOND: + ret = BFD_ECOND; + goto done; + default: + xassert(bfd != bfd); + } + } +#else +skip: /* try to factorize the basis matrix */ + if (bfd->fi != NULL) + { /* FIXME */ + if (fhvint_factorize(bfd->fi, m, col, info) != 0) + { ret = BFD_ESING; + goto done; + } + /* printf("*** FACTORIZED; m = %d ***\n", m); */ + } +#endif + else if (bfd->lpf != NULL) + { switch (lpf_factorize(bfd->lpf, m, bh, col, info)) + { case 0: + /* set the Schur complement update type */ + switch (bfd->type) + { case GLP_BF_BG: + /* Bartels-Golub update */ +#if 0 /* 11/VIII-2013 */ + bfd->lpf->scf->t_opt = SCF_TBG; +#else + bfd->lpf->t_opt = SCF_TBG; +#endif + break; + case GLP_BF_GR: + /* Givens rotations update */ +#if 0 /* 11/VIII-2013 */ + bfd->lpf->scf->t_opt = SCF_TGR; +#else + bfd->lpf->t_opt = SCF_TGR; +#endif + break; + default: + xassert(bfd != bfd); + } + break; + case LPF_ESING: + ret = BFD_ESING; + goto done; + case LPF_ECOND: + ret = BFD_ECOND; + goto done; + default: + xassert(bfd != bfd); + } + } + else + xassert(bfd != bfd); + /* the basis matrix has been successfully factorized */ + bfd->valid = 1; + bfd->upd_cnt = 0; + ret = 0; +done: /* return to the calling program */ + return ret; +} + +/*********************************************************************** +* NAME +* +* bfd_ftran - perform forward transformation (solve system B*x = b) +* +* SYNOPSIS +* +* #include "glpbfd.h" +* void bfd_ftran(BFD *bfd, double x[]); +* +* DESCRIPTION +* +* The routine bfd_ftran performs forward transformation, i.e. solves +* the system B*x = b, where B is the basis matrix, x is the vector of +* unknowns to be computed, b is the vector of right-hand sides. +* +* On entry elements of the vector b should be stored in dense format +* in locations x[1], ..., x[m], where m is the number of rows. On exit +* the routine stores elements of the vector x in the same locations. */ + +void bfd_ftran(BFD *bfd, double x[]) +{ xassert(bfd != NULL); + xassert(bfd->valid); +#if 0 /* 27/IV-2013 */ + if (bfd->fhv != NULL) + fhv_ftran(bfd->fhv, x); +#else + if (bfd->fi != NULL) + fhvint_ftran(bfd->fi, x); +#endif + else if (bfd->lpf != NULL) + lpf_ftran(bfd->lpf, x); + else + xassert(bfd != bfd); + return; +} + +/*********************************************************************** +* NAME +* +* bfd_btran - perform backward transformation (solve system B'*x = b) +* +* SYNOPSIS +* +* #include "glpbfd.h" +* void bfd_btran(BFD *bfd, double x[]); +* +* DESCRIPTION +* +* The routine bfd_btran performs backward transformation, i.e. solves +* the system B'*x = b, where B' is a matrix transposed to the basis +* matrix B, x is the vector of unknowns to be computed, b is the vector +* of right-hand sides. +* +* On entry elements of the vector b should be stored in dense format +* in locations x[1], ..., x[m], where m is the number of rows. On exit +* the routine stores elements of the vector x in the same locations. */ + +void bfd_btran(BFD *bfd, double x[]) +{ xassert(bfd != NULL); + xassert(bfd->valid); +#if 0 /* 27/IV-2013 */ + if (bfd->fhv != NULL) + fhv_btran(bfd->fhv, x); +#else + if (bfd->fi != NULL) + fhvint_btran(bfd->fi, x); +#endif + else if (bfd->lpf != NULL) + lpf_btran(bfd->lpf, x); + else + xassert(bfd != bfd); + return; +} + +/*********************************************************************** +* NAME +* +* bfd_update_it - update LP basis factorization +* +* SYNOPSIS +* +* #include "glpbfd.h" +* int bfd_update_it(BFD *bfd, int j, int bh, int len, const int ind[], +* const double val[]); +* +* DESCRIPTION +* +* The routine bfd_update_it updates the factorization of the basis +* matrix B after replacing its j-th column by a new vector. +* +* The parameter j specifies the number of column of B, which has been +* replaced, 1 <= j <= m, where m is the order of B. +* +* The parameter bh specifies the basis header entry for the new column +* of B, which is the number of the new column in some original matrix. +* This parameter is optional and can be specified as 0. +* +* Row indices and numerical values of non-zero elements of the new +* column of B should be placed in locations ind[1], ..., ind[len] and +* val[1], ..., val[len], resp., where len is the number of non-zeros +* in the column. Neither zero nor duplicate elements are allowed. +* +* RETURNS +* +* 0 The factorization has been successfully updated. +* +* BFD_ESING +* New basis matrix is singular within the working precision. +* +* BFD_ECHECK +* The factorization is inaccurate. +* +* BFD_ELIMIT +* Factorization update limit has been reached. +* +* BFD_EROOM +* Overflow of the sparse vector area. +* +* In case of non-zero return code the factorization becomes invalid. +* It should not be used until it has been recomputed with the routine +* bfd_factorize. */ + +int bfd_update_it(BFD *bfd, int j, int bh, int len, const int ind[], + const double val[]) +{ int ret; + xassert(bfd != NULL); + xassert(bfd->valid); + /* try to update the factorization */ +#if 0 /* 27/IV-2013 */ + if (bfd->fhv != NULL) + { switch (fhv_update_it(bfd->fhv, j, len, ind, val)) + { case 0: + break; + case FHV_ESING: + bfd->valid = 0; + ret = BFD_ESING; + goto done; + case FHV_ECHECK: + bfd->valid = 0; + ret = BFD_ECHECK; + goto done; + case FHV_ELIMIT: + bfd->valid = 0; + ret = BFD_ELIMIT; + goto done; + case FHV_EROOM: + bfd->valid = 0; + ret = BFD_EROOM; + goto done; + default: + xassert(bfd != bfd); + } + } +#else + if (bfd->fi != NULL) + { /* see fhv_ft_update for return codes */ + switch (fhvint_update(bfd->fi, j, len, ind, val)) + { case 0: + break; + case 1: + bfd->valid = 0; + ret = BFD_ESING; + goto done; + case 2: + case 3: + case 5: + bfd->valid = 0; + ret = BFD_ECHECK; + goto done; + case 4: + bfd->valid = 0; + ret = BFD_ELIMIT; + goto done; + default: + xassert(bfd != bfd); + } + } +#endif + else if (bfd->lpf != NULL) + { switch (lpf_update_it(bfd->lpf, j, bh, len, ind, val)) + { case 0: + break; + case LPF_ESING: + bfd->valid = 0; + ret = BFD_ESING; + goto done; + case LPF_ELIMIT: + bfd->valid = 0; + ret = BFD_ELIMIT; + goto done; + default: + xassert(bfd != bfd); + } + } + else + xassert(bfd != bfd); + /* the factorization has been successfully updated */ + /* increase the update count */ + bfd->upd_cnt++; + ret = 0; +done: /* return to the calling program */ + return ret; +} + +/**********************************************************************/ + +int bfd_get_count(BFD *bfd) +{ /* determine factorization update count */ + xassert(bfd != NULL); + xassert(bfd->valid); + return bfd->upd_cnt; +} + +/*********************************************************************** +* NAME +* +* bfd_delete_it - delete LP basis factorization +* +* SYNOPSIS +* +* #include "glpbfd.h" +* void bfd_delete_it(BFD *bfd); +* +* DESCRIPTION +* +* The routine bfd_delete_it deletes LP basis factorization specified +* by the parameter fhv and frees all memory allocated to this program +* object. */ + +void bfd_delete_it(BFD *bfd) +{ xassert(bfd != NULL); +#if 0 /* 27/IV-2013 */ + if (bfd->fhv != NULL) + fhv_delete_it(bfd->fhv); +#else + if (bfd->fi != NULL) + fhvint_delete(bfd->fi); +#endif + if (bfd->lpf != NULL) + lpf_delete_it(bfd->lpf); + xfree(bfd); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bfd.h b/resources/3rdparty/glpk-4.53/src/bfd.h new file mode 100644 index 000000000..98f7e44b4 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bfd.h @@ -0,0 +1,73 @@ +/* bfd.h (LP basis factorization driver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef BFD_H +#define BFD_H + +typedef struct BFD BFD; + +/* return codes: */ +#define BFD_ESING 1 /* singular matrix */ +#define BFD_ECOND 2 /* ill-conditioned matrix */ +#define BFD_ECHECK 3 /* insufficient accuracy */ +#define BFD_ELIMIT 4 /* update limit reached */ +#define BFD_EROOM 5 /* SVA overflow */ + +#define bfd_create_it _glp_bfd_create_it +BFD *bfd_create_it(void); +/* create LP basis factorization */ + +#define bfd_set_parm _glp_bfd_set_parm +void bfd_set_parm(BFD *bfd, const void *parm); +/* change LP basis factorization control parameters */ + +#define bfd_factorize _glp_bfd_factorize +int bfd_factorize(BFD *bfd, int m, const int bh[], int (*col) + (void *info, int j, int ind[], double val[]), void *info); +/* compute LP basis factorization */ + +#define bfd_ftran _glp_bfd_ftran +void bfd_ftran(BFD *bfd, double x[]); +/* perform forward transformation (solve system B*x = b) */ + +#define bfd_btran _glp_bfd_btran +void bfd_btran(BFD *bfd, double x[]); +/* perform backward transformation (solve system B'*x = b) */ + +#define bfd_update_it _glp_bfd_update_it +int bfd_update_it(BFD *bfd, int j, int bh, int len, const int ind[], + const double val[]); +/* update LP basis factorization */ + +#define bfd_get_count _glp_bfd_get_count +int bfd_get_count(BFD *bfd); +/* determine factorization update count */ + +#define bfd_delete_it _glp_bfd_delete_it +void bfd_delete_it(BFD *bfd); +/* delete LP basis factorization */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/fhv.c b/resources/3rdparty/glpk-4.53/src/bflib/fhv.c new file mode 100644 index 000000000..271460657 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/fhv.c @@ -0,0 +1,586 @@ +/* fhv.c (sparse updatable FHV-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "fhv.h" + +/*********************************************************************** +* fhv_ft_update - update FHV-factorization (Forrest-Tomlin) +* +* This routine updates FHV-factorization of the original matrix A +* after replacing its j-th column by a new one. The routine is based +* on the method proposed by Forrest and Tomlin [1]. +* +* The parameter q specifies the number of column of A, which has been +* replaced, 1 <= q <= n, where n is the order of A. +* +* Row indices and numerical values of non-zero elements of the new +* j-th column of A should be placed in locations aq_ind[1], ..., +* aq_ind[aq_len] and aq_val[1], ..., aq_val[aq_len], respectively, +* where aq_len is the number of non-zeros. Neither zero nor duplicate +* elements are allowed. +* +* The working arrays ind, val, and work should have at least 1+n +* elements (0-th elements are not used). +* +* RETURNS +* +* 0 The factorization has been successfully updated. +* +* 1 New matrix U = P'* V * Q' is upper triangular with zero diagonal +* element u[s,s]. (Elimination was not performed.) +* +* 2 New matrix U = P'* V * Q' is upper triangular, and its diagonal +* element u[s,s] or u[t,t] is too small in magnitude. (Elimination +* was not performed.) +* +* 3 The same as 2, but after performing elimination. +* +* 4 The factorization has not been updated, because maximal number of +* updates has been reached. +* +* 5 Accuracy test failed for the updated factorization. +* +* BACKGROUND +* +* The routine is based on the updating method proposed by Forrest and +* Tomlin [1]. +* +* Let q-th column of the original matrix A have been replaced by new +* column A[q]. Then, to keep the equality A = F * H * V, q-th column +* of matrix V should be replaced by column V[q] = inv(F * H) * A[q]. +* From the standpoint of matrix U = P'* V * Q' such replacement is +* equivalent to replacement of s-th column of matrix U, where s is +* determined from q by permutation matrix Q. Thus, matrix U loses its +* upper triangular form and becomes the following: +* +* 1 s t n +* 1 x x * x x x x x x +* . x * x x x x x x +* s . . * x x x x x x +* . . * x x x x x x +* . . * . x x x x x +* . . * . . x x x x +* t . . * . . . x x x +* . . . . . . . x x +* n . . . . . . . . x +* +* where t is largest row index of a non-zero element in s-th column. +* +* The routine makes matrix U upper triangular as follows. First, it +* moves rows and columns s+1, ..., t by one position to the left and +* upwards, resp., and moves s-th row and s-th column to position t. +* Due to such symmetric permutations matrix U becomes the following +* (note that all diagonal elements remain on the diagonal, and element +* u[s,s] becomes u[t,t]): +* +* 1 s t n +* 1 x x x x x x * x x +* . x x x x x * x x +* s . . x x x x * x x +* . . . x x x * x x +* . . . . x x * x x +* . . . . . x * x x +* t . . x x x x * x x +* . . . . . . . x x +* n . . . . . . . . x +* +* Then the routine performs gaussian elimination to eliminate +* subdiagonal elements u[t,s], ..., u[t,t-1] using diagonal elements +* u[s,s], ..., u[t-1,t-1] as pivots. During the elimination process +* the routine permutes neither rows nor columns, so only t-th row is +* changed. Should note that actually all operations are performed on +* matrix V = P * U * Q, since matrix U is not stored. +* +* To keep the equality A = F * H * V, the routine appends new row-like +* factor H[k] to matrix H, and every time it applies elementary +* gaussian transformation to eliminate u[t,j'] = v[p,j] using pivot +* u[j',j'] = v[i,j], it also adds new element f[p,j] = v[p,j] / v[i,j] +* (gaussian multiplier) to factor H[k], which initially is a unity +* matrix. At the end of elimination process the row-like factor H[k] +* may look as follows: +* +* 1 n 1 s t n +* 1 1 . . . . . . . . 1 1 . . . . . . . . +* . 1 . . . . . . . . 1 . . . . . . . +* . . 1 . . . . . . s . . 1 . . . . . . +* p . x x 1 . x . x . . . . 1 . . . . . +* . . . . 1 . . . . . . . . 1 . . . . +* . . . . . 1 . . . . . . . . 1 . . . +* . . . . . . 1 . . t . . x x x x 1 . . +* . . . . . . . 1 . . . . . . . . 1 . +* n . . . . . . . . 1 n . . . . . . . . 1 +* +* H[k] inv(P) * H[k] * P +* +* If, however, s = t, no elimination is needed, in which case no new +* row-like factor is created. +* +* REFERENCES +* +* 1. J.J.H.Forrest and J.A.Tomlin, "Updated triangular factors of the +* basis to maintain sparsity in the product form simplex method," +* Math. Prog. 2 (1972), pp. 263-78. */ + +int fhv_ft_update(FHV *fhv, int q, int aq_len, const int aq_ind[], + const double aq_val[], int ind[/*1+n*/], double val[/*1+n*/], + double work[/*1+n*/]) +{ LUF *luf = fhv->luf; + int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int *vr_cap = &sva->cap[vr_ref-1]; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *vc_cap = &sva->cap[vc_ref-1]; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int *hh_ind = fhv->hh_ind; + int hh_ref = fhv->hh_ref; + int *hh_ptr = &sva->ptr[hh_ref-1]; + int *hh_len = &sva->len[hh_ref-1]; +#if 1 /* FIXME */ + const double eps_tol = DBL_EPSILON; + const double vpq_tol = 1e-5; + const double err_tol = 1e-10; +#endif + int end, i, i_end, i_ptr, j, j_end, j_ptr, k, len, nnz, p, p_end, + p_ptr, ptr, q_end, q_ptr, s, t; + double f, vpq, temp; + /*--------------------------------------------------------------*/ + /* replace current q-th column of matrix V by new one */ + /*--------------------------------------------------------------*/ + xassert(1 <= q && q <= n); + /* convert new q-th column of matrix A to dense format */ + for (i = 1; i <= n; i++) + val[i] = 0.0; + xassert(0 <= aq_len && aq_len <= n); + for (k = 1; k <= aq_len; k++) + { i = aq_ind[k]; + xassert(1 <= i && i <= n); + xassert(val[i] == 0.0); + xassert(aq_val[k] != 0.0); + val[i] = aq_val[k]; + } + /* compute new q-th column of matrix V: + * new V[q] = inv(F * H) * (new A[q]) */ + luf->pp_ind = fhv->p0_ind; + luf->pp_inv = fhv->p0_inv; + luf_f_solve(luf, val); + luf->pp_ind = pp_ind; + luf->pp_inv = pp_inv; + fhv_h_solve(fhv, val); + /* q-th column of V = s-th column of U */ + s = qq_inv[q]; + /* determine row number of element v[p,q] that corresponds to + * diagonal element u[s,s] */ + p = pp_inv[s]; + /* convert new q-th column of V to sparse format; + * element v[p,q] = u[s,s] is not included in the element list + * and stored separately */ + vpq = 0.0; + len = 0; + for (i = 1; i <= n; i++) + { temp = val[i]; +#if 1 /* FIXME */ + if (-eps_tol < temp && temp < +eps_tol) +#endif + /* nop */; + else if (i == p) + vpq = temp; + else + { ind[++len] = i; + val[len] = temp; + } + } + /* clear q-th column of matrix V */ + for (q_end = (q_ptr = vc_ptr[q]) + vc_len[q]; + q_ptr < q_end; q_ptr++) + { /* get row index of v[i,q] */ + i = sv_ind[q_ptr]; + /* find and remove v[i,q] from i-th row */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + sv_ind[i_ptr] != q; i_ptr++) + /* nop */; + xassert(i_ptr < i_end); + sv_ind[i_ptr] = sv_ind[i_end-1]; + sv_val[i_ptr] = sv_val[i_end-1]; + vr_len[i]--; + } + /* now q-th column of matrix V is empty */ + vc_len[q] = 0; + /* put new q-th column of V (except element v[p,q] = u[s,s]) in + * column-wise format */ + if (len > 0) + { if (vc_cap[q] < len) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vc_ref-1+q, len, 0); + } + ptr = vc_ptr[q]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); + vc_len[q] = len; + } + /* put new q-th column of V (except element v[p,q] = u[s,s]) in + * row-wise format, and determine largest row number t such that + * u[s,t] != 0 */ + t = (vpq == 0.0 ? 0 : s); + for (k = 1; k <= len; k++) + { /* get row index of v[i,q] */ + i = ind[k]; + /* put v[i,q] to i-th row */ + if (vr_cap[i] == vr_len[i]) + { /* reserve extra locations in i-th row to reduce further + * relocations of that row */ +#if 1 /* FIXME */ + int need = vr_len[i] + 5; +#endif + if (sva->r_ptr - sva->m_ptr < need) + { sva_more_space(sva, need); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vr_ref-1+i, need, 0); + } + sv_ind[ptr = vr_ptr[i] + (vr_len[i]++)] = q; + sv_val[ptr] = val[k]; + /* v[i,q] is non-zero; increase t */ + if (t < pp_ind[i]) + t = pp_ind[i]; + } + /*--------------------------------------------------------------*/ + /* check if matrix U is already upper triangular */ + /*--------------------------------------------------------------*/ + /* check if there is a spike in s-th column of matrix U, which + * is q-th column of matrix V */ + if (s >= t) + { /* no spike; matrix U is already upper triangular */ + /* store its diagonal element u[s,s] = v[p,q] */ + vr_piv[p] = vpq; + if (s > t) + { /* matrix U is structurally singular, because its diagonal + * element u[s,s] = v[p,q] is exact zero */ + xassert(vpq == 0.0); + return 1; + } +#if 1 /* FIXME */ + else if (-vpq_tol < vpq && vpq < +vpq_tol) +#endif + { /* matrix U is not well conditioned, because its diagonal + * element u[s,s] = v[p,q] is too small in magnitude */ + return 2; + } + else + { /* normal case */ + return 0; + } + } + /*--------------------------------------------------------------*/ + /* perform implicit symmetric permutations of rows and columns */ + /* of matrix U */ + /*--------------------------------------------------------------*/ + /* currently v[p,q] = u[s,s] */ + xassert(p == pp_inv[s] && q == qq_ind[s]); + for (k = s; k < t; k++) + { pp_ind[pp_inv[k] = pp_inv[k+1]] = k; + qq_inv[qq_ind[k] = qq_ind[k+1]] = k; + } + /* now v[p,q] = u[t,t] */ + pp_ind[pp_inv[t] = p] = qq_inv[qq_ind[t] = q] = t; + /*--------------------------------------------------------------*/ + /* check if matrix U is already upper triangular */ + /*--------------------------------------------------------------*/ + /* check if there is a spike in t-th row of matrix U, which is + * p-th row of matrix V */ + for (p_end = (p_ptr = vr_ptr[p]) + vr_len[p]; + p_ptr < p_end; p_ptr++) + { if (qq_inv[sv_ind[p_ptr]] < t) + break; /* spike detected */ + } + if (p_ptr == p_end) + { /* no spike; matrix U is already upper triangular */ + /* store its diagonal element u[t,t] = v[p,q] */ + vr_piv[p] = vpq; +#if 1 /* FIXME */ + if (-vpq_tol < vpq && vpq < +vpq_tol) +#endif + { /* matrix U is not well conditioned, because its diagonal + * element u[t,t] = v[p,q] is too small in magnitude */ + return 2; + } + else + { /* normal case */ + return 0; + } + } + /*--------------------------------------------------------------*/ + /* copy p-th row of matrix V, which is t-th row of matrix U, to */ + /* working array */ + /*--------------------------------------------------------------*/ + /* copy p-th row of matrix V, including element v[p,q] = u[t,t], + * to the working array in dense format and remove these elements + * from matrix V; since no pivoting is used, only this row will + * change during elimination */ + for (j = 1; j <= n; j++) + work[j] = 0.0; + work[q] = vpq; + for (p_end = (p_ptr = vr_ptr[p]) + vr_len[p]; + p_ptr < p_end; p_ptr++) + { /* get column index of v[p,j] and store this element to the + * working array */ + work[j = sv_ind[p_ptr]] = sv_val[p_ptr]; + /* find and remove v[p,j] from j-th column */ + for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + sv_ind[j_ptr] != p; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + sv_ind[j_ptr] = sv_ind[j_end-1]; + sv_val[j_ptr] = sv_val[j_end-1]; + vc_len[j]--; + } + /* now p-th row of matrix V is temporarily empty */ + vr_len[p] = 0; + /*--------------------------------------------------------------*/ + /* perform gaussian elimination */ + /*--------------------------------------------------------------*/ + /* transform p-th row of matrix V stored in working array, which + * is t-th row of matrix U, to eliminate subdiagonal elements + * u[t,s], ..., u[t,t-1]; corresponding gaussian multipliers will + * form non-trivial row of new row-like factor */ + nnz = 0; /* number of non-zero gaussian multipliers */ + for (k = s; k < t; k++) + { /* diagonal element u[k,k] = v[i,j] is used as pivot */ + i = pp_inv[k], j = qq_ind[k]; + /* take subdiagonal element u[t,k] = v[p,j] */ + temp = work[j]; +#if 1 /* FIXME */ + if (-eps_tol < temp && temp < +eps_tol) + continue; +#endif + /* compute and save gaussian multiplier: + * f := u[t,k] / u[k,k] = v[p,j] / v[i,j] */ + ind[++nnz] = i; + val[nnz] = f = work[j] / vr_piv[i]; + /* gaussian transformation to eliminate u[t,k] = v[p,j]: + * (p-th row of V) := (p-th row of V) - f * (i-th row of V) */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + work[sv_ind[i_ptr]] -= f * sv_val[i_ptr]; + } + /* now matrix U is again upper triangular */ +#if 1 /* FIXME */ + if (-vpq_tol < work[q] && work[q] < +vpq_tol) +#endif + { /* however, its new diagonal element u[t,t] = v[p,q] is too + * small in magnitude */ + return 3; + } + /*--------------------------------------------------------------*/ + /* create new row-like factor H[k] and add to eta file H */ + /*--------------------------------------------------------------*/ + /* (nnz = 0 means that all subdiagonal elements were too small + * in magnitude) */ + if (nnz > 0) + { if (fhv->nfs == fhv->nfs_max) + { /* maximal number of row-like factors has been reached */ + return 4; + } + k = ++(fhv->nfs); + hh_ind[k] = p; + /* store non-trivial row of H[k] in right (dynamic) part of + * SVA (diagonal unity element is not stored) */ + if (sva->r_ptr - sva->m_ptr < nnz) + { sva_more_space(sva, nnz); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, fhv->hh_ref-1+k, nnz); + ptr = hh_ptr[k]; + memcpy(&sv_ind[ptr], &ind[1], nnz * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], nnz * sizeof(double)); + hh_len[k] = nnz; + } + /*--------------------------------------------------------------*/ + /* copy transformed p-th row of matrix V, which is t-th row of */ + /* matrix U, from working array back to matrix V */ + /*--------------------------------------------------------------*/ + /* copy elements of transformed p-th row of matrix V, which are + * non-diagonal elements u[t,t+1], ..., u[t,n] of matrix U, from + * working array to corresponding columns of matrix V (note that + * diagonal element u[t,t] = v[p,q] not copied); also transform + * p-th row of matrix V to sparse format */ + len = 0; + for (k = t+1; k <= n; k++) + { /* j-th column of V = k-th column of U */ + j = qq_ind[k]; + /* take non-diagonal element v[p,j] = u[t,k] */ + temp = work[j]; +#if 1 /* FIXME */ + if (-eps_tol < temp && temp < +eps_tol) + continue; +#endif + /* add v[p,j] to j-th column of matrix V */ + if (vc_cap[j] == vc_len[j]) + { /* reserve extra locations in j-th column to reduce further + * relocations of that column */ +#if 1 /* FIXME */ + int need = vc_len[j] + 5; +#endif + if (sva->r_ptr - sva->m_ptr < need) + { sva_more_space(sva, need); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vc_ref-1+j, need, 0); + } + sv_ind[ptr = vc_ptr[j] + (vc_len[j]++)] = p; + sv_val[ptr] = temp; + /* store element v[p,j] = u[t,k] to working sparse vector */ + ind[++len] = j; + val[len] = temp; + } + /* copy elements from working sparse vector to p-th row of matrix + * V (this row is currently empty) */ + if (vr_cap[p] < len) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vr_ref-1+p, len, 0); + } + ptr = vr_ptr[p]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); + vr_len[p] = len; + /* store new diagonal element u[t,t] = v[p,q] */ + vr_piv[p] = work[q]; + /*--------------------------------------------------------------*/ + /* perform accuracy test (only if new H[k] was added) */ + /*--------------------------------------------------------------*/ + if (nnz > 0) + { /* copy p-th (non-trivial) row of row-like factor H[k] (except + * unity diagonal element) to working array in dense format */ + for (j = 1; j <= n; j++) + work[j] = 0.0; + k = fhv->nfs; + for (end = (ptr = hh_ptr[k]) + hh_len[k]; ptr < end; ptr++) + work[sv_ind[ptr]] = sv_val[ptr]; + /* compute inner product of p-th (non-trivial) row of matrix + * H[k] and q-th column of matrix V */ + temp = vr_piv[p]; /* 1 * v[p,q] */ + ptr = vc_ptr[q]; + end = ptr + vc_len[q]; + for (; ptr < end; ptr++) + temp += work[sv_ind[ptr]] * sv_val[ptr]; + /* inner product should be equal to element v[p,q] *before* + * matrix V was transformed */ + /* compute relative error */ + temp = fabs(vpq - temp) / (1.0 + fabs(vpq)); +#if 1 /* FIXME */ + if (temp > err_tol) +#endif + { /* relative error is too large */ + return 5; + } + } + /* factorization has been successfully updated */ + return 0; +} + +/*********************************************************************** +* fhv_h_solve - solve system H * x = b +* +* This routine solves the system H * x = b, where the matrix H is the +* middle factor of the sparse updatable FHV-factorization. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix H. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void fhv_h_solve(FHV *fhv, double x[/*1+n*/]) +{ SVA *sva = fhv->luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int nfs = fhv->nfs; + int *hh_ind = fhv->hh_ind; + int hh_ref = fhv->hh_ref; + int *hh_ptr = &sva->ptr[hh_ref-1]; + int *hh_len = &sva->len[hh_ref-1]; + int i, k, end, ptr; + double x_i; + for (k = 1; k <= nfs; k++) + { x_i = x[i = hh_ind[k]]; + for (end = (ptr = hh_ptr[k]) + hh_len[k]; ptr < end; ptr++) + x_i -= sv_val[ptr] * x[sv_ind[ptr]]; + x[i] = x_i; + } + return; +} + +/*********************************************************************** +* fhv_ht_solve - solve system H' * x = b +* +* This routine solves the system H' * x = b, where H' is a matrix +* transposed to the matrix H, which is the middle factor of the sparse +* updatable FHV-factorization. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix H. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void fhv_ht_solve(FHV *fhv, double x[/*1+n*/]) +{ SVA *sva = fhv->luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int nfs = fhv->nfs; + int *hh_ind = fhv->hh_ind; + int hh_ref = fhv->hh_ref; + int *hh_ptr = &sva->ptr[hh_ref-1]; + int *hh_len = &sva->len[hh_ref-1]; + int k, end, ptr; + double x_j; + for (k = nfs; k >= 1; k--) + { if ((x_j = x[hh_ind[k]]) == 0.0) + continue; + for (end = (ptr = hh_ptr[k]) + hh_len[k]; ptr < end; ptr++) + x[sv_ind[ptr]] -= sv_val[ptr] * x_j; + } + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/fhv.h b/resources/3rdparty/glpk-4.53/src/bflib/fhv.h new file mode 100644 index 000000000..992ca311d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/fhv.h @@ -0,0 +1,114 @@ +/* fhv.h (sparse updatable FHV-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef FHV_H +#define FHV_H + +#include "luf.h" + +/*********************************************************************** +* The structure FHV describes sparse updatable FHV-factorization. +* +* The FHV-factorization has the following format: +* +* A = F * H * V, (1) +* +* F = P0 * L * P0', (2) +* +* H = H[1] * H[2] * ... * H[nfs], (3) +* +* V = P * U * Q, (4) +* +* where: A is a given (unsymmetric) square matrix; F, H, V are matrix +* factors actually computed; L is a lower triangular matrix with unity +* diagonal; U is an upper tringular matrix; H[k], k = 1, 2, ..., nfs, +* is a row-like factor, which differs from unity matrix only in one +* row called a non-trivial row; P0, P, Q are permutation matrices; and +* P0' is a matrix transposed to P0. +* +* Matrices F, V, P, Q are stored in the underlying LUF object. +* +* Non-trivial rows of factors H[k] are stored as sparse vectors in the +* right (static) part of the sparse vector area (SVA). Note that unity +* diagonal elements of non-trivial rows are not stored. +* +* Matrix P0 is stored in the same way as matrix P. +* +* Matrices L and U are completely defined by matrices F, V, P, and Q, +* and therefore not stored explicitly. */ + +typedef struct FHV FHV; + +struct FHV +{ /* FHV-factorization */ + LUF *luf; + /* LU-factorization (contains matrices F, V, P, Q) */ + /*--------------------------------------------------------------*/ + /* matrix H in the form of eta file */ + int nfs_max; + /* maximal number of row-like factors (this limits the number of + * updates of the factorization) */ + int nfs; + /* current number of row-like factors, 0 <= nfs <= nfs_max */ + int *hh_ind; /* int hh_ind[1+nfs_max]; */ + /* hh_ind[0] is not used; + * hh_ind[k], 1 <= k <= nfs, is number of non-trivial row of + * factor H[k] */ + int hh_ref; + /* reference number of sparse vector in SVA, which is non-trivial + * row of factor H[1] */ +#if 0 + 0 + int *hh_ptr = &sva->ptr[hh_ref-1]; + /* hh_ptr[0] is not used; + * hh_ptr[k], 1 <= k <= nfs, is pointer to non-trivial row of + * factor H[k] */ + int *hh_len = &sva->len[hh_ref-1]; + /* hh_len[0] is not used; + * hh_len[k], 1 <= k <= nfs, is number of non-zero elements in + * non-trivial row of factor H[k] */ +#endif + /*--------------------------------------------------------------*/ + /* matrix P0 */ + int *p0_ind; /* int p0_ind[1+n]; */ + /* p0_ind[i] = j means that P0[i,j] = 1 */ + int *p0_inv; /* int p0_inv[1+n]; */ + /* p0_inv[j] = i means that P0[i,j] = 1 */ +}; + +#define fhv_ft_update _glp_fhv_ft_update +int fhv_ft_update(FHV *fhv, int q, int aq_len, const int aq_ind[], + const double aq_val[], int ind[/*1+n*/], double val[/*1+n*/], + double work[/*1+n*/]); +/* update FHV-factorization (Forrest-Tomlin) */ + +#define fhv_h_solve _glp_fhv_h_solve +void fhv_h_solve(FHV *fhv, double x[/*1+n*/]); +/* solve system H * x = b */ + +#define fhv_ht_solve _glp_fhv_ht_solve +void fhv_ht_solve(FHV *fhv, double x[/*1+n*/]); +/* solve system H' * x = b */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/fhvint.c b/resources/3rdparty/glpk-4.53/src/bflib/fhvint.c new file mode 100644 index 000000000..9d2b25938 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/fhvint.c @@ -0,0 +1,181 @@ +/* fhvint.c (interface to FHV-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "fhvint.h" + +FHVINT *fhvint_create(void) +{ /* create interface to FHV-factorization */ + FHVINT *fi; + fi = talloc(1, FHVINT); + fi->valid = 0; + fi->fhv = NULL; + fi->lufint = NULL; + fi->nfs_max = 0; + return fi; +} + +int fhvint_factorize(FHVINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info) +{ /* compute FHV-factorization of specified matrix A */ + FHV *fhv; + LUFINT *lufint; + int nfs_max, old_n_max, n_max, k, ret; + xassert(n > 0); + fi->valid = 0; + /* get required value of nfs_max */ + nfs_max = fi->nfs_max; + if (nfs_max == 0) + nfs_max = 100; + xassert(nfs_max > 0); + /* create interface to LU-factorization, if necessary */ + lufint = fi->lufint; + if (lufint == NULL) + { lufint = fi->lufint = lufint_create(); + lufint->sva_n_max = 4 * n + nfs_max; + lufint->sva_size = 10 * n; + lufint->delta_n0 = 0; + lufint->delta_n = 100; + lufint->sgf_updat = 1; + } + /* compute LU-factorization of specified matrix A */ + old_n_max = lufint->n_max; + ret = lufint_factorize(lufint, n, col, info); + n_max = lufint->n_max; + /* create FHV-factorization, if necessary */ + fhv = fi->fhv; + if (fhv == NULL) + { fhv = fi->fhv = talloc(1, FHV); + fhv->luf = lufint->luf; + fhv->nfs_max = 0; + fhv->hh_ind = NULL; + fhv->p0_ind = NULL; + fhv->p0_inv = NULL; + } + /* allocate/reallocate FHV-factorization, if necessary */ + if (fhv->nfs_max != nfs_max) + { fhv->nfs_max = nfs_max; + if (fhv->hh_ind != NULL) + tfree(fhv->hh_ind); + fhv->hh_ind = talloc(1+nfs_max, int); + } + if (old_n_max < n_max) + { if (fhv->p0_ind != NULL) + tfree(fhv->p0_ind); + if (fhv->p0_inv != NULL) + tfree(fhv->p0_inv); + fhv->p0_ind = talloc(1+n_max, int); + fhv->p0_inv = talloc(1+n_max, int); + } + /* H := I */ + fhv->nfs = 0; + fhv->hh_ref = sva_alloc_vecs(fi->lufint->sva, nfs_max); + /* P0 := P */ + for (k = 1; k <= n; k++) + { fhv->p0_ind[k] = fi->lufint->luf->pp_ind[k]; + fhv->p0_inv[k] = fi->lufint->luf->pp_inv[k]; + } + /* set validation flag */ + if (ret == 0) + fi->valid = 1; + return ret; +} + +int fhvint_update(FHVINT *fi, int j, int len, const int ind[], + const double val[]) +{ /* update FHV-factorization after replacing j-th column of A */ + SGF *sgf = fi->lufint->sgf; + int *ind1 = sgf->rs_next; + double *val1 = sgf->vr_max; + double *work = sgf->work; + int ret; + xassert(fi->valid); + ret = fhv_ft_update(fi->fhv, j, len, ind, val, ind1, val1, work); + if (ret != 0) + fi->valid = 0; + return ret; +} + +void fhvint_ftran(FHVINT *fi, double x[]) +{ /* solve system A * x = b */ + FHV *fhv = fi->fhv; + LUF *luf = fhv->luf; + int n = luf->n; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + SGF *sgf = fi->lufint->sgf; + double *work = sgf->work; + xassert(fi->valid); + /* A = F * H * V */ + /* x = inv(A) * b = inv(V) * inv(H) * inv(F) * b */ + luf->pp_ind = fhv->p0_ind; + luf->pp_inv = fhv->p0_inv; + luf_f_solve(luf, x); + luf->pp_ind = pp_ind; + luf->pp_inv = pp_inv; + fhv_h_solve(fhv, x); + luf_v_solve(luf, x, work); + memcpy(&x[1], &work[1], n * sizeof(double)); + return; +} + +void fhvint_btran(FHVINT *fi, double x[]) +{ /* solve system A'* x = b */ + FHV *fhv = fi->fhv; + LUF *luf = fhv->luf; + int n = luf->n; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + SGF *sgf = fi->lufint->sgf; + double *work = sgf->work; + xassert(fi->valid); + /* A' = (F * H * V)' = V'* H'* F' */ + /* x = inv(A') * b = inv(F') * inv(H') * inv(V') * b */ + luf_vt_solve(luf, x, work); + fhv_ht_solve(fhv, work); + luf->pp_ind = fhv->p0_ind; + luf->pp_inv = fhv->p0_inv; + luf_ft_solve(luf, work); + luf->pp_ind = pp_ind; + luf->pp_inv = pp_inv; + memcpy(&x[1], &work[1], n * sizeof(double)); + return; +} + +void fhvint_delete(FHVINT *fi) +{ /* delete interface to FHV-factorization */ + FHV *fhv = fi->fhv; + LUFINT *lufint = fi->lufint; + if (fhv != NULL) + { tfree(fhv->hh_ind); + tfree(fhv->p0_ind); + tfree(fhv->p0_inv); + tfree(fhv); + } + if (lufint != NULL) + lufint_delete(fi->lufint); + tfree(fi); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/fhvint.h b/resources/3rdparty/glpk-4.53/src/bflib/fhvint.h new file mode 100644 index 000000000..1363a9230 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/fhvint.h @@ -0,0 +1,74 @@ +/* fhvint.h (interface to FHV-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef FHVINT_H +#define FHVINT_H + +#include "fhv.h" +#include "lufint.h" + +typedef struct FHVINT FHVINT; + +struct FHVINT +{ /* interface to FHV-factorization */ + int valid; + /* factorization is valid only if this flag is set */ + FHV *fhv; + /* FHV-factorization */ + LUFINT *lufint; + /* interface to underlying LU-factorization */ + /*--------------------------------------------------------------*/ + /* control parameters */ + int nfs_max; + /* required maximal number of row-like factors */ +}; + +#define fhvint_create _glp_fhvint_create +FHVINT *fhvint_create(void); +/* create interface to FHV-factorization */ + +#define fhvint_factorize _glp_fhvint_factorize +int fhvint_factorize(FHVINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info); +/* compute FHV-factorization of specified matrix A */ + +#define fhvint_update _glp_fhvint_update +int fhvint_update(FHVINT *fi, int j, int len, const int ind[], + const double val[]); +/* update FHV-factorization after replacing j-th column of A */ + +#define fhvint_ftran _glp_fhvint_ftran +void fhvint_ftran(FHVINT *fi, double x[]); +/* solve system A * x = b */ + +#define fhvint_btran _glp_fhvint_btran +void fhvint_btran(FHVINT *fi, double x[]); +/* solve system A'* x = b */ + +#define fhvint_delete _glp_fhvint_delete +void fhvint_delete(FHVINT *fi); +/* delete interface to FHV-factorization */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/ifu.c b/resources/3rdparty/glpk-4.53/src/bflib/ifu.c new file mode 100644 index 000000000..9e4adc7f8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/ifu.c @@ -0,0 +1,392 @@ +/* ifu.c (dense updatable IFU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "ifu.h" + +/*********************************************************************** +* ifu_expand - expand IFU-factorization +* +* This routine expands the IFU-factorization of the matrix A according +* to the following expansion of A: +* +* ( A c ) +* new A = ( ) +* ( r' d ) +* +* where c[1,...,n] is a new column, r[1,...,n] is a new row, and d is +* a new diagonal element. +* +* From the main equality F * A = U it follows that: +* +* ( F 0 ) ( A c ) ( FA Fc ) ( U Fc ) +* ( ) ( ) = ( ) = ( ), +* ( 0 1 ) ( r' d ) ( r' d ) ( r' d ) +* +* thus, +* +* ( F 0 ) ( U Fc ) +* new F = ( ), new U = ( ). +* ( 0 1 ) ( r' d ) +* +* Note that the resulting matrix U loses its upper triangular form due +* to row spike r', which should be eliminated. */ + +void ifu_expand(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d) +{ /* non-optimized version */ + int n_max = ifu->n_max; + int n = ifu->n; + double *f_ = ifu->f; + double *u_ = ifu->u; + int i, j; + double t; +# define f(i,j) f_[(i)*n_max+(j)] +# define u(i,j) u_[(i)*n_max+(j)] + xassert(0 <= n && n < n_max); + /* adjust indexing */ + c++, r++; + /* set new zero column of matrix F */ + for (i = 0; i < n; i++) + f(i,n) = 0.0; + /* set new zero row of matrix F */ + for (j = 0; j < n; j++) + f(n,j) = 0.0; + /* set new unity diagonal element of matrix F */ + f(n,n) = 1.0; + /* set new column of matrix U to vector (old F) * c */ + for (i = 0; i < n; i++) + { /* u[i,n] := (i-th row of old F) * c */ + t = 0.0; + for (j = 0; j < n; j++) + t += f(i,j) * c[j]; + u(i,n) = t; + } + /* set new row of matrix U to vector r */ + for (j = 0; j < n; j++) + u(n,j) = r[j]; + /* set new diagonal element of matrix U to scalar d */ + u(n,n) = d; + /* increase factorization order */ + ifu->n++; +# undef f +# undef u + return; +} + +/*********************************************************************** +* ifu_bg_update - update IFU-factorization (Bartels-Golub) +* +* This routine updates IFU-factorization of the matrix A according to +* its expansion (see comments to the routine ifu_expand). The routine +* is based on the method proposed by Bartels and Golub [1]. +* +* RETURNS +* +* 0 The factorization has been successfully updated. +* +* 1 On some elimination step diagional element u[k,k] to be used as +* pivot is too small in magnitude. +* +* 2 Diagonal element u[n,n] is too small in magnitude (at the end of +* update). +* +* REFERENCES +* +* 1. R.H.Bartels, G.H.Golub, "The Simplex Method of Linear Programming +* Using LU-decomposition", Comm. ACM, 12, pp. 266-68, 1969. */ + +int ifu_bg_update(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d) +{ /* non-optimized version */ + int n_max = ifu->n_max; + int n = ifu->n; + double *f_ = ifu->f; + double *u_ = ifu->u; +#if 1 /* FIXME */ + double tol = 1e-5; +#endif + int j, k; + double t; +# define f(i,j) f_[(i)*n_max+(j)] +# define u(i,j) u_[(i)*n_max+(j)] + /* expand factorization */ + ifu_expand(ifu, c, r, d); + /* NOTE: n keeps its old value */ + /* eliminate spike (non-zero subdiagonal elements) in last row of + * matrix U */ + for (k = 0; k < n; k++) + { /* if |u[k,k]| < |u[n,k]|, interchange k-th and n-th rows to + * provide |u[k,k]| >= |u[n,k]| for numeric stability */ + if (fabs(u(k,k)) < fabs(u(n,k))) + { /* interchange k-th and n-th rows of matrix U */ + for (j = k; j <= n; j++) + t = u(k,j), u(k,j) = u(n,j), u(n,j) = t; + /* interchange k-th and n-th rows of matrix F to keep the + * main equality F * A = U */ + for (j = 0; j <= n; j++) + t = f(k,j), f(k,j) = f(n,j), f(n,j) = t; + } + /* now |u[k,k]| >= |u[n,k]| */ + /* check if diagonal element u[k,k] can be used as pivot */ + if (fabs(u(k,k)) < tol) + { /* u[k,k] is too small in magnitude */ + return 1; + } + /* if u[n,k] = 0, elimination is not needed */ + if (u(n,k) == 0.0) + continue; + /* compute gaussian multiplier t = u[n,k] / u[k,k] */ + t = u(n,k) / u(k,k); + /* apply gaussian transformation to eliminate u[n,k] */ + /* (n-th row of U) := (n-th row of U) - t * (k-th row of U) */ + for (j = k+1; j <= n; j++) + u(n,j) -= t * u(k,j); + /* apply the same transformation to matrix F to keep the main + * equality F * A = U */ + for (j = 0; j <= n; j++) + f(n,j) -= t * f(k,j); + } + /* now matrix U is upper triangular */ + if (fabs(u(n,n)) < tol) + { /* u[n,n] is too small in magnitude */ + return 2; + } +# undef f +# undef u + return 0; +} + +/*********************************************************************** +* The routine givens computes the parameters of Givens plane rotation +* c = cos(teta) and s = sin(teta) such that: +* +* ( c -s ) ( a ) ( r ) +* ( ) ( ) = ( ) , +* ( s c ) ( b ) ( 0 ) +* +* where a and b are given scalars. +* +* REFERENCES +* +* G.H.Golub, C.F.Van Loan, "Matrix Computations", 2nd ed. */ + +static void givens(double a, double b, double *c, double *s) +{ /* non-optimized version */ + double t; + if (b == 0.0) + (*c) = 1.0, (*s) = 0.0; + else if (fabs(a) <= fabs(b)) + t = - a / b, (*s) = 1.0 / sqrt(1.0 + t * t), (*c) = (*s) * t; + else + t = - b / a, (*c) = 1.0 / sqrt(1.0 + t * t), (*s) = (*c) * t; + return; +} + +/*********************************************************************** +* ifu_gr_update - update IFU-factorization (Givens rotations) +* +* This routine updates IFU-factorization of the matrix A according to +* its expansion (see comments to the routine ifu_expand). The routine +* is based on Givens plane rotations [1]. +* +* RETURNS +* +* 0 The factorization has been successfully updated. +* +* 1 On some elimination step both elements u[k,k] and u[n,k] are too +* small in magnitude. +* +* 2 Diagonal element u[n,n] is too small in magnitude (at the end of +* update). +* +* REFERENCES +* +* 1. G.H.Golub, C.F.Van Loan, "Matrix Computations", 2nd ed. */ + +int ifu_gr_update(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d) +{ /* non-optimized version */ + int n_max = ifu->n_max; + int n = ifu->n; + double *f_ = ifu->f; + double *u_ = ifu->u; +#if 1 /* FIXME */ + double tol = 1e-5; +#endif + int j, k; + double cs, sn; +# define f(i,j) f_[(i)*n_max+(j)] +# define u(i,j) u_[(i)*n_max+(j)] + /* expand factorization */ + ifu_expand(ifu, c, r, d); + /* NOTE: n keeps its old value */ + /* eliminate spike (non-zero subdiagonal elements) in last row of + * matrix U */ + for (k = 0; k < n; k++) + { /* check if elements u[k,k] and u[n,k] are eligible */ + if (fabs(u(k,k)) < tol && fabs(u(n,k)) < tol) + { /* both u[k,k] and u[n,k] are too small in magnitude */ + return 1; + } + /* if u[n,k] = 0, elimination is not needed */ + if (u(n,k) == 0.0) + continue; + /* compute parameters of Givens plane rotation */ + givens(u(k,k), u(n,k), &cs, &sn); + /* apply Givens rotation to k-th and n-th rows of matrix U to + * eliminate u[n,k] */ + for (j = k; j <= n; j++) + { double ukj = u(k,j), unj = u(n,j); + u(k,j) = cs * ukj - sn * unj; + u(n,j) = sn * ukj + cs * unj; + } + /* apply the same transformation to matrix F to keep the main + * equality F * A = U */ + for (j = 0; j <= n; j++) + { double fkj = f(k,j), fnj = f(n,j); + f(k,j) = cs * fkj - sn * fnj; + f(n,j) = sn * fkj + cs * fnj; + } + } + /* now matrix U is upper triangular */ + if (fabs(u(n,n)) < tol) + { /* u[n,n] is too small in magnitude */ + return 2; + } +# undef f +# undef u + return 0; +} + +/*********************************************************************** +* ifu_a_solve - solve system A * x = b +* +* This routine solves the system A * x = b, where the matrix A is +* specified by its IFU-factorization. +* +* Using the main equality F * A = U we have: +* +* A * x = b => F * A * x = F * b => U * x = F * b => +* +* x = inv(U) * F * b. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix A. On exit this array will contain elements of the solution +* vector x in the same locations. +* +* The working array w should have at least 1+n elements (0-th element +* is not used). */ + +void ifu_a_solve(IFU *ifu, double x[/*1+n*/], double w[/*1+n*/]) +{ /* non-optimized version */ + int n_max = ifu->n_max; + int n = ifu->n; + double *f_ = ifu->f; + double *u_ = ifu->u; + int i, j; + double t; +# define f(i,j) f_[(i)*n_max+(j)] +# define u(i,j) u_[(i)*n_max+(j)] + xassert(0 <= n && n <= n_max); + /* adjust indexing */ + x++, w++; + /* y := F * b */ + memcpy(w, x, n * sizeof(double)); + for (i = 0; i < n; i++) + { /* y[i] := (i-th row of F) * b */ + t = 0.0; + for (j = 0; j < n; j++) + t += f(i,j) * w[j]; + x[i] = t; + } + /* x := inv(U) * y */ + for (i = n-1; i >= 0; i--) + { t = x[i]; + for (j = i+1; j < n; j++) + t -= u(i,j) * x[j]; + x[i] = t / u(i,i); + } +# undef f +# undef u + return; +} + +/*********************************************************************** +* ifu_at_solve - solve system A'* x = b +* +* This routine solves the system A'* x = b, where A' is a matrix +* transposed to the matrix A, specified by its IFU-factorization. +* +* Using the main equality F * A = U, from which it follows that +* A'* F' = U', we have: +* +* A'* x = b => A'* F'* inv(F') * x = b => +* +* U'* inv(F') * x = b => inv(F') * x = inv(U') * b => +* +* x = F' * inv(U') * b. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix A. On exit this array will contain elements of the solution +* vector x in the same locations. +* +* The working array w should have at least 1+n elements (0-th element +* is not used). */ + +void ifu_at_solve(IFU *ifu, double x[/*1+n*/], double w[/*1+n*/]) +{ /* non-optimized version */ + int n_max = ifu->n_max; + int n = ifu->n; + double *f_ = ifu->f; + double *u_ = ifu->u; + int i, j; + double t; +# define f(i,j) f_[(i)*n_max+(j)] +# define u(i,j) u_[(i)*n_max+(j)] + xassert(0 <= n && n <= n_max); + /* adjust indexing */ + x++, w++; + /* y := inv(U') * b */ + for (i = 0; i < n; i++) + { t = (x[i] /= u(i,i)); + for (j = i+1; j < n; j++) + x[j] -= u(i,j) * t; + } + /* x := F'* y */ + for (j = 0; j < n; j++) + { /* x[j] := (j-th column of F) * y */ + t = 0.0; + for (i = 0; i < n; i++) + t += f(i,j) * x[i]; + w[j] = t; + } + memcpy(x, w, n * sizeof(double)); +# undef f +# undef u + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/ifu.h b/resources/3rdparty/glpk-4.53/src/bflib/ifu.h new file mode 100644 index 000000000..0d53f78f6 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/ifu.h @@ -0,0 +1,99 @@ +/* ifu.h (dense updatable IFU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef IFU_H +#define IFU_H + +/*********************************************************************** +* The structure IFU describes dense updatable IFU-factorization. +* +* The IFU-factorization has the following format: +* +* A = inv(F) * U, (1) +* +* where A is a given (unsymmetric) nxn square matrix, F is a square +* matrix, U is an upper triangular matrix. Obviously, the equality (1) +* is equivalent to the following equality: +* +* F * A = U. (2) +* +* It is assumed that matrix A is small and dense, so matrices F and U +* are stored by rows in dense format as follows: +* +* 1 n n_max 1 n n_max +* 1 * * * * * * x x x x 1 * * * * * * x x x x +* * * * * * * x x x x ? * * * * * x x x x +* * * * * * * x x x x ? ? * * * * x x x x +* * * * * * * x x x x ? ? ? * * * x x x x +* * * * * * * x x x x ? ? ? ? * * x x x x +* n * * * * * * x x x x n ? ? ? ? ? * x x x x +* x x x x x x x x x x x x x x x x x x x x +* x x x x x x x x x x x x x x x x x x x x +* x x x x x x x x x x x x x x x x x x x x +* n_max x x x x x x x x x x n_max x x x x x x x x x x +* +* matrix F matrix U +* +* where '*' are matrix elements, '?' are unused locations, 'x' are +* reserved locations. */ + +typedef struct IFU IFU; + +struct IFU +{ /* IFU-factorization */ + int n_max; + /* maximal order of matrices A, F, U; n_max >= 1 */ + int n; + /* current order of matrices A, F, U; 0 <= n <= n_max */ + double *f; /* double f[n_max*n_max]; */ + /* matrix F stored by rows */ + double *u; /* double u[n_max*n_max]; */ + /* matrix U stored by rows */ +}; + +#define ifu_expand _glp_ifu_expand +void ifu_expand(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d); +/* expand IFU-factorization */ + +#define ifu_bg_update _glp_ifu_bg_update +int ifu_bg_update(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d); +/* update IFU-factorization (Bartels-Golub) */ + +#define ifu_gr_update _glp_ifu_gr_update +int ifu_gr_update(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d); +/* update IFU-factorization (Givens rotations) */ + +#define ifu_a_solve _glp_ifu_a_solve +void ifu_a_solve(IFU *ifu, double x[/*1+n*/], double w[/*1+n*/]); +/* solve system A * x = b */ + +#define ifu_at_solve _glp_ifu_at_solve +void ifu_at_solve(IFU *ifu, double x[/*1+n*/], double w[/*1+n*/]); +/* solve system A'* x = b */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/luf.c b/resources/3rdparty/glpk-4.53/src/bflib/luf.c new file mode 100644 index 000000000..adbf10451 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/luf.c @@ -0,0 +1,575 @@ +/* luf.c (sparse LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "luf.h" + +/*********************************************************************** +* luf_check_all - check LU-factorization before k-th elimination step +* +* This routine checks that before performing k-th elimination step, +* 1 <= k <= n+1, all components of the LU-factorization are correct. +* +* In case of k = n+1, i.e. after last elimination step, it is assumed +* that rows of F and columns of V are *not* built yet. +* +* NOTE: For testing/debugging only. */ + +void luf_check_all(LUF *luf, int k) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fr_ref = luf->fr_ref; + int *fr_len = &sva->len[fr_ref-1]; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int i, ii, i_ptr, i_end, j, jj, j_ptr, j_end; + xassert(n > 0); + xassert(1 <= k && k <= n+1); + /* check permutation matrix P */ + for (i = 1; i <= n; i++) + { ii = pp_ind[i]; + xassert(1 <= ii && ii <= n); + xassert(pp_inv[ii] == i); + } + /* check permutation matrix Q */ + for (j = 1; j <= n; j++) + { jj = qq_inv[j]; + xassert(1 <= jj && jj <= n); + xassert(qq_ind[jj] == j); + } + /* check row-wise representation of matrix F */ + for (i = 1; i <= n; i++) + xassert(fr_len[i] == 0); + /* check column-wise representation of matrix F */ + for (j = 1; j <= n; j++) + { /* j-th column of F = jj-th column of L */ + jj = pp_ind[j]; + if (jj < k) + { j_ptr = fc_ptr[j]; + j_end = j_ptr + fc_len[j]; + for (; j_ptr < j_end; j_ptr++) + { i = sv_ind[j_ptr]; + xassert(1 <= i && i <= n); + ii = pp_ind[i]; /* f[i,j] = l[ii,jj] */ + xassert(ii > jj); + xassert(sv_val[j_ptr] != 0.0); + } + } + else /* jj >= k */ + xassert(fc_len[j] == 0); + } + /* check row-wise representation of matrix V */ + for (i = 1; i <= n; i++) + { /* i-th row of V = ii-th row of U */ + ii = pp_ind[i]; + i_ptr = vr_ptr[i]; + i_end = i_ptr + vr_len[i]; + for (; i_ptr < i_end; i_ptr++) + { j = sv_ind[i_ptr]; + xassert(1 <= j && j <= n); + jj = qq_inv[j]; /* v[i,j] = u[ii,jj] */ + if (ii < k) + xassert(jj > ii); + else /* ii >= k */ + { xassert(jj >= k); + /* find v[i,j] in j-th column */ + j_ptr = vc_ptr[j]; + j_end = j_ptr + vc_len[j]; + for (; sv_ind[j_ptr] != i; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + } + xassert(sv_val[i_ptr] != 0.0); + } + } + /* check column-wise representation of matrix V */ + for (j = 1; j <= n; j++) + { /* j-th column of V = jj-th column of U */ + jj = qq_inv[j]; + if (jj < k) + xassert(vc_len[j] == 0); + else /* jj >= k */ + { j_ptr = vc_ptr[j]; + j_end = j_ptr + vc_len[j]; + for (; j_ptr < j_end; j_ptr++) + { i = sv_ind[j_ptr]; + ii = pp_ind[i]; /* v[i,j] = u[ii,jj] */ + xassert(ii >= k); + /* find v[i,j] in i-th row */ + i_ptr = vr_ptr[i]; + i_end = i_ptr + vr_len[i]; + for (; sv_ind[i_ptr] != j; i_ptr++) + /* nop */; + xassert(i_ptr < i_end); + } + } + } + return; +} + +/*********************************************************************** +* luf_build_v_rows - build matrix V in row-wise format +* +* This routine builds the row-wise representation of matrix V in the +* left part of SVA using its column-wise representation. +* +* NOTE: On entry to the routine all rows of matrix V should have zero +* capacity. +* +* The working array len should have at least 1+n elements (len[0] is +* not used). */ + +void luf_build_v_rows(LUF *luf, int len[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int i, j, end, nnz, ptr, ptr1; + /* calculate the number of non-zeros in each row of matrix V and + * the total number of non-zeros */ + nnz = 0; + for (i = 1; i <= n; i++) + len[i] = 0; + for (j = 1; j <= n; j++) + { nnz += vc_len[j]; + for (end = (ptr = vc_ptr[j]) + vc_len[j]; ptr < end; ptr++) + len[sv_ind[ptr]]++; + } + /* we need at least nnz free locations in SVA */ + if (sva->r_ptr - sva->m_ptr < nnz) + { sva_more_space(sva, nnz); + sv_ind = sva->ind; + sv_val = sva->val; + } + /* reserve locations for rows of matrix V */ + for (i = 1; i <= n; i++) + { if (len[i] > 0) + sva_enlarge_cap(sva, vr_ref-1+i, len[i], 0); + vr_len[i] = len[i]; + } + /* walk thru column of matrix V and build its rows */ + for (j = 1; j <= n; j++) + { for (end = (ptr = vc_ptr[j]) + vc_len[j]; ptr < end; ptr++) + { i = sv_ind[ptr]; + sv_ind[ptr1 = vr_ptr[i] + (--len[i])] = j; + sv_val[ptr1] = sv_val[ptr]; + } + } + return; +} + +/*********************************************************************** +* luf_build_f_rows - build matrix F in row-wise format +* +* This routine builds the row-wise representation of matrix F in the +* right part of SVA using its column-wise representation. +* +* NOTE: On entry to the routine all rows of matrix F should have zero +* capacity. +* +* The working array len should have at least 1+n elements (len[0] is +* not used). */ + +void luf_build_f_rows(LUF *luf, int len[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fr_ref = luf->fr_ref; + int *fr_ptr = &sva->ptr[fr_ref-1]; + int *fr_len = &sva->len[fr_ref-1]; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int i, j, end, nnz, ptr, ptr1; + /* calculate the number of non-zeros in each row of matrix F and + * the total number of non-zeros (except diagonal elements) */ + nnz = 0; + for (i = 1; i <= n; i++) + len[i] = 0; + for (j = 1; j <= n; j++) + { nnz += fc_len[j]; + for (end = (ptr = fc_ptr[j]) + fc_len[j]; ptr < end; ptr++) + len[sv_ind[ptr]]++; + } + /* we need at least nnz free locations in SVA */ + if (sva->r_ptr - sva->m_ptr < nnz) + { sva_more_space(sva, nnz); + sv_ind = sva->ind; + sv_val = sva->val; + } + /* reserve locations for rows of matrix F */ + for (i = 1; i <= n; i++) + { if (len[i] > 0) + sva_reserve_cap(sva, fr_ref-1+i, len[i]); + fr_len[i] = len[i]; + } + /* walk through columns of matrix F and build its rows */ + for (j = 1; j <= n; j++) + { for (end = (ptr = fc_ptr[j]) + fc_len[j]; ptr < end; ptr++) + { i = sv_ind[ptr]; + sv_ind[ptr1 = fr_ptr[i] + (--len[i])] = j; + sv_val[ptr1] = sv_val[ptr]; + } + } + return; +} + +/*********************************************************************** +* luf_build_v_cols - build matrix V in column-wise format +* +* This routine builds the column-wise representation of matrix V in +* the left (if the flag updat is set) or right (if the flag updat is +* clear) part of SVA using its row-wise representation. +* +* NOTE: On entry to the routine all columns of matrix V should have +* zero capacity. +* +* The working array len should have at least 1+n elements (len[0] is +* not used). */ + +void luf_build_v_cols(LUF *luf, int updat, int len[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int i, j, end, nnz, ptr, ptr1; + /* calculate the number of non-zeros in each column of matrix V + * and the total number of non-zeros (except pivot elements) */ + nnz = 0; + for (j = 1; j <= n; j++) + len[j] = 0; + for (i = 1; i <= n; i++) + { nnz += vr_len[i]; + for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) + len[sv_ind[ptr]]++; + } + /* we need at least nnz free locations in SVA */ + if (sva->r_ptr - sva->m_ptr < nnz) + { sva_more_space(sva, nnz); + sv_ind = sva->ind; + sv_val = sva->val; + } + /* reserve locations for columns of matrix V */ + for (j = 1; j <= n; j++) + { if (len[j] > 0) + { if (updat) + sva_enlarge_cap(sva, vc_ref-1+j, len[j], 0); + else + sva_reserve_cap(sva, vc_ref-1+j, len[j]); + } + vc_len[j] = len[j]; + } + /* walk through rows of matrix V and build its columns */ + for (i = 1; i <= n; i++) + { for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) + { j = sv_ind[ptr]; + sv_ind[ptr1 = vc_ptr[j] + (--len[j])] = i; + sv_val[ptr1] = sv_val[ptr]; + } + } + return; +} + +/*********************************************************************** +* luf_check_f_rc - check rows and columns of matrix F +* +* This routine checks that the row- and column-wise representations +* of matrix F are identical. +* +* NOTE: For testing/debugging only. */ + +void luf_check_f_rc(LUF *luf) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fr_ref = luf->fr_ref; + int *fr_ptr = &sva->ptr[fr_ref-1]; + int *fr_len = &sva->len[fr_ref-1]; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int i, i_end, i_ptr, j, j_end, j_ptr; + /* walk thru rows of matrix F */ + for (i = 1; i <= n; i++) + { for (i_end = (i_ptr = fr_ptr[i]) + fr_len[i]; + i_ptr < i_end; i_ptr++) + { j = sv_ind[i_ptr]; + /* find element f[i,j] in j-th column of matrix F */ + for (j_end = (j_ptr = fc_ptr[j]) + fc_len[j]; + sv_ind[j_ptr] != i; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + xassert(sv_val[i_ptr] == sv_val[j_ptr]); + /* mark element f[i,j] */ + sv_ind[j_ptr] = -i; + } + } + /* walk thru column of matix F and check that all elements has + been marked */ + for (j = 1; j <= n; j++) + { for (j_end = (j_ptr = fc_ptr[j]) + fc_len[j]; + j_ptr < j_end; j_ptr++) + { xassert((i = sv_ind[j_ptr]) < 0); + /* unmark element f[i,j] */ + sv_ind[j_ptr] = -i; + } + } + return; +} + +/*********************************************************************** +* luf_check_v_rc - check rows and columns of matrix V +* +* This routine checks that the row- and column-wise representations +* of matrix V are identical. +* +* NOTE: For testing/debugging only. */ + +void luf_check_v_rc(LUF *luf) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int i, i_end, i_ptr, j, j_end, j_ptr; + /* walk thru rows of matrix V */ + for (i = 1; i <= n; i++) + { for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + { j = sv_ind[i_ptr]; + /* find element v[i,j] in j-th column of matrix V */ + for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + sv_ind[j_ptr] != i; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + xassert(sv_val[i_ptr] == sv_val[j_ptr]); + /* mark element v[i,j] */ + sv_ind[j_ptr] = -i; + } + } + /* walk thru column of matix V and check that all elements has + been marked */ + for (j = 1; j <= n; j++) + { for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + j_ptr < j_end; j_ptr++) + { xassert((i = sv_ind[j_ptr]) < 0); + /* unmark element v[i,j] */ + sv_ind[j_ptr] = -i; + } + } + return; +} + +/*********************************************************************** +* luf_f_solve - solve system F * x = b +* +* This routine solves the system F * x = b, where the matrix F is the +* left factor of the sparse LU-factorization. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix F. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void luf_f_solve(LUF *luf, double x[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int *pp_inv = luf->pp_inv; + int j, k, ptr, end; + double x_j; + for (k = 1; k <= n; k++) + { /* k-th column of L = j-th column of F */ + j = pp_inv[k]; + /* x[j] is already computed */ + /* walk thru j-th column of matrix F and substitute x[j] into + * other equations */ + if ((x_j = x[j]) != 0.0) + { for (end = (ptr = fc_ptr[j]) + fc_len[j]; + ptr < end; ptr++) + x[sv_ind[ptr]] -= sv_val[ptr] * x_j; + } + } + return; +} + +/*********************************************************************** +* luf_ft_solve - solve system F' * x = b +* +* This routine solves the system F' * x = b, where F' is a matrix +* transposed to the matrix F, which is the left factor of the sparse +* LU-factorization. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix F. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void luf_ft_solve(LUF *luf, double x[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fr_ref = luf->fr_ref; + int *fr_ptr = &sva->ptr[fr_ref-1]; + int *fr_len = &sva->len[fr_ref-1]; + int *pp_inv = luf->pp_inv; + int i, k, ptr, end; + double x_i; + for (k = n; k >= 1; k--) + { /* k-th column of L' = i-th row of F */ + i = pp_inv[k]; + /* x[i] is already computed */ + /* walk thru i-th row of matrix F and substitute x[i] into + * other equations */ + if ((x_i = x[i]) != 0.0) + { for (end = (ptr = fr_ptr[i]) + fr_len[i]; + ptr < end; ptr++) + x[sv_ind[ptr]] -= sv_val[ptr] * x_i; + } + } + return; +} + +/*********************************************************************** +* luf_v_solve - solve system V * x = b +* +* This routine solves the system V * x = b, where the matrix V is the +* right factor of the sparse LU-factorization. +* +* On entry the array b should contain elements of the right-hand side +* vector b in locations b[1], ..., b[n], where n is the order of the +* matrix V. On exit the array x will contain elements of the solution +* vector x in locations x[1], ..., x[n]. Note that the array b will be +* clobbered on exit. */ + +void luf_v_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int i, j, k, ptr, end; + double x_j; + for (k = n; k >= 1; k--) + { /* k-th row of U = i-th row of V */ + /* k-th column of U = j-th column of V */ + i = pp_inv[k]; + j = qq_ind[k]; + /* compute x[j] = b[i] / u[k,k], where u[k,k] = v[i,j]; + * walk through j-th column of matrix V and substitute x[j] + * into other equations */ + if ((x_j = x[j] = b[i] / vr_piv[i]) != 0.0) + { for (end = (ptr = vc_ptr[j]) + vc_len[j]; + ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * x_j; + } + } + return; +} + +/*********************************************************************** +* luf_vt_solve - solve system V' * x = b +* +* This routine solves the system V' * x = b, where V' is a matrix +* transposed to the matrix V, which is the right factor of the sparse +* LU-factorization. +* +* On entry the array b should contain elements of the right-hand side +* vector b in locations b[1], ..., b[n], where n is the order of the +* matrix V. On exit the array x will contain elements of the solution +* vector x in locations x[1], ..., x[n]. Note that the array b will be +* clobbered on exit. */ + +void luf_vt_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + double *vr_piv = luf->vr_piv; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int i, j, k, ptr, end; + double x_i; + for (k = 1; k <= n; k++) + { /* k-th row of U' = j-th column of V */ + /* k-th column of U' = i-th row of V */ + i = pp_inv[k]; + j = qq_ind[k]; + /* compute x[i] = b[j] / u'[k,k], where u'[k,k] = v[i,j]; + * walk through i-th row of matrix V and substitute x[i] into + * other equations */ + if ((x_i = x[i] = b[j] / vr_piv[i]) != 0.0) + { for (end = (ptr = vr_ptr[i]) + vr_len[i]; + ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * x_i; + } + } + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/luf.h b/resources/3rdparty/glpk-4.53/src/bflib/luf.h new file mode 100644 index 000000000..d5b0bd3c8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/luf.h @@ -0,0 +1,213 @@ +/* luf.h (sparse LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef LUF_H +#define LUF_H + +#include "sva.h" + +/*********************************************************************** +* The structure LUF describes sparse LU-factorization. +* +* The LU-factorization has the following format: +* +* A = F * V = P * L * U * Q, (1) +* +* F = P * L * P', (2) +* +* V = P * U * Q, (3) +* +* where A is a given (unsymmetric) square matrix, F and V are matrix +* factors actually computed, L is a lower triangular matrix with unity +* diagonal, U is an upper triangular matrix, P and Q are permutation +* matrices, P' is a matrix transposed to P. All the matrices have the +* same order n. +* +* Matrices F and V are stored in both row- and column-wise sparse +* formats in the associated sparse vector area (SVA). Unity diagonal +* elements of matrix F are not stored. Pivot elements of matrix V +* (which correspond to diagonal elements of matrix U) are stored in +* a separate ordinary array. +* +* Permutation matrices P and Q are stored in ordinary arrays in both +* row- and column-like formats. +* +* Matrices L and U are completely defined by matrices F, V, P, and Q, +* and therefore not stored explicitly. */ + +typedef struct LUF LUF; + +struct LUF +{ /* sparse LU-factorization */ + int n; + /* order of matrices A, F, V, P, Q */ + SVA *sva; + /* associated sparse vector area (SVA) used to store rows and + * columns of matrices F and V; note that different objects may + * share the same SVA */ + /*--------------------------------------------------------------*/ + /* matrix F in row-wise format */ + /* during the factorization process this object is not used */ + int fr_ref; + /* reference number of sparse vector in SVA, which is the first + * row of matrix F */ +#if 0 + 0 + int *fr_ptr = &sva->ptr[fr_ref-1]; + /* fr_ptr[0] is not used; + * fr_ptr[i], 1 <= i <= n, is pointer to i-th row in SVA */ + int *fr_len = &sva->len[fr_ref-1]; + /* fr_len[0] is not used; + * fr_len[i], 1 <= i <= n, is length of i-th row */ +#endif + /*--------------------------------------------------------------*/ + /* matrix F in column-wise format */ + /* during the factorization process this object is constructed + by columns */ + int fc_ref; + /* reference number of sparse vector in SVA, which is the first + * column of matrix F */ +#if 0 + 0 + int *fc_ptr = &sva->ptr[fc_ref-1]; + /* fc_ptr[0] is not used; + * fc_ptr[j], 1 <= j <= n, is pointer to j-th column in SVA */ + int *fc_len = &sva->len[fc_ref-1]; + /* fc_len[0] is not used; + * fc_len[j], 1 <= j <= n, is length of j-th column */ +#endif + /*--------------------------------------------------------------*/ + /* matrix V in row-wise format */ + int vr_ref; + /* reference number of sparse vector in SVA, which is the first + * row of matrix V */ +#if 0 + 0 + int *vr_ptr = &sva->ptr[vr_ref-1]; + /* vr_ptr[0] is not used; + * vr_ptr[i], 1 <= i <= n, is pointer to i-th row in SVA */ + int *vr_len = &sva->len[vr_ref-1]; + /* vr_len[0] is not used; + * vr_len[i], 1 <= i <= n, is length of i-th row */ + int *vr_cap = &sva->cap[vr_ref-1]; + /* vr_cap[0] is not used; + * vr_cap[i], 1 <= i <= n, is capacity of i-th row */ +#endif + double *vr_piv; /* double vr_piv[1+n]; */ + /* vr_piv[0] is not used; + * vr_piv[i], 1 <= i <= n, is pivot element of i-th row */ + /*--------------------------------------------------------------*/ + /* matrix V in column-wise format */ + /* during the factorization process this object contains only the + * patterns (row indices) of columns of the active submatrix */ + int vc_ref; + /* reference number of sparse vector in SVA, which is the first + * column of matrix V */ +#if 0 + 0 + int *vc_ptr = &sva->ptr[vc_ref-1]; + /* vc_ptr[0] is not used; + * vc_ptr[j], 1 <= j <= n, is pointer to j-th column in SVA */ + int *vc_len = &sva->len[vc_ref-1]; + /* vc_len[0] is not used; + * vc_len[j], 1 <= j <= n, is length of j-th column */ + int *vc_cap = &sva->cap[vc_ref-1]; + /* vc_cap[0] is not used; + * vc_cap[j], 1 <= j <= n, is capacity of j-th column */ +#endif + /*--------------------------------------------------------------*/ + /* matrix P */ + int *pp_ind; /* int pp_ind[1+n]; */ + /* pp_ind[i] = j means that P[i,j] = 1 */ + int *pp_inv; /* int pp_inv[1+n]; */ + /* pp_inv[j] = i means that P[i,j] = 1 */ + /* if i-th row or column of matrix F is i'-th row or column of + * matrix L, or if i-th row of matrix V is i'-th row of matrix U, + * then pp_ind[i] = i' and pp_inv[i'] = i */ + /*--------------------------------------------------------------*/ + /* matrix Q */ + int *qq_ind; /* int qq_ind[1+n]; */ + /* qq_ind[i] = j means that Q[i,j] = 1 */ + int *qq_inv; /* int qq_inv[1+n]; */ + /* qq_inv[j] = i means that Q[i,j] = 1 */ + /* if j-th column of matrix V is j'-th column of matrix U, then + * qq_ind[j'] = j and qq_inv[j] = j' */ +}; + +#define luf_swap_u_rows(i1, i2) \ + do \ + { int j1, j2; \ + j1 = pp_inv[i1], j2 = pp_inv[i2]; \ + pp_ind[j1] = i2, pp_inv[i2] = j1; \ + pp_ind[j2] = i1, pp_inv[i1] = j2; \ + } while (0) +/* swap rows i1 and i2 of matrix U = P'* V * Q' */ + +#define luf_swap_u_cols(j1, j2) \ + do \ + { int i1, i2; \ + i1 = qq_ind[j1], i2 = qq_ind[j2]; \ + qq_ind[j1] = i2, qq_inv[i2] = j1; \ + qq_ind[j2] = i1, qq_inv[i1] = j2; \ + } while (0) +/* swap columns j1 and j2 of matrix U = P'* V * Q' */ + +#define luf_check_all _glp_luf_check_all +void luf_check_all(LUF *luf, int k); +/* check LU-factorization before k-th elimination step */ + +#define luf_build_v_rows _glp_luf_build_v_rows +void luf_build_v_rows(LUF *luf, int len[/*1+n*/]); +/* build matrix V in row-wise format */ + +#define luf_build_f_rows _glp_luf_build_f_rows +void luf_build_f_rows(LUF *luf, int len[/*1+n*/]); +/* build matrix F in row-wise format */ + +#define luf_build_v_cols _glp_luf_build_v_cols +void luf_build_v_cols(LUF *luf, int updat, int len[/*1+n*/]); +/* build matrix V in column-wise format */ + +#define luf_check_f_rc _glp_luf_check_f_rc +void luf_check_f_rc(LUF *luf); +/* check rows and columns of matrix F */ + +#define luf_check_v_rc _glp_luf_check_v_rc +void luf_check_v_rc(LUF *luf); +/* check rows and columns of matrix V */ + +#define luf_f_solve _glp_luf_f_solve1 +void luf_f_solve(LUF *luf, double x[/*1+n*/]); +/* solve system F * x = b */ + +#define luf_ft_solve _glp_luf_ft_solve1 +void luf_ft_solve(LUF *luf, double x[/*1+n*/]); +/* solve system F' * x = b */ + +#define luf_v_solve _glp_luf_v_solve1 +void luf_v_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]); +/* solve system V * x = b */ + +#define luf_vt_solve _glp_luf_vt_solve1 +void luf_vt_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]); +/* solve system V' * x = b */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/lufint.c b/resources/3rdparty/glpk-4.53/src/bflib/lufint.c new file mode 100644 index 000000000..56f83e32f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/lufint.c @@ -0,0 +1,218 @@ +/* lufint.c (interface to LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "lufint.h" + +LUFINT *lufint_create(void) +{ /* create interface to LU-factorization */ + LUFINT *fi; + fi = talloc(1, LUFINT); + fi->n_max = 0; + fi->valid = 0; + fi->sva = NULL; + fi->luf = NULL; + fi->sgf = NULL; + fi->sva_n_max = fi->sva_size = 0; + fi->delta_n0 = fi->delta_n = 0; + fi->sgf_updat = 0; + fi->sgf_piv_tol = 0.10; + fi->sgf_piv_lim = 4; + fi->sgf_suhl = 1; + fi->sgf_eps_tol = DBL_EPSILON; + return fi; +} + +static int setup_v_cols(LUF *luf, int (*col)(void *info, int j, + int ind[], double val[]), void *info, int ind[], double val[]) +{ /* setup matrix V = A in column-wise format */ + int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *vc_cap = &sva->cap[vc_ref-1]; + int j, len, ptr, nnz; + nnz = 0; + for (j = 1; j <= n; j++) + { /* get j-th column */ + len = col(info, j, ind, val); + xassert(0 <= len && len <= n); + /* enlarge j-th column capacity */ + if (vc_cap[j] < len) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vc_ref-1+j, len, 0); + } + /* store j-th column */ + ptr = vc_ptr[j]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); + vc_len[j] = len; + nnz += len; + } + return nnz; +} + +int lufint_factorize(LUFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info) +{ /* compute LU-factorization of specified matrix A */ + SVA *sva; + LUF *luf; + SGF *sgf; + int k; + xassert(n > 0); + fi->valid = 0; + /* create sparse vector area (SVA), if necessary */ + sva = fi->sva; + if (sva == NULL) + { int sva_n_max = fi->sva_n_max; + int sva_size = fi->sva_size; + if (sva_n_max == 0) + sva_n_max = 4 * n; + if (sva_size == 0) + sva_size = 10 * n; + sva = fi->sva = sva_create_area(sva_n_max, sva_size); + } + /* allocate/reallocate underlying objects, if necessary */ + if (fi->n_max < n) + { int n_max = fi->n_max; + if (n_max == 0) + n_max = fi->n_max = n + fi->delta_n0; + else + n_max = fi->n_max = n + fi->delta_n; + xassert(n_max >= n); + /* allocate/reallocate LU-factorization (LUF) */ + luf = fi->luf; + if (luf == NULL) + { luf = fi->luf = talloc(1, LUF); + memset(luf, 0, sizeof(LUF)); + luf->sva = sva; + } + else + { tfree(luf->vr_piv); + tfree(luf->pp_ind); + tfree(luf->pp_inv); + tfree(luf->qq_ind); + tfree(luf->qq_inv); + } + luf->vr_piv = talloc(1+n_max, double); + luf->pp_ind = talloc(1+n_max, int); + luf->pp_inv = talloc(1+n_max, int); + luf->qq_ind = talloc(1+n_max, int); + luf->qq_inv = talloc(1+n_max, int); + /* allocate/reallocate factorizer workspace (SGF) */ + sgf = fi->sgf; + if (sgf == NULL) + { sgf = fi->sgf = talloc(1, SGF); + memset(sgf, 0, sizeof(SGF)); + sgf->luf = luf; + } + else + { tfree(sgf->rs_head); + tfree(sgf->rs_prev); + tfree(sgf->rs_next); + tfree(sgf->cs_head); + tfree(sgf->cs_prev); + tfree(sgf->cs_next); + tfree(sgf->vr_max); + tfree(sgf->flag); + tfree(sgf->work); + } + sgf->rs_head = talloc(1+n_max, int); + sgf->rs_prev = talloc(1+n_max, int); + sgf->rs_next = talloc(1+n_max, int); + sgf->cs_head = talloc(1+n_max, int); + sgf->cs_prev = talloc(1+n_max, int); + sgf->cs_next = talloc(1+n_max, int); + sgf->vr_max = talloc(1+n_max, double); + sgf->flag = talloc(1+n_max, char); + sgf->work = talloc(1+n_max, double); + } + luf = fi->luf; + sgf = fi->sgf; +#if 1 /* FIXME */ + /* initialize SVA */ + sva->n = 0; + sva->m_ptr = 1; + sva->r_ptr = sva->size + 1; + sva->head = sva->tail = 0; +#endif + /* allocate sparse vectors in SVA */ + luf->n = n; + luf->fr_ref = sva_alloc_vecs(sva, n); + luf->fc_ref = sva_alloc_vecs(sva, n); + luf->vr_ref = sva_alloc_vecs(sva, n); + luf->vc_ref = sva_alloc_vecs(sva, n); + /* setup matrix V = A in column-wise format */ + setup_v_cols(luf, col, info, sgf->rs_prev, sgf->work); + /* setup factorizer control parameters */ + sgf->updat = fi->sgf_updat; + sgf->piv_tol = fi->sgf_piv_tol; + sgf->piv_lim = fi->sgf_piv_lim; + sgf->suhl = fi->sgf_suhl; + sgf->eps_tol = fi->sgf_eps_tol; + /* compute LU-factorization of specified matrix A */ + k = sgf_factorize(sgf, 1); + if (k == 0) + fi->valid = 1; + return k; +} + +void lufint_delete(LUFINT *fi) +{ /* delete interface to LU-factorization */ + SVA *sva = fi->sva; + LUF *luf = fi->luf; + SGF *sgf = fi->sgf; + if (sva != NULL) + sva_delete_area(sva); + if (luf != NULL) + { tfree(luf->vr_piv); + tfree(luf->pp_ind); + tfree(luf->pp_inv); + tfree(luf->qq_ind); + tfree(luf->qq_inv); + tfree(luf); + } + if (sgf != NULL) + { tfree(sgf->rs_head); + tfree(sgf->rs_prev); + tfree(sgf->rs_next); + tfree(sgf->cs_head); + tfree(sgf->cs_prev); + tfree(sgf->cs_next); + tfree(sgf->vr_max); + tfree(sgf->flag); + tfree(sgf->work); + tfree(sgf); + } + tfree(fi); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/lufint.h b/resources/3rdparty/glpk-4.53/src/bflib/lufint.h new file mode 100644 index 000000000..6ec6cf073 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/lufint.h @@ -0,0 +1,73 @@ +/* lufint.h (interface to LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef LUFINT_H +#define LUFINT_H + +#include "sgf.h" + +typedef struct LUFINT LUFINT; + +struct LUFINT +{ /* interface to LU-factorization */ + int n_max; + /* maximal value of n (increased automatically) */ + int valid; + /* factorization is valid only if this flag is set */ + SVA *sva; + /* sparse vector area (SVA) */ + LUF *luf; + /* sparse LU-factorization */ + SGF *sgf; + /* sparse Gaussian factorizer workspace */ + /*--------------------------------------------------------------*/ + /* control parameters */ + int sva_n_max, sva_size; + /* parameters passed to sva_create_area */ + int delta_n0, delta_n; + /* if n_max = 0, set n_max = n + delta_n0 + * if n_max < n, set n_max = n + delta_n */ + int sgf_updat; + double sgf_piv_tol; + int sgf_piv_lim; + int sgf_suhl; + double sgf_eps_tol; + /* factorizer control parameters */ +}; + +#define lufint_create _glp_lufint_create +LUFINT *lufint_create(void); +/* create interface to LU-factorization */ + +#define lufint_factorize _glp_lufint_factorize +int lufint_factorize(LUFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info); +/* compute LU-factorization of specified matrix A */ + +#define lufint_delete _glp_lufint_delete +void lufint_delete(LUFINT *fi); +/* delete interface to LU-factorization */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/sgf.c b/resources/3rdparty/glpk-4.53/src/bflib/sgf.c new file mode 100644 index 000000000..462ac10ac --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/sgf.c @@ -0,0 +1,1407 @@ +/* sgf.c (sparse Gaussian factorizer) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "sgf.h" + +/*********************************************************************** +* sgf_reduce_nuc - initial reordering to minimize nucleus size +* +* On entry to this routine it is assumed that V = A and F = P = Q = I, +* where A is the original matrix to be factorized. It is also assumed +* that matrix V = A is stored in both row- and column-wise formats. +* +* This routine performs (implicit) non-symmetric permutations of rows +* and columns of matrix U = P'* V * Q' to reduce it to the form: +* +* 1 k1 k2 n +* 1 x x x x x x x x x x +* . x x x x x x x x x +* . . x x x x x x x x +* k1 . . . * * * * x x x +* . . . * * * * x x x +* . . . * * * * x x x +* k2 . . . * * * * x x x +* . . . . . . . x x x +* . . . . . . . . x x +* n . . . . . . . . . x +* +* where non-zeros in rows and columns k1, k1+1, ..., k2 constitute so +* called nucleus ('*'), whose size is minimized by the routine. +* +* The numbers k1 and k2 are returned by the routine on exit. Usually, +* if the nucleus exists, 1 <= k1 < k2 <= n. However, if the resultant +* matrix U is upper triangular (has no nucleus), k1 = n+1 and k2 = n. +* +* Note that the routines sgf_choose_pivot and sgf_eliminate perform +* exactly the same transformations (by processing row and columns +* singletons), so preliminary minimization of the nucleus may not be +* used. However, processing row and column singletons by the routines +* sgf_minimize_nuc and sgf_singl_phase is more efficient. */ + +void sgf_reduce_nuc(LUF *luf, int *k1_, int *k2_, int cnt[/*1+n*/], + int list[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int i, ii, j, jj, k1, k2, ns, ptr, end; + /* initial nucleus is U = V = A */ + k1 = 1, k2 = n; + /*--------------------------------------------------------------*/ + /* process column singletons */ + /*--------------------------------------------------------------*/ + /* determine initial counts of columns of V and initialize list + * of active column singletons */ + ns = 0; /* number of active column singletons */ + for (j = 1; j <= n; j++) + { if ((cnt[j] = vc_len[j]) == 1) + list[++ns] = j; + } + /* process active column singletons */ + while (ns > 0) + { /* column singleton is in j-th column of V */ + j = list[ns--]; + /* find i-th row of V containing column singleton */ + ptr = vc_ptr[j]; + end = ptr + vc_len[j]; + for (; pp_ind[i = sv_ind[ptr]] < k1; ptr++) + /* nop */; + xassert(ptr < end); + /* permute rows and columns of U to move column singleton to + * position u[k1,k1] */ + ii = pp_ind[i]; + luf_swap_u_rows(k1, ii); + jj = qq_inv[j]; + luf_swap_u_cols(k1, jj); + /* nucleus size decreased */ + k1++; + /* walk thru i-th row of V and decrease column counts; this + * may cause new column singletons to appear */ + ptr = vr_ptr[i]; + end = ptr + vr_len[i]; + for (; ptr < end; ptr++) + { if (--(cnt[j = sv_ind[ptr]]) == 1) + list[++ns] = j; + } + } + /* nucleus begins at k1-th row/column of U */ + if (k1 > n) + { /* U is upper triangular; no nucleus exist */ + goto done; + } + /*--------------------------------------------------------------*/ + /* process row singletons */ + /*--------------------------------------------------------------*/ + /* determine initial counts of rows of V and initialize list of + * active row singletons */ + ns = 0; /* number of active row singletons */ + for (i = 1; i <= n; i++) + { if (pp_ind[i] < k1) + { /* corresponding row of U is above its k1-th row; set its + * count to zero to prevent including it in active list */ + cnt[i] = 0; + } + else if ((cnt[i] = vr_len[i]) == 1) + list[++ns] = i; + } + /* process active row singletons */ + while (ns > 0) + { /* row singleton is in i-th row of V */ + i = list[ns--]; + /* find j-th column of V containing row singleton */ + ptr = vr_ptr[i]; + end = ptr + vr_len[i]; + for (; qq_inv[j = sv_ind[ptr]] > k2; ptr++) + /* nop */; + xassert(ptr < end); + /* permute rows and columns of U to move row singleton to + * position u[k2,k2] */ + ii = pp_ind[i]; + luf_swap_u_rows(k2, ii); + jj = qq_inv[j]; + luf_swap_u_cols(k2, jj); + /* nucleus size decreased */ + k2--; + /* walk thru j-th column of V and decrease row counts; this + * may cause new row singletons to appear */ + ptr = vc_ptr[j]; + end = ptr + vc_len[j]; + for (; ptr < end; ptr++) + { if (--(cnt[i = sv_ind[ptr]]) == 1) + list[++ns] = i; + } + } + /* nucleus ends at k2-th row/column of U */ + xassert(k1 < k2); +done: *k1_ = k1, *k2_ = k2; + return; +} + +/*********************************************************************** +* sgf_singl_phase - compute LU-factorization (singleton phase) +* +* It is assumed that on entry to the routine L = P'* F * P = F = I +* and matrix U = P'* V * Q' has the following structure (provided by +* the routine sgf_reduce_nuc): +* +* 1 k1 k2 n +* 1 a a a b b b b c c c +* . a a b b b b c c c +* . . a b b b b c c c +* k1 . . . * * * * d d d +* . . . * * * * d d d +* . . . * * * * d d d +* k2 . . . * * * * d d d +* . . . . . . . e e e +* . . . . . . . . e e +* n . . . . . . . . . e +* +* First, the routine performs (implicit) symmetric permutations of +* rows and columns of matrix U to place them in the following order: +* +* 1, 2, ..., k1-1; n, n-1, ..., k2+1; k1, k1+1, ..., k2 +* +* This changes the structure of matrix U as follows: +* +* 1 k1 k2' n +* 1 a a a c c c b b b b +* . a a c c c b b b b +* . . a c c c b b b b +* k1 . . . e . . . . . . +* . . . e e . . . . . +* . . . e e e . . . . +* k2'. . . d d d * * * * +* . . . d d d * * * * +* . . . d d d * * * * +* n . . . d d d * * * * +* +* where k2' = n - k2 + k1. +* +* Then the routine performs elementary gaussian transformations to +* eliminate subdiagonal elements in columns k1, ..., k2'-1 of U. The +* effect is the same as if the routine sgf_eliminate would be called +* for k = 1, ..., k2'-1 using diagonal elements u[k,k] as pivots. +* +* After elimination matrices L and U becomes the following: +* +* 1 k1 k2' n 1 k1 k2' n +* 1 1 . . . . . . . . . 1 a a a c c c b b b b +* . 1 . . . . . . . . . a a c c c b b b b +* . . 1 . . . . . . . . . a c c c b b b b +* k1 . . . 1 . . . . . . k1 . . . e . . . . . . +* . . . e'1 . . . . . . . . . e . . . . . +* . . . e'e'1 . . . . . . . . . e . . . . +* k2'. . . d'd'd'1 . . . k2'. . . . . . * * * * +* . . . d'd'd'. 1 . . . . . . . . * * * * +* . . . d'd'd'. . 1 . . . . . . . * * * * +* n . . . d'd'd'. . . 1 n . . . . . . * * * * +* +* matrix L matrix U +* +* where columns k1, ..., k2'-1 of L consist of subdiagonal elements +* of initial matrix U divided by pivots u[k,k]. +* +* On exit the routine returns k2', the elimination step number, from +* which computing of the factorization should be continued. Note that +* k2' = n+1 means that matrix U is already upper triangular. */ + +int sgf_singl_phase(LUF *luf, int k1, int k2, int updat, + int ind[/*1+n*/], double val[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int i, j, k, ptr, ptr1, end, len; + double piv; + /* (see routine sgf_reduce_nuc) */ + xassert((1 <= k1 && k1 < k2 && k2 <= n) + || (k1 == n+1 && k2 == n)); + /* perform symmetric permutations of rows/columns of U */ + for (k = k1; k <= k2; k++) + pp_ind[pp_inv[k]] = qq_inv[qq_ind[k]] = k - k2 + n; + for (k = k2+1; k <= n; k++) + pp_ind[pp_inv[k]] = qq_inv[qq_ind[k]] = n - k + k1; + for (k = 1; k <= n; k++) + pp_inv[pp_ind[k]] = qq_ind[qq_inv[k]] = k; + /* determine k2' */ + k2 = n - k2 + k1; + /* process rows and columns of V corresponding to rows and + * columns 1, ..., k1-1 of U */ + for (k = 1; k < k1; k++) + { /* k-th row of U = i-th row of V */ + i = pp_inv[k]; + /* find pivot u[k,k] = v[i,j] in i-th row of V */ + ptr = vr_ptr[i]; + end = ptr + vr_len[i]; + for (; qq_inv[sv_ind[ptr]] != k; ptr++) + /* nop */; + xassert(ptr < end); + /* store pivot */ + vr_piv[i] = sv_val[ptr]; + /* and remove it from i-th row of V */ + sv_ind[ptr] = sv_ind[end-1]; + sv_val[ptr] = sv_val[end-1]; + vr_len[i]--; + /* clear column of V corresponding to k-th column of U */ + vc_len[qq_ind[k]] = 0; + } + /* clear rows of V corresponding to rows k1, ..., k2'-1 of U */ + for (k = k1; k < k2; k++) + vr_len[pp_inv[k]] = 0; + /* process rows and columns of V corresponding to rows and + * columns k2', ..., n of U */ + for (k = k2; k <= n; k++) + { /* k-th row of U = i-th row of V */ + i = pp_inv[k]; + /* remove elements from i-th row of V that correspond to + * elements u[k,k1], ..., u[k,k2'-1] */ + ptr = ptr1 = vr_ptr[i]; + end = ptr + vr_len[i]; + for (; ptr < end; ptr++) + { if (qq_inv[sv_ind[ptr]] >= k2) + { sv_ind[ptr1] = sv_ind[ptr]; + sv_val[ptr1] = sv_val[ptr]; + ptr1++; + } + } + vr_len[i] = ptr1 - vr_ptr[i]; + /* k-th column of U = j-th column of V */ + j = qq_ind[k]; + /* remove elements from j-th column of V that correspond to + * elements u[1,k], ..., u[k1-1,k] */ + ptr = ptr1 = vc_ptr[j]; + end = ptr + vc_len[j]; + for (; ptr < end; ptr++) + { if (pp_ind[sv_ind[ptr]] >= k2) + /* element value is not needed in this case */ + sv_ind[ptr1++] = sv_ind[ptr]; + } + vc_len[j] = ptr1 - vc_ptr[j]; + } + /* process columns of V corresponding to columns k1, ..., k2'-1 + * of U, build columns of F */ + for (k = k1; k < k2; k++) + { /* k-th column of U = j-th column of V */ + j = qq_ind[k]; + /* remove elements from j-th column of V that correspond to + * pivot (diagonal) element u[k,k] and subdiagonal elements + * u[k+1,k], ..., u[n,k]; subdiagonal elements are stored for + * further addition to matrix F */ + len = 0; + piv = 0.0; + ptr = vc_ptr[j]; + end = ptr + vc_len[j]; + for (; ptr < end; ptr++) + { i = sv_ind[ptr]; /* v[i,j] */ + if (pp_ind[i] == k) + { /* store pivot v[i,j] = u[k,k] */ + piv = vr_piv[i] = sv_val[ptr]; + } + else if (pp_ind[i] > k) + { /* store subdiagonal element v[i,j] = u[i',k] */ + len++; + ind[len] = i; + val[len] = sv_val[ptr]; + } + } + /* clear j-th column of V = k-th column of U */ + vc_len[j] = 0; + /* build k-th column of L = j-th column of F */ + j = pp_inv[k]; + xassert(piv != 0.0); + if (len > 0) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, fc_ref-1+j, len); + for (ptr = fc_ptr[j], ptr1 = 1; ptr1 <= len; ptr++, ptr1++) + { sv_ind[ptr] = ind[ptr1]; + sv_val[ptr] = val[ptr1] / piv; + } + fc_len[j] = len; + } + } + /* if it is not planned to update matrix V, relocate all its + * non-active rows corresponding to rows 1, ..., k2'-1 of U to + * the right (static) part of SVA */ + if (!updat) + { for (k = 1; k < k2; k++) + { i = pp_inv[k]; + len = vr_len[i]; + if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_make_static(sva, vr_ref-1+i); + } + } + /* elimination steps 1, ..., k2'-1 have been performed */ + return k2; +} + +/*********************************************************************** +* sgf_choose_pivot - choose pivot element v[p,q] +* +* This routine chooses pivot element v[p,q], k <= p, q <= n, in the +* active submatrix of matrix V = P * U * Q, where k is the number of +* current elimination step, 1 <= k <= n. +* +* It is assumed that on entry to the routine matrix U = P'* V * Q' has +* the following partially triangularized form: +* +* 1 k n +* 1 x x x x x x x x x x +* . x x x x x x x x x +* . . x x x x x x x x +* . . . x x x x x x x +* k . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* n . . . . * * * * * * +* +* where rows and columns k, k+1, ..., n belong to the active submatrix +* (its elements are marked by '*'). +* +* Since the matrix U is not stored, the routine works with the matrix +* V = P * U * Q. It is assumed that the row-wise representation +* corresponds to the matrix V, but the column-wise representation +* corresponds to the active submatrix of the matrix V, i.e. elements, +* which are not in the active submatrix, are not included in column +* vectors. It is also assumed that each active row of the matrix V is +* in the set R[len], where len is the number of non-zeros in the row, +* and each active column of the matrix V is in the set C[len], where +* len is the number of non-zeros in the column (in the latter case +* only elements of the active submatrix are counted; such elements are +* marked by '*' on the figure above). +* +* For the reason of numerical stability the routine applies so called +* threshold pivoting proposed by J.Reid. It is assumed that an element +* v[i,j] can be selected as a pivot candidate if it is not very small +* (in magnitude) among other elements in the same row, i.e. if it +* satisfies to the stability condition |v[i,j]| >= tol * max|v[i,*]|, +* where 0 < tol < 1 is a given tolerance. +* +* In order to keep sparsity of the matrix V the routine uses Markowitz +* strategy, trying to choose such element v[p,q], which satisfies to +* the stability condition (see above) and has smallest Markowitz cost +* (nr[p]-1) * (nc[q]-1), where nr[p] and nc[q] are, resp., numbers of +* non-zeros in p-th row and q-th column of the active submatrix. +* +* In order to reduce the search, i.e. not to walk through all elements +* of the active submatrix, the routine uses a technique proposed by +* I.Duff. This technique is based on using the sets R[len] and C[len] +* of active rows and columns. +* +* If the pivot element v[p,q] has been chosen, the routine stores its +* indices to locations *p and *q and returns zero. Otherwise, non-zero +* is returned. */ + +int sgf_choose_pivot(SGF *sgf, int *p_, int *q_) +{ LUF *luf = sgf->luf; + int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *rs_head = sgf->rs_head; + int *rs_next = sgf->rs_next; + int *cs_head = sgf->cs_head; + int *cs_prev = sgf->cs_prev; + int *cs_next = sgf->cs_next; + double *vr_max = sgf->vr_max; + double piv_tol = sgf->piv_tol; + int piv_lim = sgf->piv_lim; + int suhl = sgf->suhl; + int i, i_ptr, i_end, j, j_ptr, j_end, len, min_i, min_j, min_len, + ncand, next_j, p, q; + double best, big, cost, temp; + /* no pivot candidate has been chosen so far */ + p = q = 0, best = DBL_MAX, ncand = 0; + /* if the active submatrix contains a column having the only + * non-zero element (column singleton), choose it as the pivot */ + j = cs_head[1]; + if (j != 0) + { xassert(vc_len[j] == 1); + p = sv_ind[vc_ptr[j]], q = j; + goto done; + } + /* if the active submatrix contains a row having the only + * non-zero element (row singleton), choose it as the pivot */ + i = rs_head[1]; + if (i != 0) + { xassert(vr_len[i] == 1); + p = i, q = sv_ind[vr_ptr[i]]; + goto done; + } + /* the active submatrix contains no singletons; walk thru its + * other non-empty rows and columns */ + for (len = 2; len <= n; len++) + { /* consider active columns containing len non-zeros */ + for (j = cs_head[len]; j != 0; j = next_j) + { /* save the number of next column of the same length */ + next_j = cs_next[j]; + /* find an element in j-th column, which is placed in the + * row with minimal number of non-zeros and satisfies to + * the stability condition (such element may not exist) */ + min_i = min_j = 0, min_len = INT_MAX; + for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + j_ptr < j_end; j_ptr++) + { /* get row index of v[i,j] */ + i = sv_ind[j_ptr]; + /* if i-th row is not shorter, skip v[i,j] */ + if (vr_len[i] >= min_len) + continue; + /* big := max|v[i,*]| */ + if ((big = vr_max[i]) < 0.0) + { /* largest magnitude is unknown; compute it */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + { if ((temp = sv_val[i_ptr]) < 0.0) + temp = -temp; + if (big < temp) + big = temp; + } + xassert(big > 0.0); + vr_max[i] = big; + } + /* find v[i,j] in i-th row */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + sv_ind[i_ptr] != j; i_ptr++) + /* nop */; + xassert(i_ptr < i_end); + /* if |v[i,j]| < piv_tol * max|v[i,*]|, skip v[i,j] */ + if ((temp = sv_val[i_ptr]) < 0.0) + temp = -temp; + if (temp < piv_tol * big) + continue; + /* v[i,j] is a better candidate */ + min_i = i, min_j = j, min_len = vr_len[i]; + /* if Markowitz cost of v[i,j] is not greater than + * (len-1)**2, v[i,j] can be chosen as the pivot right + * now; this heuristic reduces the search and works well + * in many cases */ + if (min_len <= len) + { p = min_i, q = min_j; + goto done; + } + } + /* j-th column has been scanned */ + if (min_i != 0) + { /* element v[min_i,min_j] is a next pivot candidate */ + ncand++; + /* compute its Markowitz cost */ + cost = (double)(min_len - 1) * (double)(len - 1); + /* if this element is better, choose it as the pivot */ + if (cost < best) + p = min_i, q = min_j, best = cost; + /* if piv_lim candidates were considered, terminate + * the search, because it is doubtful that a much better + * candidate will be found */ + if (ncand == piv_lim) + goto done; + } + else if (suhl) + { /* j-th column has no eligible elements that satisfy to + * the stability criterion; Uwe Suhl suggests to exclude + * such column from further considerations until it + * becomes a column singleton; in hard cases this may + * significantly reduce the time needed to choose the + * pivot element */ + sgf_deactivate_col(j); + cs_prev[j] = cs_next[j] = j; + } + } + /* consider active rows containing len non-zeros */ + for (i = rs_head[len]; i != 0; i = rs_next[i]) + { /* big := max|v[i,*]| */ + if ((big = vr_max[i]) < 0.0) + { /* largest magnitude is unknown; compute it */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + { if ((temp = sv_val[i_ptr]) < 0.0) + temp = -temp; + if (big < temp) + big = temp; + } + xassert(big > 0.0); + vr_max[i] = big; + } + /* find an element in i-th row, which is placed in the + * column with minimal number of non-zeros and satisfies to + * the stability condition (such element always exists) */ + min_i = min_j = 0, min_len = INT_MAX; + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + { /* get column index of v[i,j] */ + j = sv_ind[i_ptr]; + /* if j-th column is not shorter, skip v[i,j] */ + if (vc_len[j] >= min_len) + continue; + /* if |v[i,j]| < piv_tol * max|v[i,*]|, skip v[i,j] */ + if ((temp = sv_val[i_ptr]) < 0.0) + temp = -temp; + if (temp < piv_tol * big) + continue; + /* v[i,j] is a better candidate */ + min_i = i, min_j = j, min_len = vc_len[j]; + /* if Markowitz cost of v[i,j] is not greater than + * (len-1)**2, v[i,j] can be chosen as the pivot right + * now; this heuristic reduces the search and works well + * in many cases */ + if (min_len <= len) + { p = min_i, q = min_j; + goto done; + } + } + /* i-th row has been scanned */ + if (min_i != 0) + { /* element v[min_i,min_j] is a next pivot candidate */ + ncand++; + /* compute its Markowitz cost */ + cost = (double)(len - 1) * (double)(min_len - 1); + /* if this element is better, choose it as the pivot */ + if (cost < best) + p = min_i, q = min_j, best = cost; + /* if piv_lim candidates were considered, terminate + * the search, because it is doubtful that a much better + * candidate will be found */ + if (ncand == piv_lim) + goto done; + } + else + { /* this can never be */ + xassert(min_i != min_i); + } + } + } +done: /* report the pivot to the factorization routine */ + *p_ = p, *q_ = q; + return (p == 0); +} + +/*********************************************************************** +* sgf_eliminate - perform gaussian elimination +* +* This routine performs elementary gaussian transformations in order +* to eliminate subdiagonal elements in k-th column of matrix +* U = P'* V * Q' using pivot element u[k,k], where k is the number of +* current elimination step, 1 <= k <= n. +* +* The parameters p and q specify, resp., row and column indices of the +* pivot element v[p,q] = u[k,k]. +* +* On entry the routine assumes that partially triangularized matrices +* L = P'* F * P and U = P'* V * Q' have the following structure: +* +* 1 k n 1 k n +* 1 1 . . . . . . . . . 1 x x x x x x x x x x +* x 1 . . . . . . . . . x x x x x x x x x +* x x 1 . . . . . . . . . x x x x x x x x +* x x x 1 . . . . . . . . . x x x x x x x +* k x x x x 1 . . . . . k . . . . * * * * * * +* x x x x _ 1 . . . . . . . . # * * * * * +* x x x x _ . 1 . . . . . . . # * * * * * +* x x x x _ . . 1 . . . . . . # * * * * * +* x x x x _ . . . 1 . . . . . # * * * * * +* n x x x x _ . . . . 1 n . . . . # * * * * * +* +* matrix L matrix U +* +* where rows and columns k, k+1, ..., n of matrix U constitute the +* active submatrix. Elements to be eliminated are marked by '#', and +* other elements of the active submatrix are marked by '*'. May note +* that each eliminated non-zero element u[i,k] of matrix U gives +* corresponding non-zero element l[i,k] of matrix L (marked by '_'). +* +* Actually all operations are performed on matrix V. It is assumed +* that the row-wise representation corresponds to matrix V, but the +* column-wise representation corresponds to the active submatrix of +* matrix V (or, more precisely, to its pattern, because only row +* indices for columns of the active submatrix are used on this stage). +* +* Let u[k,k] = v[p,q] be the pivot. In order to eliminate subdiagonal +* elements u[i',k] = v[i,q], i'= k+1, k+2, ..., n, the routine applies +* the following elementary gaussian transformations: +* +* (i-th row of V) := (i-th row of V) - f[i,p] * (p-th row of V), +* +* where f[i,p] = v[i,q] / v[p,q] is a gaussian multiplier stored to +* p-th column of matrix F to keep the main equality A = F * V +* (corresponding elements l[i',k] of matrix L are marked by '_' on the +* figure above). +* +* NOTE: On entry to the routine the working arrays flag and work +* should contain zeros. This status is retained by the routine +* on exit. */ + +int sgf_eliminate(SGF *sgf, int p, int q) +{ LUF *luf = sgf->luf; + int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int *vr_cap = &sva->cap[vr_ref-1]; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *vc_cap = &sva->cap[vc_ref-1]; + int *rs_head = sgf->rs_head; + int *rs_prev = sgf->rs_prev; + int *rs_next = sgf->rs_next; + int *cs_head = sgf->cs_head; + int *cs_prev = sgf->cs_prev; + int *cs_next = sgf->cs_next; + double *vr_max = sgf->vr_max; + char *flag = sgf->flag; + double *work = sgf->work; + double eps_tol = sgf->eps_tol; + int nnz_diff = 0; + int fill, i, i_ptr, i_end, j, j_ptr, j_end, ptr, len, loc, loc1; + double vpq, fip, vij; + xassert(1 <= p && p <= n); + xassert(1 <= q && q <= n); + /* remove p-th row from the active set; this row will never + * return there */ + sgf_deactivate_row(p); + /* process p-th (pivot) row */ + ptr = 0; + for (i_end = (i_ptr = vr_ptr[p]) + vr_len[p]; + i_ptr < i_end; i_ptr++) + { /* get column index of v[p,j] */ + j = sv_ind[i_ptr]; + if (j == q) + { /* save pointer to pivot v[p,q] */ + ptr = i_ptr; + } + else + { /* store v[p,j], j != q, to working array */ + flag[j] = 1; + work[j] = sv_val[i_ptr]; + } + /* remove j-th column from the active set; q-th column will + * never return there while other columns will return to the + * active set with new length */ + if (cs_next[j] == j) + { /* j-th column was marked by the pivoting routine according + * to Uwe Suhl's suggestion and is already inactive */ + xassert(cs_prev[j] == j); + } + else + sgf_deactivate_col(j); + nnz_diff -= vc_len[j]; + /* find and remove v[p,j] from j-th column */ + for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + sv_ind[j_ptr] != p; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + sv_ind[j_ptr] = sv_ind[j_end-1]; + vc_len[j]--; + } + /* save pivot v[p,q] and remove it from p-th row */ + xassert(ptr > 0); + vpq = vr_piv[p] = sv_val[ptr]; + sv_ind[ptr] = sv_ind[i_end-1]; + sv_val[ptr] = sv_val[i_end-1]; + vr_len[p]--; + /* if it is not planned to update matrix V, relocate p-th row to + * the right (static) part of SVA */ + if (!sgf->updat) + { len = vr_len[p]; + if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_make_static(sva, vr_ref-1+p); + } + /* copy the pattern (row indices) of q-th column of the active + * submatrix (from which v[p,q] has been just removed) to p-th + * column of matrix F (without unity diagonal element) */ + len = vc_len[q]; + if (len > 0) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, fc_ref-1+p, len); + memcpy(&sv_ind[fc_ptr[p]], &sv_ind[vc_ptr[q]], + len * sizeof(int)); + fc_len[p] = len; + } + /* make q-th column of the active submatrix empty */ + vc_len[q] = 0; + /* transform non-pivot rows of the active submatrix */ + for (loc = fc_len[p]-1; loc >= 0; loc--) + { /* get row index of v[i,q] = row index of f[i,p] */ + i = sv_ind[fc_ptr[p] + loc]; + xassert(i != p); /* v[p,q] was removed */ + /* remove i-th row from the active set; this row will return + * there with new length */ + sgf_deactivate_row(i); + /* find v[i,q] in i-th row */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + sv_ind[i_ptr] != q; i_ptr++) + /* nop */; + xassert(i_ptr < i_end); + /* compute gaussian multiplier f[i,p] = v[i,q] / v[p,q] */ + fip = sv_val[fc_ptr[p] + loc] = sv_val[i_ptr] / vpq; + /* remove v[i,q] from i-th row */ + sv_ind[i_ptr] = sv_ind[i_end-1]; + sv_val[i_ptr] = sv_val[i_end-1]; + vr_len[i]--; + /* perform elementary gaussian transformation: + * (i-th row) := (i-th row) - f[i,p] * (p-th row) + * note that p-th row of V, which is in the working array, + * doesn't contain pivot v[p,q], and i-th row of V doesn't + * contain v[i,q] to be eliminated */ + /* walk thru i-th row and transform existing elements */ + fill = vr_len[p]; + for (i_end = (i_ptr = ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + { /* get column index and value of v[i,j] */ + j = sv_ind[i_ptr]; + vij = sv_val[i_ptr]; + if (flag[j]) + { /* v[p,j] != 0 */ + flag[j] = 0, fill--; + /* v[i,j] := v[i,j] - f[i,p] * v[p,j] */ + vij -= fip * work[j]; + if (-eps_tol < vij && vij < +eps_tol) + { /* new v[i,j] is close to zero; remove it from the + * active submatrix, i.e. replace it by exact zero */ + /* find and remove v[i,j] from j-th column */ + for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + sv_ind[j_ptr] != i; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + sv_ind[j_ptr] = sv_ind[j_end-1]; + vc_len[j]--; + continue; + } + } + /* keep new v[i,j] in i-th row */ + sv_ind[ptr] = j; + sv_val[ptr] = vij; + ptr++; + } + /* (new length of i-th row may decrease because of numerical + * cancellation) */ + vr_len[i] = len = ptr - vr_ptr[i]; + /* now flag[*] is the pattern of the set v[p,*] \ v[i,*], and + * fill is the number of non-zeros in this set */ + if (fill == 0) + { /* no fill-in occurs */ + /* walk thru p-th row and restore the column flags */ + for (i_end = (i_ptr = vr_ptr[p]) + vr_len[p]; + i_ptr < i_end; i_ptr++) + flag[sv_ind[i_ptr]] = 1; /* v[p,j] != 0 */ + goto skip; + } + /* up to fill new non-zero elements may appear in i-th row due + * to fill-in; reserve locations for these elements (note that + * actual length of i-th row is currently stored in len) */ + if (vr_cap[i] < len + fill) + { if (sva->r_ptr - sva->m_ptr < len + fill) + { sva_more_space(sva, len + fill); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vr_ref-1+i, len + fill, 0); + } + vr_len[i] += fill; + /* walk thru p-th row and add new elements to i-th row */ + for (loc1 = vr_len[p]-1; loc1 >= 0; loc1--) + { /* get column index of v[p,j] */ + j = sv_ind[vr_ptr[p] + loc1]; + if (!flag[j]) + { /* restore j-th column flag */ + flag[j] = 1; + /* v[i,j] was computed earlier on transforming existing + * elements of i-th row */ + continue; + } + /* v[i,j] := 0 - f[i,p] * v[p,j] */ + vij = - fip * work[j]; + if (-eps_tol < vij && vij < +eps_tol) + { /* new v[i,j] is close to zero; do not add it to the + * active submatrix, i.e. replace it by exact zero */ + continue; + } + /* add new v[i,j] to i-th row */ + sv_ind[ptr = vr_ptr[i] + (len++)] = j; + sv_val[ptr] = vij; + /* add new v[i,j] to j-th column */ + if (vc_cap[j] == vc_len[j]) + { /* we reserve extra locations in j-th column to reduce + * further relocations of that column */ +#if 1 /* FIXME */ + /* use control parameter to specify the number of extra + * locations reserved */ + int need = vc_len[j] + 10; +#endif + if (sva->r_ptr - sva->m_ptr < need) + { sva_more_space(sva, need); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vc_ref-1+j, need, 1); + } + sv_ind[vc_ptr[j] + (vc_len[j]++)] = i; + } + /* set final length of i-th row just transformed */ + xassert(len <= vr_len[i]); + vr_len[i] = len; +skip: /* return i-th row to the active set with new length */ + sgf_activate_row(i); + /* since i-th row has been changed, largest magnitude of its + * elements becomes unknown */ + vr_max[i] = -1.0; + } + /* walk thru p-th (pivot) row */ + for (i_end = (i_ptr = vr_ptr[p]) + vr_len[p]; + i_ptr < i_end; i_ptr++) + { /* get column index of v[p,j] */ + j = sv_ind[i_ptr]; + xassert(j != q); /* v[p,q] was removed */ + /* return j-th column to the active set with new length */ + if (cs_next[j] == j && vc_len[j] != 1) + { /* j-th column was marked by the pivoting routine and it is + * still not a column singleton, so leave it incative */ + xassert(cs_prev[j] == j); + } + else + sgf_activate_col(j); + nnz_diff += vc_len[j]; + /* restore zero content of the working arrays */ + flag[j] = 0; + work[j] = 0.0; + } + /* return the difference between the numbers of non-zeros in the + * active submatrix on entry and on exit, resp. */ + return nnz_diff; +} + +/*********************************************************************** +* sgf_dense_lu - compute dense LU-factorization with full pivoting +* +* This routine performs Gaussian elimination with full pivoting to +* compute dense LU-factorization of the specified matrix A of order n +* in the form: +* +* A = P * L * U * Q, (1) +* +* where L is lower triangular matrix with unit diagonal, U is upper +* triangular matrix, P and Q are permutation matrices. +* +* On entry to the routine elements of matrix A = (a[i,j]) should be +* placed in the array elements a[0], ..., a[n^2-1] in dense row-wise +* format. On exit from the routine matrix A is replaced by factors L +* and U as follows: +* +* u[1,1] u[1,2] ... u[1,n-1] u[1,n] +* l[2,1] u[2,2] ... u[2,n-1] u[2,n] +* . . . . . . . . . . . . . . +* l[n-1,1] l[n-1,2] u[n-1,n-1] u[n-1,n] +* l[n,1] l[n,2] ... l[n,n-1] u[n,n] +* +* The unit diagonal elements of L are not stored. +* +* Information on permutations of rows and columns of active submatrix +* during factorization is accumulated by the routine as follows. Every +* time the routine permutes rows i and i' or columns j and j', it also +* permutes elements r[i-1] and r[i'-1] or c[j-1] and c[j'-1], resp. +* Thus, on entry to the routine elements r[0], r[1], ..., r[n-1] and +* c[0], c[1], ..., c[n-1] should be initialized by some integers that +* identify rows and columns of the original matrix A. +* +* If the factorization has been successfully computed, the routine +* returns zero. Otherwise, if on k-th elimination step, 1 <= k <= n, +* all elements of the active submatrix are close to zero, the routine +* returns k, in which case a partial factorization is stored in the +* array a. */ + +int sgf_dense_lu(int n, double a_[], int r[], int c[], double eps) +{ /* non-optimized version */ + int i, j, k, p, q, ref; + double akk, big, temp; +# define a(i,j) a_[(i)*n+(j)] + /* initially U = A, L = P = Q = I */ + /* main elimination loop */ + for (k = 0; k < n; k++) + { /* choose pivot u[p,q], k <= p, q <= n */ + p = q = -1, big = eps; + for (i = k; i < n; i++) + { for (j = k; j < n; j++) + { /* temp = |u[i,j]| */ + if ((temp = a(i,j)) < 0.0) + temp = -temp; + if (big < temp) + p = i, q = j, big = temp; + } + } + if (p < 0) + { /* k-th elimination step failed */ + return k+1; + } + /* permute rows k and p */ + if (k != p) + { for (j = 0; j < n; j++) + temp = a(k,j), a(k,j) = a(p,j), a(p,j) = temp; + ref = r[k], r[k] = r[p], r[p] = ref; + } + /* permute columns k and q */ + if (k != q) + { for (i = 0; i < n; i++) + temp = a(i,k), a(i,k) = a(i,q), a(i,q) = temp; + ref = c[k], c[k] = c[q], c[q] = ref; + } + /* now pivot is in position u[k,k] */ + akk = a(k,k); + /* eliminate subdiagonal elements u[k+1,k], ..., u[n,k] */ + for (i = k+1; i < n; i++) + { if (a(i,k) != 0.0) + { /* gaussian multiplier l[i,k] := u[i,k] / u[k,k] */ + temp = (a(i,k) /= akk); + /* (i-th row) := (i-th row) - l[i,k] * (k-th row) */ + for (j = k+1; j < n; j++) + a(i,j) -= temp * a(k,j); + } + } + } +# undef a + return 0; +} + +/*********************************************************************** +* sgf_dense_phase - compute LU-factorization (dense phase) +* +* This routine performs dense phase of computing LU-factorization. +* +* The aim is two-fold. First, the main factorization routine switches +* to dense phase when the active submatrix is relatively dense, so +* using dense format allows significantly reduces overheads needed to +* maintain sparse data structures. And second, that is more important, +* on dense phase full pivoting is used (rather than partial pivoting) +* that allows improving numerical stability, since round-off errors +* tend to increase on last steps of the elimination process. +* +* On entry the routine assumes that elimination steps 1, 2, ..., k-1 +* have been performed, so partially transformed matrices L = P'* F * P +* and U = P'* V * Q' have the following structure: +* +* 1 k n 1 k n +* 1 1 . . . . . . . . . 1 x x x x x x x x x x +* x 1 . . . . . . . . . x x x x x x x x x +* x x 1 . . . . . . . . . x x x x x x x x +* x x x 1 . . . . . . . . . x x x x x x x +* k x x x x 1 . . . . . k . . . . * * * * * * +* x x x x . 1 . . . . . . . . * * * * * * +* x x x x . . 1 . . . . . . . * * * * * * +* x x x x . . . 1 . . . . . . * * * * * * +* x x x x . . . . 1 . . . . . * * * * * * +* n x x x x . . . . . 1 n . . . . * * * * * * +* +* matrix L matrix U +* +* where rows and columns k, k+1, ..., n of matrix U constitute the +* active submatrix A~, whose elements are marked by '*'. +* +* The routine copies the active submatrix A~ to a working array in +* dense format, compute dense factorization A~ = P~* L~* U~* Q~ using +* full pivoting, and then copies non-zero elements of factors L~ and +* U~ back to factors L and U (more precisely, to factors F and V). +* +* If the factorization has been successfully computed, the routine +* returns zero. Otherwise, if on k-th elimination step, 1 <= k <= n, +* all elements of the active submatrix are close to zero, the routine +* returns k (information on linearly dependent rows/columns in this +* case is provided by matrices P and Q). */ + +int sgf_dense_phase(LUF *luf, int k, int updat) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int *fc_cap = &sva->cap[fc_ref-1]; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int *vr_cap = &sva->cap[vr_ref-1]; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_inv = luf->pp_inv; + int *pp_ind = luf->pp_ind; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int a_end, a_ptr, end, i, ia, ii, j, ja, jj, ka, len, na, ne, + need, ptr; + double *a_; + xassert(1 <= k && k <= n); + /* active columns of V are not longer needed; make them empty */ + for (jj = k; jj <= n; jj++) + { /* jj is number of active column of U = P'* V * Q' */ + vc_len[qq_ind[jj]] = 0; + } + /* determine order of active submatrix A~ of matrix U */ + na = n - k + 1; + xassert(1 <= na && na <= n); + /* determine number of elements in dense triangular factor (L~ or + * U~), except diagonal elements */ + ne = na * (na - 1) / 2; + /* we allocate active submatrix A~ in free (middle) part of SVA; + * to avoid defragmentation that could destroy A~ we also should + * reserve ne locations to build rows of V from rows of U~ and ne + * locations to build columns of F from columns of L~ */ + need = na * na + ne + ne; + if (sva->r_ptr - sva->m_ptr < need) + { sva_more_space(sva, need); + sv_ind = sva->ind; + sv_val = sva->val; + } + /* free (middle) part of SVA is structured as follows: + * end of left (dynamic) part + * ne free locations for new rows of V + * na free locations for active submatrix A~ + * unused locations, if any + * ne free locations for new columns of F + * beginning of right (static) part */ + a_ptr = sva->m_ptr + ne; + a_end = a_ptr + na * na; + /* copy active submatrix A~ from matrix V to working array in + * dense row-wise format */ + a_ = &sva->val[a_ptr]; +# define a(ia, ja) a_[((ia) - 1) * na + ((ja) - 1)] + for (ia = 1; ia <= na; ia++) + { /* clear ia-th row of A~ */ + for (ja = 1; ja <= na; ja++) + a(ia, ja) = 0.0; + /* ia-th row of A~ = (k-1+ia)-th row of U = i-th row of V */ + i = pp_inv[k-1+ia]; + ptr = vr_ptr[i]; + end = ptr + vr_len[i]; + for (; ptr < end; ptr++) + a(ia, qq_inv[sv_ind[ptr]]-k+1) = sv_val[ptr]; + /* i-th row of V is no longer needed; make it empty */ + vr_len[i] = 0; + } + /* compute dense factorization A~ = P~* L~* U~* Q~ */ +#if 1 /* FIXME: epsilon tolerance */ + ka = sgf_dense_lu(na, &a(1, 1), &pp_inv[k], &qq_ind[k], 1e-20); +#endif + /* rows of U with numbers pp_inv[k, k+1, ..., n] were permuted + * due to row permutations of A~; update matrix P using P~ */ + for (ii = k; ii <= n; ii++) + pp_ind[pp_inv[ii]] = ii; + /* columns of U with numbers qq_ind[k, k+1, ..., n] were permuted + * due to column permutations of A~; update matrix Q using Q~ */ + for (jj = k; jj <= n; jj++) + qq_inv[qq_ind[jj]] = jj; + /* check if dense factorization is complete */ + if (ka != 0) + { /* A~ is singular to working precision */ + /* information on linearly dependent rows/columns is provided + * by matrices P and Q */ + xassert(1 <= ka && ka <= na); + return k - 1 + ka; + } + /* build new rows of V from rows of U~ */ + for (ia = 1; ia <= na; ia++) + { /* ia-th row of U~ = (k-1+ia)-th row of U = i-th row of V */ + i = pp_inv[k-1+ia]; + xassert(vr_len[i] == 0); + /* store diagonal element u~[ia,ia] */ + vr_piv[i] = a(ia, ia); + /* determine number of non-zero non-diagonal elements in ia-th + * row of U~ */ + len = 0; + for (ja = ia+1; ja <= na; ja++) + { if (a(ia, ja) != 0.0) + len++; + } + /* reserve len locations for i-th row of matrix V in left + * (dynamic) part of SVA */ + if (vr_cap[i] < len) + { /* there should be enough room in free part of SVA */ + xassert(sva->r_ptr - sva->m_ptr >= len); + sva_enlarge_cap(sva, vr_ref-1+i, len, 0); + /* left part of SVA should not overlap matrix A~ */ + xassert(sva->m_ptr <= a_ptr); + } + /* copy non-zero non-diaginal elements of ia-th row of U~ to + * i-th row of V */ + ptr = vr_ptr[i]; + for (ja = ia+1; ja <= na; ja++) + { if (a(ia, ja) != 0.0) + { sv_ind[ptr] = qq_ind[k-1+ja]; + sv_val[ptr] = a(ia, ja); + ptr++; + } + } + xassert(ptr - vr_ptr[i] == len); + vr_len[i] = len; + } + /* build new columns of F from columns of L~ */ + for (ja = 1; ja <= na; ja++) + { /* ja-th column of L~ = (k-1+ja)-th column of L = j-th column + * of F */ + j = pp_inv[k-1+ja]; + xassert(fc_len[j] == 0); + xassert(fc_cap[j] == 0); + /* determine number of non-zero non-diagonal elements in ja-th + * column of L~ */ + len = 0; + for (ia = ja+1; ia <= na; ia++) + { if (a(ia, ja) != 0.0) + len++; + } + /* reserve len locations for j-th column of matrix F in right + * (static) part of SVA */ + /* there should be enough room in free part of SVA */ + xassert(sva->r_ptr - sva->m_ptr >= len); + if (len > 0) + sva_reserve_cap(sva, fc_ref-1+j, len); + /* right part of SVA should not overlap matrix A~ */ + xassert(a_end <= sva->r_ptr); + /* copy non-zero non-diagonal elements of ja-th column of L~ + * to j-th column of F */ + ptr = fc_ptr[j]; + for (ia = ja+1; ia <= na; ia++) + { if (a(ia, ja) != 0.0) + { sv_ind[ptr] = pp_inv[k-1+ia]; + sv_val[ptr] = a(ia, ja); + ptr++; + } + } + xassert(ptr - fc_ptr[j] == len); + fc_len[j] = len; + } + /* factors L~ and U~ are no longer needed */ +# undef a + /* if it is not planned to update matrix V, relocate all its new + * rows to the right (static) part of SVA */ + if (!updat) + { for (ia = 1; ia <= na; ia++) + { i = pp_inv[k-1+ia]; + len = vr_len[i]; + if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_make_static(sva, vr_ref-1+i); + } + } + return 0; +} + +/*********************************************************************** +* sgf_factorize - compute LU-factorization (main routine) +* +* This routine computes sparse LU-factorization of specified matrix A +* using Gaussian elimination. +* +* On entry to the routine matrix V = A should be stored in column-wise +* format. +* +* If the factorization has been successfully computed, the routine +* returns zero. Otherwise, if on k-th elimination step, 1 <= k <= n, +* all elements of the active submatrix are close to zero, the routine +* returns k (information on linearly dependent rows/columns in this +* case is provided by matrices P and Q). */ + +int sgf_factorize(SGF *sgf, int singl) +{ LUF *luf = sgf->luf; + int n = luf->n; + SVA *sva = luf->sva; + int vr_ref = luf->vr_ref; + int *vr_len = &sva->len[vr_ref-1]; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int *rs_head = sgf->rs_head; + int *rs_prev = sgf->rs_prev; + int *rs_next = sgf->rs_next; + int *cs_head = sgf->cs_head; + int *cs_prev = sgf->cs_prev; + int *cs_next = sgf->cs_next; + double *vr_max = sgf->vr_max; + char *flag = sgf->flag; + double *work = sgf->work; + int i, j, k, k1, k2, p, q, nnz; + /* build matrix V = A in row-wise format */ + luf_build_v_rows(luf, rs_prev); + /* P := Q := I, so V = U = A, F = L = I */ + for (k = 1; k <= n; k++) + { vr_piv[k] = 0.0; + pp_ind[k] = pp_inv[k] = qq_ind[k] = qq_inv[k] = k; + } +#ifdef GLP_DEBUG + sva_check_area(sva); + luf_check_all(luf, 1); +#endif + /* perform singleton phase, if required */ + if (!singl) + { /* assume that nucleus is entire matrix U */ + k2 = 1; + } + else + { /* minimize nucleus size */ + sgf_reduce_nuc(luf, &k1, &k2, rs_prev, rs_next); +#ifdef GLP_DEBUG + xprintf("n = %d; k1 = %d; k2 = %d\n", n, k1, k2); +#endif + /* perform singleton phase */ + k2 = sgf_singl_phase(luf, k1, k2, sgf->updat, rs_prev, work); + } +#ifdef GLP_DEBUG + sva_check_area(sva); + luf_check_all(luf, k2); +#endif + /* initialize working arrays */ + rs_head[0] = cs_head[0] = 0; + for (k = 1; k <= n; k++) + { rs_head[k] = cs_head[k] = 0; + vr_max[k] = -1.0; + flag[k] = 0; + work[k] = 0.0; + } + /* build lists of active rows and columns of matrix V; determine + * number of non-zeros in initial active submatrix */ + nnz = 0; + for (k = k2; k <= n; k++) + { i = pp_inv[k]; + sgf_activate_row(i); + nnz += vr_len[i]; + j = qq_ind[k]; + sgf_activate_col(j); + } + /* main factorization loop */ + for (k = k2; k <= n; k++) + { int na; + double den; + /* calculate density of active submatrix */ + na = n - k + 1; /* order of active submatrix */ + den = (double)nnz / (double)(na * na); + /* if active submatrix is relatively dense, switch to dense + * phase */ +#if 1 /* FIXME */ + if (na >= 5 && den >= 0.71) + { +#ifdef GLP_DEBUG + xprintf("na = %d; nnz = %d; den = %g\n", na, nnz, den); +#endif + break; + } +#endif + /* choose pivot v[p,q] */ + if (sgf_choose_pivot(sgf, &p, &q) != 0) + return k; /* failure */ + /* u[i,j] = v[p,q], k <= i, j <= n */ + i = pp_ind[p]; + xassert(k <= i && i <= n); + j = qq_inv[q]; + xassert(k <= j && j <= n); + /* move u[i,j] to position u[k,k] by implicit permutations of + * rows and columns of matrix U */ + luf_swap_u_rows(k, i); + luf_swap_u_cols(k, j); + /* perform gaussian elimination */ + nnz += sgf_eliminate(sgf, p, q); + } +#if 1 /* FIXME */ + if (k <= n) + { /* continue computing factorization in dense mode */ +#ifdef GLP_DEBUG + sva_check_area(sva); + luf_check_all(luf, k); +#endif + k = sgf_dense_phase(luf, k, sgf->updat); + if (k != 0) + return k; /* failure */ + } +#endif +#ifdef GLP_DEBUG + sva_check_area(sva); + luf_check_all(luf, n+1); +#endif + /* defragment SVA; currently all columns of V are empty, so they + * will have zero capacity as required by luf_build_v_cols */ + sva_defrag_area(sva); + /* build matrix F in row-wise format */ + luf_build_f_rows(luf, rs_head); + /* build matrix V in column-wise format */ + luf_build_v_cols(luf, sgf->updat, rs_head); + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/sgf.h b/resources/3rdparty/glpk-4.53/src/bflib/sgf.h new file mode 100644 index 000000000..dc64f957c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/sgf.h @@ -0,0 +1,203 @@ +/* sgf.h (sparse Gaussian factorizer) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef SGF_H +#define SGF_H + +#include "luf.h" + +typedef struct SGF SGF; + +struct SGF +{ /* sparse Gaussian factorizer workspace */ + LUF *luf; + /* LU-factorization being computed */ + /*--------------------------------------------------------------*/ + /* to efficiently choose pivot elements according to Markowitz + * strategy, the search technique proposed by Iain Duff is used; + * it is based on using two families of sets {R[0], ..., R[n]} + * and {C[0], ..., C[n]}, where R[k] and C[k], 0 <= k <= n, are, + * respectively, sets of rows and columns of the active submatrix + * of matrix V having k non-zeros (i.e. whose length is k); each + * set R[k] and C[k] is implemented as a doubly linked list */ + int *rs_head; /* int rs_head[1+n]; */ + /* rs_head[k], 0 <= k <= n, is the number of first row, which + * has k non-zeros in the active submatrix */ + int *rs_prev; /* int rs_prev[1+n]; */ + /* rs_prev[0] is not used; + * rs_prev[i], 1 <= i <= n, is the number of previous row, which + * has the same number of non-zeros as i-th row; + * rs_prev[i] < 0 means that i-th row is inactive */ + int *rs_next; /* int rs_next[1+n]; */ + /* rs_next[0] is not used; + * rs_next[i], 1 <= i <= n, is the number of next row, which has + * the same number of non-zeros as i-th row; + * rs_next[i] < 0 means that i-th row is inactive */ + int *cs_head; /* int cs_head[1+n]; */ + /* cs_head[k], 0 <= k <= n, is the number of first column, which + * has k non-zeros in the active submatrix */ + int *cs_prev; /* int cs_prev[1+n]; */ + /* cs_prev[0] is not used; + * cs_prev[j], 1 <= j <= n, is the number of previous column, + * which has the same number of non-zeros as j-th column; + * cs_prev[j] < 0 means that j-th column is inactive */ + int *cs_next; /* int cs_next[1+n]; */ + /* cs_next[0] is not used; + * cs_next[j], 1 <= j <= n, is the number of next column, which + * has the same number of non-zeros as j-th column; + * cs_next[j] < 0 means that j-th column is inactive */ + /* NOTE: cs_prev[j] = cs_next[j] = j means that j-th column was + * temporarily removed from corresponding set C[k] by the + * pivoting routine according to Uwe Suhl's heuristic */ + /*--------------------------------------------------------------*/ + /* working arrays */ + double *vr_max; /* int vr_max[1+n]; */ + /* vr_max[0] is not used; + * vr_max[i], 1 <= i <= n, is used only if i-th row of matrix V + * is active (i.e. belongs to the active submatrix), and is the + * largest magnitude of elements in that row; if vr_max[i] < 0, + * the largest magnitude is unknown yet */ + char *flag; /* char flag[1+n]; */ + /* boolean working array */ + double *work; /* double work[1+n]; */ + /* floating-point working array */ + /*--------------------------------------------------------------*/ + /* control parameters */ + int updat; + /* if this flag is set, the matrix V is assumed to be updatable; + * in this case factorized (non-active) part of V is stored in + * the left part of SVA rather than in its right part */ + double piv_tol; + /* threshold pivoting tolerance, 0 < piv_tol < 1; element v[i,j] + * of the active submatrix fits to be pivot if it satisfies to + * the stability criterion |v[i,j]| >= piv_tol * max |v[i,*]|, + * i.e. if it is not very small in the magnitude among other + * elements in the same row; decreasing this parameter gives + * better sparsity at the expense of numerical accuracy and vice + * versa */ + int piv_lim; + /* maximal allowable number of pivot candidates to be considered; + * if piv_lim pivot candidates have been considered, the pivoting + * routine terminates the search with the best candidate found */ + int suhl; + /* if this flag is set, the pivoting routine applies a heuristic + * proposed by Uwe Suhl: if a column of the active submatrix has + * no eligible pivot candidates (i.e. all its elements do not + * satisfy to the stability criterion), the routine excludes it + * from futher consideration until it becomes column singleton; + * in many cases this allows reducing the time needed to choose + * the pivot */ + double eps_tol; + /* epsilon tolerance; each element of the active submatrix, whose + * magnitude is less than eps_tol, is replaced by exact zero */ +#if 0 /* FIXME */ + double den_lim; + /* density limit; if the density of the active submatrix reaches + * this limit, the factorization routine switches from sparse to + * dense mode */ +#endif +}; + +#define sgf_activate_row(i) \ + do \ + { int len = vr_len[i]; \ + rs_prev[i] = 0; \ + rs_next[i] = rs_head[len]; \ + if (rs_next[i] != 0) \ + rs_prev[rs_next[i]] = i; \ + rs_head[len] = i; \ + } while (0) +/* include i-th row of matrix V in active set R[len] */ + +#define sgf_deactivate_row(i) \ + do \ + { if (rs_prev[i] == 0) \ + rs_head[vr_len[i]] = rs_next[i]; \ + else \ + rs_next[rs_prev[i]] = rs_next[i]; \ + if (rs_next[i] == 0) \ + ; \ + else \ + rs_prev[rs_next[i]] = rs_prev[i]; \ + rs_prev[i] = rs_next[i] = -1; \ + } while (0) +/* remove i-th row of matrix V from active set R[len] */ + +#define sgf_activate_col(j) \ + do \ + { int len = vc_len[j]; \ + cs_prev[j] = 0; \ + cs_next[j] = cs_head[len]; \ + if (cs_next[j] != 0) \ + cs_prev[cs_next[j]] = j; \ + cs_head[len] = j; \ + } while (0) +/* include j-th column of matrix V in active set C[len] */ + +#define sgf_deactivate_col(j) \ + do \ + { if (cs_prev[j] == 0) \ + cs_head[vc_len[j]] = cs_next[j]; \ + else \ + cs_next[cs_prev[j]] = cs_next[j]; \ + if (cs_next[j] == 0) \ + ; \ + else \ + cs_prev[cs_next[j]] = cs_prev[j]; \ + cs_prev[j] = cs_next[j] = -1; \ + } while (0) +/* remove j-th column of matrix V from active set C[len] */ + +#define sgf_reduce_nuc _glp_sgf_reduce_nuc +void sgf_reduce_nuc(LUF *luf, int *k1, int *k2, int cnt[/*1+n*/], + int list[/*1+n*/]); +/* initial reordering to minimize nucleus size */ + +#define sgf_singl_phase _glp_sgf_singl_phase +int sgf_singl_phase(LUF *luf, int k1, int k2, int updat, + int ind[/*1+n*/], double val[/*1+n*/]); +/* compute LU-factorization (singleton phase) */ + +#define sgf_choose_pivot _glp_sgf_choose_pivot +int sgf_choose_pivot(SGF *sgf, int *p, int *q); +/* choose pivot element v[p,q] */ + +#define sgf_eliminate _glp_sgf_eliminate +int sgf_eliminate(SGF *sgf, int p, int q); +/* perform gaussian elimination */ + +#define sgf_dense_lu _glp_sgf_dense_lu +int sgf_dense_lu(int n, double a[], int r[], int c[], double eps); +/* compute dense LU-factorization with full pivoting */ + +#define sgf_dense_phase _glp_sgf_dense_phase +int sgf_dense_phase(LUF *luf, int k, int updat); +/* compute LU-factorization (dense phase) */ + +#define sgf_factorize _glp_sgf_factorize +int sgf_factorize(SGF *sgf, int singl); +/* compute LU-factorization (main routine) */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/sva.c b/resources/3rdparty/glpk-4.53/src/bflib/sva.c new file mode 100644 index 000000000..264f9e15f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/sva.c @@ -0,0 +1,568 @@ +/* sva.c (sparse vector area) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "sva.h" + +/*********************************************************************** +* sva_create_area - create sparse vector area (SVA) +* +* This routine creates the sparse vector area (SVA), which initially +* is empty. +* +* The parameter n_max specifies the initial number of vectors that can +* be allocated in the SVA, n_max > 0. +* +* The parameter size specifies the initial number of free locations in +* the SVA, size > 0. +* +* On exit the routine returns a pointer to the SVA created. */ + +SVA *sva_create_area(int n_max, int size) +{ SVA *sva; + xassert(0 < n_max && n_max < INT_MAX); + xassert(0 < size && size < INT_MAX); + sva = talloc(1, SVA); + sva->n_max = n_max; + sva->n = 0; + sva->ptr = talloc(1+n_max, int); + sva->len = talloc(1+n_max, int); + sva->cap = talloc(1+n_max, int); + sva->size = size; + sva->m_ptr = 1; + sva->r_ptr = size+1; + sva->head = sva->tail = 0; + sva->prev = talloc(1+n_max, int); + sva->next = talloc(1+n_max, int); + sva->ind = talloc(1+size, int); + sva->val = talloc(1+size, double); + sva->talky = 0; + return sva; +} + +/*********************************************************************** +* sva_alloc_vecs - allocate new vectors in SVA +* +* This routine allocates nnn new empty vectors, nnn > 0, in the sparse +* vector area (SVA). +* +* The new vectors are assigned reference numbers k, k+1, ..., k+nnn-1, +* where k is a reference number assigned to the very first new vector, +* which is returned by the routine on exit. */ + +int sva_alloc_vecs(SVA *sva, int nnn) +{ int n = sva->n; + int n_max = sva->n_max; + int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + int *prev = sva->prev; + int *next = sva->next; + int k, new_n; +#if 1 + if (sva->talky) + xprintf("sva_alloc_vecs: nnn = %d\n", nnn); +#endif + xassert(nnn > 0); + /* determine new number of vectors in SVA */ + new_n = n + nnn; + xassert(new_n > n); + if (n_max < new_n) + { /* enlarge the SVA arrays */ + while (n_max < new_n) + { n_max += n_max; + xassert(n_max > 0); + } + sva->n_max = n_max; + sva->ptr = ptr = trealloc(ptr, 1+n_max, int); + sva->len = len = trealloc(len, 1+n_max, int); + sva->cap = cap = trealloc(cap, 1+n_max, int); + sva->prev = prev = trealloc(prev, 1+n_max, int); + sva->next = next = trealloc(next, 1+n_max, int); + } + /* initialize new vectors */ + sva->n = new_n; + for (k = n+1; k <= new_n; k++) + { ptr[k] = len[k] = cap[k] = 0; + prev[k] = next[k] = -1; + } +#if 1 + if (sva->talky) + xprintf("now sva->n_max = %d, sva->n = %d\n", + sva->n_max, sva->n); +#endif + /* return reference number of very first new vector */ + return n+1; +} + +/*********************************************************************** +* sva_resize_area - change size of SVA storage +* +* This routine increases or decrases the size of the SVA storage by +* reallocating it. +* +* The parameter delta specifies the number of location by which the +* current size of the SVA storage should be increased (if delta > 0) +* or decreased (if delta < 0). Note that if delta is negative, it +* should not be less than the current size of the middle part. +* +* As a result of this operation the size of the middle part of SVA is +* increased/decreased by delta locations. +* +* NOTE: This operation changes ptr[k] for all vectors stored in the +* right part of SVA. */ + +void sva_resize_area(SVA *sva, int delta) +{ int n = sva->n; + int *ptr = sva->ptr; + int size = sva->size; + int m_ptr = sva->m_ptr; + int r_ptr = sva->r_ptr; + int k, r_size; +#if 1 + if (sva->talky) + xprintf("sva_resize_area: delta = %d\n", delta); +#endif + xassert(delta != 0); + /* determine size of the right part, in locations */ + r_size = size - r_ptr + 1; + /* relocate the right part in case of negative delta */ + if (delta < 0) + { xassert(delta >= m_ptr - r_ptr); + sva->r_ptr += delta; + memmove(&sva->ind[sva->r_ptr], &sva->ind[r_ptr], + r_size * sizeof(int)); + memmove(&sva->val[sva->r_ptr], &sva->val[r_ptr], + r_size * sizeof(double)); + } + /* reallocate the storage arrays */ + xassert(delta < INT_MAX - sva->size); + sva->size += delta; + sva->ind = trealloc(sva->ind, 1+sva->size, int); + sva->val = trealloc(sva->val, 1+sva->size, double); + /* relocate the right part in case of positive delta */ + if (delta > 0) + { sva->r_ptr += delta; + memmove(&sva->ind[sva->r_ptr], &sva->ind[r_ptr], + r_size * sizeof(int)); + memmove(&sva->val[sva->r_ptr], &sva->val[r_ptr], + r_size * sizeof(double)); + } + /* update pointers to vectors stored in the right part */ + for (k = 1; k <= n; k++) + { if (ptr[k] >= r_ptr) + ptr[k] += delta; + } +#if 1 + if (sva->talky) + xprintf("now sva->size = %d\n", sva->size); +#endif + return; +} + +/*********************************************************************** +* sva_defrag_area - defragment left part of SVA +* +* This routine performs "garbage" collection to defragment the left +* part of SVA. +* +* NOTE: This operation may change ptr[k] and cap[k] for all vectors +* stored in the left part of SVA. */ + +void sva_defrag_area(SVA *sva) +{ int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + int *prev = sva->prev; + int *next = sva->next; + int *ind = sva->ind; + double *val = sva->val; + int k, next_k, ptr_k, len_k, m_ptr, head, tail; +#if 1 + if (sva->talky) + { xprintf("sva_defrag_area:\n"); + xprintf("before defragmenting = %d %d %d\n", sva->m_ptr - 1, + sva->r_ptr - sva->m_ptr, sva->size + 1 - sva->r_ptr); + } +#endif + m_ptr = 1; + head = tail = 0; + /* walk through the linked list of vectors stored in the left + * part of SVA */ + for (k = sva->head; k != 0; k = next_k) + { /* save number of next vector in the list */ + next_k = next[k]; + /* determine length of k-th vector */ + len_k = len[k]; + if (len_k == 0) + { /* k-th vector is empty; remove it from the left part */ + ptr[k] = cap[k] = 0; + prev[k] = next[k] = -1; + } + else + { /* determine pointer to first location of k-th vector */ + ptr_k = ptr[k]; + xassert(m_ptr <= ptr_k); + /* relocate k-th vector to the beginning of the left part, + * if necessary */ + if (m_ptr < ptr_k) + { memmove(&ind[m_ptr], &ind[ptr_k], + len_k * sizeof(int)); + memmove(&val[m_ptr], &val[ptr_k], + len_k * sizeof(double)); + ptr[k] = m_ptr; + } + /* remove unused locations from k-th vector */ + cap[k] = len_k; + /* the left part of SVA has been enlarged */ + m_ptr += len_k; + /* add k-th vector to the end of the new linked list */ + prev[k] = tail; + next[k] = 0; + if (head == 0) + head = k; + else + next[tail] = k; + tail = k; + } + } + /* set new pointer to the middle part of SVA */ + xassert(m_ptr <= sva->r_ptr); + sva->m_ptr = m_ptr; + /* set new head and tail of the linked list */ + sva->head = head; + sva->tail = tail; +#if 1 + if (sva->talky) + xprintf("after defragmenting = %d %d %d\n", sva->m_ptr - 1, + sva->r_ptr - sva->m_ptr, sva->size + 1 - sva->r_ptr); +#endif + return; +} + +/*********************************************************************** +* sva_more_space - increase size of middle (free) part of SVA +* +* This routine increases the size of the middle (free) part of the +* sparse vector area (SVA). +* +* The parameter m_size specifies the minimal size, in locations, of +* the middle part to be provided. This new size should be greater than +* the current size of the middle part. +* +* First, the routine defragments the left part of SVA. Then, if the +* size of the left part has not sufficiently increased, the routine +* increases the total size of the SVA storage by reallocating it. */ + +void sva_more_space(SVA *sva, int m_size) +{ int size, delta; +#if 1 + if (sva->talky) + xprintf("sva_more_space: m_size = %d\n", m_size); +#endif + xassert(m_size > sva->r_ptr - sva->m_ptr); + /* defragment the left part */ + sva_defrag_area(sva); + /* set, heuristically, the minimal size of the middle part to be + * not less than the size of the defragmented left part */ + if (m_size < sva->m_ptr - 1) + m_size = sva->m_ptr - 1; + /* if there is still not enough room, increase the total size of + * the SVA storage */ + if (sva->r_ptr - sva->m_ptr < m_size) + { size = sva->size; /* new sva size */ + for (;;) + { delta = size - sva->size; + if (sva->r_ptr - sva->m_ptr + delta >= m_size) + break; + size += size; + xassert(size > 0); + } + sva_resize_area(sva, delta); + xassert(sva->r_ptr - sva->m_ptr >= m_size); + } + return; +} + +/*********************************************************************** +* sva_enlarge_cap - enlarge capacity of specified vector +* +* This routine enlarges the current capacity of the specified vector +* by relocating its content. +* +* The parameter k specifies the reference number of the vector whose +* capacity should be enlarged, 1 <= k <= n. This vector should either +* have zero capacity or be stored in the left (dynamic) part of SVA. +* +* The parameter new_cap specifies the new capacity of the vector, +* in locations. This new capacity should be greater than the current +* capacity of the vector. +* +* The parameter skip is a flag. If this flag is set, the routine does +* *not* copy numerical values of elements of the vector on relocating +* its content, i.e. only element indices are copied. +* +* NOTE: On entry to the routine the middle part of SVA should have at +* least new_cap free locations. */ + +void sva_enlarge_cap(SVA *sva, int k, int new_cap, int skip) +{ int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + int *prev = sva->prev; + int *next = sva->next; + int *ind = sva->ind; + double *val = sva->val; + xassert(1 <= k && k <= sva->n); + xassert(new_cap > cap[k]); + /* there should be at least new_cap free locations */ + xassert(sva->r_ptr - sva->m_ptr >= new_cap); + /* relocate the vector */ + if (cap[k] == 0) + { /* the vector is empty */ + xassert(ptr[k] == 0); + xassert(len[k] == 0); + } + else + { /* the vector has non-zero capacity */ + xassert(ptr[k] + len[k] <= sva->m_ptr); + /* copy the current vector content to the beginning of the + * middle part */ + if (len[k] > 0) + { memcpy(&ind[sva->m_ptr], &ind[ptr[k]], + len[k] * sizeof(int)); + if (!skip) + memcpy(&val[sva->m_ptr], &val[ptr[k]], + len[k] * sizeof(double)); + } + /* remove the vector from the linked list */ + if (prev[k] == 0) + sva->head = next[k]; + else + { /* preceding vector exists; increase its capacity */ + cap[prev[k]] += cap[k]; + next[prev[k]] = next[k]; + } + if (next[k] == 0) + sva->tail = prev[k]; + else + prev[next[k]] = prev[k]; + } + /* set new pointer and capacity of the vector */ + ptr[k] = sva->m_ptr; + cap[k] = new_cap; + /* add the vector to the end of the linked list */ + prev[k] = sva->tail; + next[k] = 0; + if (sva->head == 0) + sva->head = k; + else + next[sva->tail] = k; + sva->tail = k; + /* new_cap free locations have been consumed */ + sva->m_ptr += new_cap; + xassert(sva->m_ptr <= sva->r_ptr); + return; +} + +/*********************************************************************** +* sva_reserve_cap - reserve locations for specified vector +* +* This routine reserves locations for the specified vector in the +* right (static) part of SVA. +* +* The parameter k specifies the reference number of the vector (this +* vector should have zero capacity), 1 <= k <= n. +* +* The parameter new_cap specifies a non-zero capacity of the vector, +* in locations. +* +* NOTE: On entry to the routine the middle part of SVA should have at +* least new_cap free locations. */ + +void sva_reserve_cap(SVA *sva, int k, int new_cap) +{ int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + xassert(1 <= k && k <= sva->n); + xassert(new_cap > 0); + xassert(ptr[k] == 0 && len[k] == 0 && cap[k] == 0); + /* there should be at least new_cap free locations */ + xassert(sva->r_ptr - sva->m_ptr >= new_cap); + /* set the pointer and capacity of the vector */ + ptr[k] = sva->r_ptr - new_cap; + cap[k] = new_cap; + /* new_cap free locations have been consumed */ + sva->r_ptr -= new_cap; + return; +} + +/*********************************************************************** +* sva_make_static - relocate specified vector to right part of SVA +* +* Assuming that the specified vector is stored in the left (dynamic) +* part of SVA, this routine makes the vector static by relocating its +* content to the right (static) part of SVA. However, if the specified +* vector has zero capacity, the routine does nothing. +* +* The parameter k specifies the reference number of the vector to be +* relocated, 1 <= k <= n. +* +* NOTE: On entry to the routine the middle part of SVA should have at +* least len[k] free locations, where len[k] is the length of the +* vector to be relocated. */ + +void sva_make_static(SVA *sva, int k) +{ int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + int *prev = sva->prev; + int *next = sva->next; + int *ind = sva->ind; + double *val = sva->val; + int ptr_k, len_k; + xassert(1 <= k && k <= sva->n); + /* if the vector has zero capacity, do nothing */ + if (cap[k] == 0) + { xassert(ptr[k] == 0); + xassert(len[k] == 0); + goto done; + } + /* there should be at least len[k] free locations */ + len_k = len[k]; + xassert(sva->r_ptr - sva->m_ptr >= len_k); + /* remove the vector from the linked list */ + if (prev[k] == 0) + sva->head = next[k]; + else + { /* preceding vector exists; increase its capacity */ + cap[prev[k]] += cap[k]; + next[prev[k]] = next[k]; + } + if (next[k] == 0) + sva->tail = prev[k]; + else + prev[next[k]] = prev[k]; + /* if the vector has zero length, make it empty */ + if (len_k == 0) + { ptr[k] = cap[k] = 0; + goto done; + } + /* copy the vector content to the beginning of the right part */ + ptr_k = sva->r_ptr - len_k; + memcpy(&ind[ptr_k], &ind[ptr[k]], len_k * sizeof(int)); + memcpy(&val[ptr_k], &val[ptr[k]], len_k * sizeof(double)); + /* set new pointer and capacity of the vector */ + ptr[k] = ptr_k; + cap[k] = len_k; + /* len[k] free locations have been consumed */ + sva->r_ptr -= len_k; +done: return; +} + +/*********************************************************************** +* sva_check_area - check sparse vector area (SVA) +* +* This routine checks the SVA data structures for correctness. +* +* NOTE: For testing/debugging only. */ + +void sva_check_area(SVA *sva) +{ int n_max = sva->n_max; + int n = sva->n; + int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + int size = sva->size; + int m_ptr = sva->m_ptr; + int r_ptr = sva->r_ptr; + int head = sva->head; + int tail = sva->tail; + int *prev = sva->prev; + int *next = sva->next; + int k; + xassert(1 <= n && n <= n_max); + xassert(1 <= m_ptr && m_ptr <= r_ptr && r_ptr <= size+1); + /* all vectors included the linked list should have non-zero + * capacity and be stored in the left part */ + for (k = head; k != 0; k = next[k]) + { xassert(1 <= k && k <= n); + xassert(cap[k] > 0); + xassert(0 <= len[k] && len[k] <= cap[k]); + if (prev[k] == 0) + xassert(k == head); + else + { xassert(1 <= prev[k] && prev[k] <= n); + xassert(next[prev[k]] == k); + } + if (next[k] == 0) + { xassert(k == tail); + xassert(ptr[k] + cap[k] <= m_ptr); + } + else + { xassert(1 <= next[k] && next[k] <= n); + xassert(prev[next[k]] == k); + xassert(ptr[k] + cap[k] <= ptr[next[k]]); + } + cap[k] = -cap[k]; + } + /* all other vectors should either have zero capacity or be + * stored in the right part */ + for (k = 1; k <= n; k++) + { if (cap[k] < 0) + { /* k-th vector is stored in the left part */ + cap[k] = -cap[k]; + } + else if (cap[k] == 0) + { /* k-th vector has zero capacity */ + xassert(ptr[k] == 0); + xassert(len[k] == 0); + } + else /* cap[k] > 0 */ + { /* k-th vector is stored in the right part */ + xassert(0 <= len[k] && len[k] <= cap[k]); + xassert(r_ptr <= ptr[k] && ptr[k] + cap[k] <= size+1); + } + } + return; +} + +/*********************************************************************** +* sva_delete_area - delete sparse vector area (SVA) +* +* This routine deletes the sparse vector area (SVA) freeing all the +* memory allocated to it. */ + +void sva_delete_area(SVA *sva) +{ tfree(sva->ptr); + tfree(sva->len); + tfree(sva->cap); + tfree(sva->prev); + tfree(sva->next); + tfree(sva->ind); + tfree(sva->val); + tfree(sva); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/sva.h b/resources/3rdparty/glpk-4.53/src/bflib/sva.h new file mode 100644 index 000000000..ad3959ba5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bflib/sva.h @@ -0,0 +1,161 @@ +/* sva.h (sparse vector area) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef SVA_H +#define SVA_H + +/*********************************************************************** +* Sparse Vector Area (SVA) is a container for sparse vectors. This +* program object is used mainly on computing factorization, where the +* sparse vectors are rows and columns of sparse matrices. +* +* The SVA storage is a set of locations numbered 1, 2, ..., size, +* where size is the size of SVA, which is the total number of +* locations currently allocated. Each location is identified by its +* pointer p, 1 <= p <= size, and is the pair (ind[p], val[p]), where +* ind[p] and val[p] are, respectively, the index and value fields used +* to store the index and numeric value of a particular vector element. +* +* Each sparse vector is identified by its reference number k, +* 1 <= k <= n, where n is the total number of vectors currently stored +* in SVA, and defined by the triplet (ptr[k], len[k], cap[k]), where: +* ptr[k] is a pointer to the first location of the vector; len[k] is +* the vector length, which is the number of its non-zero elements, +* len[k] >= 0; and cap[k] is the capacity of the vector, which is the +* total number of adjacent locations allocated to that vector, +* cap[k] >= len[k]. Thus, non-zero elements of k-th vector are stored +* in locations ptr[k], ptr[k]+1, ..., ptr[k]+len[k]-1, and locations +* ptr[k]+len[k], ptr[k]+len[k]+1, ..., ptr[k]+cap[k]-1 are reserved. +* +* The SVA storage is divided into three parts as follows: +* +* Locations 1, 2, ..., m_ptr-1 constitute the left (dynamic) part of +* SVA. This part is used to store vectors, whose capacity may change. +* Note that all vectors stored in the left part are also included in +* a doubly linked list, where they are ordered by increasing their +* pointers ptr[k] (this list is needed for efficient implementation +* of the garbage collector used to defragment the left part of SVA); +* +* Locations m_ptr, m_ptr+1, ..., r_ptr-1 are free and constitute the +* middle (free) part of SVA. +* +* Locations r_ptr, r_ptr+1, ..., size constitute the right (static) +* part of SVA. This part is used to store vectors, whose capacity is +* not changed. */ + +typedef struct SVA SVA; + +struct SVA +{ /* sparse vector area */ + int n_max; + /* maximal value of n (enlarged automatically) */ + int n; + /* number of currently allocated vectors, 0 <= n <= n_max */ + int *ptr; /* int ptr[1+n_max]; */ + /* ptr[0] is not used; + * ptr[k], 1 <= i <= n, is pointer to first location of k-th + * vector in the arrays ind and val */ + int *len; /* int len[1+n_max]; */ + /* len[0] is not used; + * len[k], 1 <= k <= n, is length of k-th vector, len[k] >= 0 */ + int *cap; /* int cap[1+n_max]; */ + /* cap[0] is not used; + * cap[k], 1 <= k <= n, is capacity of k-th vector (the number + * of adjacent locations allocated to it), cap[k] >= len[k] */ + /* NOTE: if cap[k] = 0, then ptr[k] = 0 and len[k] = 0 */ + int size; + /* total number of locations in SVA */ + int m_ptr, r_ptr; + /* partitioning pointers that define the left, middle, and right + * parts of SVA (see above); 1 <= m_ptr <= r_ptr <= size+1 */ + int head; + /* number of first (leftmost) vector in the linked list */ + int tail; + /* number of last (rightmost) vector in the linked list */ + int *prev; /* int prev[1+n_max]; */ + /* prev[0] is not used; + * prev[k] is number of vector which precedes k-th vector in the + * linked list; + * prev[k] < 0 means that k-th vector is not in the list */ + int *next; /* int next[1+n_max]; */ + /* next[0] is not used; + * next[k] is number of vector which succedes k-th vector in the + * linked list; + * next[k] < 0 means that k-th vector is not in the list */ + /* NOTE: only vectors having non-zero capacity and stored in the + * left part of SVA are included in this linked list */ + int *ind; /* int ind[1+size]; */ + /* ind[0] is not used; + * ind[p], 1 <= p <= size, is index field of location p */ + double *val; /* double val[1+size]; */ + /* val[0] is not used; + * val[p], 1 <= p <= size, is value field of location p */ +#if 1 + int talky; + /* option to enable talky mode */ +#endif +}; + +#define sva_create_area _glp_sva_create_area +SVA *sva_create_area(int n_max, int size); +/* create sparse vector area (SVA) */ + +#define sva_alloc_vecs _glp_sva_alloc_vecs +int sva_alloc_vecs(SVA *sva, int nnn); +/* allocate new vectors in SVA */ + +#define sva_resize_area _glp_sva_resize_area +void sva_resize_area(SVA *sva, int delta); +/* change size of SVA storage */ + +#define sva_defrag_area _glp_sva_defrag_area +void sva_defrag_area(SVA *sva); +/* defragment left part of SVA */ + +#define sva_more_space _glp_sva_more_space +void sva_more_space(SVA *sva, int m_size); +/* increase size of middle (free) part of SVA */ + +#define sva_enlarge_cap _glp_sva_enlarge_cap +void sva_enlarge_cap(SVA *sva, int k, int new_cap, int skip); +/* enlarge capacity of specified vector */ + +#define sva_reserve_cap _glp_sva_reserve_cap +void sva_reserve_cap(SVA *sva, int k, int new_cap); +/* reserve locations for specified vector */ + +#define sva_make_static _glp_sva_make_static +void sva_make_static(SVA *sva, int k); +/* relocate specified vector to right part of SVA */ + +#define sva_check_area _glp_sva_check_area +void sva_check_area(SVA *sva); +/* check sparse vector area (SVA) */ + +#define sva_delete_area _glp_sva_delete_area +void sva_delete_area(SVA *sva); +/* delete sparse vector area (SVA) */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bfx.c b/resources/3rdparty/glpk-4.53/src/bfx.c new file mode 100644 index 000000000..565480b6f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bfx.c @@ -0,0 +1,89 @@ +/* bfx.c (LP basis factorization driver, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "bfx.h" +#include "env.h" +#include "lux.h" + +struct BFX +{ int valid; + LUX *lux; +}; + +BFX *bfx_create_binv(void) +{ /* create factorization of the basis matrix */ + BFX *bfx; + bfx = xmalloc(sizeof(BFX)); + bfx->valid = 0; + bfx->lux = NULL; + return bfx; +} + +int bfx_factorize(BFX *binv, int m, int (*col)(void *info, int j, + int ind[], mpq_t val[]), void *info) +{ /* compute factorization of the basis matrix */ + int ret; + xassert(m > 0); + if (binv->lux != NULL && binv->lux->n != m) + { lux_delete(binv->lux); + binv->lux = NULL; + } + if (binv->lux == NULL) + binv->lux = lux_create(m); + ret = lux_decomp(binv->lux, col, info); + binv->valid = (ret == 0); + return ret; +} + +void bfx_ftran(BFX *binv, mpq_t x[], int save) +{ /* perform forward transformation (FTRAN) */ + xassert(binv->valid); + lux_solve(binv->lux, 0, x); + xassert(save == save); + return; +} + +void bfx_btran(BFX *binv, mpq_t x[]) +{ /* perform backward transformation (BTRAN) */ + xassert(binv->valid); + lux_solve(binv->lux, 1, x); + return; +} + +int bfx_update(BFX *binv, int j) +{ /* update factorization of the basis matrix */ + xassert(binv->valid); + xassert(1 <= j && j <= binv->lux->n); + return 1; +} + +void bfx_delete_binv(BFX *binv) +{ /* delete factorization of the basis matrix */ + if (binv->lux != NULL) + lux_delete(binv->lux); + xfree(binv); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bfx.h b/resources/3rdparty/glpk-4.53/src/bfx.h new file mode 100644 index 000000000..7d0aedaad --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/bfx.h @@ -0,0 +1,67 @@ +/* bfx.h (LP basis factorization driver, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef BFX_H +#define BFX_H + +#include "glpgmp.h" + +typedef struct BFX BFX; + +#define bfx_create_binv _glp_bfx_create_binv +BFX *bfx_create_binv(void); +/* create factorization of the basis matrix */ + +#define bfx_is_valid _glp_bfx_is_valid +int bfx_is_valid(BFX *binv); +/* check if factorization is valid */ + +#define bfx_invalidate _glp_bfx_invalidate +void bfx_invalidate(BFX *binv); +/* invalidate factorization of the basis matrix */ + +#define bfx_factorize _glp_bfx_factorize +int bfx_factorize(BFX *binv, int m, int (*col)(void *info, int j, + int ind[], mpq_t val[]), void *info); +/* compute factorization of the basis matrix */ + +#define bfx_ftran _glp_bfx_ftran +void bfx_ftran(BFX *binv, mpq_t x[], int save); +/* perform forward transformation (FTRAN) */ + +#define bfx_btran _glp_bfx_btran +void bfx_btran(BFX *binv, mpq_t x[]); +/* perform backward transformation (BTRAN) */ + +#define bfx_update _glp_bfx_update +int bfx_update(BFX *binv, int j); +/* update factorization of the basis matrix */ + +#define bfx_delete_binv _glp_bfx_delete_binv +void bfx_delete_binv(BFX *binv); +/* delete factorization of the basis matrix */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/cglib/cfg.c b/resources/3rdparty/glpk-4.53/src/cglib/cfg.c new file mode 100644 index 000000000..92738b415 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/cglib/cfg.c @@ -0,0 +1,409 @@ +/* cfg.c (conflict graph) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "cfg.h" +#include "env.h" + +/*********************************************************************** +* cfg_create_graph - create conflict graph +* +* This routine creates the conflict graph, which initially is empty, +* and returns a pointer to the graph descriptor. +* +* The parameter n specifies the number of *all* variables in MIP, for +* which the conflict graph will be built. +* +* The parameter nv_max specifies maximal number of vertices in the +* conflict graph. It should be the double number of binary variables +* in corresponding MIP. */ + +CFG *cfg_create_graph(int n, int nv_max) +{ CFG *G; + xassert(n >= 0); + xassert(0 <= nv_max && nv_max <= n + n); + G = talloc(1, CFG); + G->n = n; + G->pos = talloc(1+n, int); + memset(&G->pos[1], 0, n * sizeof(int)); + G->neg = talloc(1+n, int); + memset(&G->neg[1], 0, n * sizeof(int)); + G->pool = dmp_create_pool(); + G->nv_max = nv_max; + G->nv = 0; + G->ref = talloc(1+nv_max, int); + G->vptr = talloc(1+nv_max, CFGVLE *); + G->cptr = talloc(1+nv_max, CFGCLE *); + return G; +} + +/*********************************************************************** +* cfg_add_clique - add clique to conflict graph +* +* This routine adds a clique to the conflict graph. +* +* The parameter size specifies the clique size, size >= 2. Note that +* any edge can be considered as a clique of size 2. +* +* The array ind specifies vertices constituting the clique in elements +* ind[k], 1 <= k <= size: +* +* ind[k] = +j means a vertex of the conflict graph that corresponds to +* original binary variable x[j], 1 <= j <= n. +* +* ind[k] = -j means a vertex of the conflict graph that corresponds to +* complement of original binary variable x[j], 1 <= j <= n. +* +* Note that if both vertices for x[j] and (1 - x[j]) have appeared in +* the conflict graph, the routine automatically adds an edge incident +* to these vertices. */ + +static void add_edge(CFG *G, int v, int w) +{ /* add clique of size 2 */ + DMP *pool = G->pool; + int nv = G->nv; + CFGVLE **vptr = G->vptr; + CFGVLE *vle; + xassert(1 <= v && v <= nv); + xassert(1 <= w && w <= nv); + xassert(v != w); + vle = dmp_talloc(pool, CFGVLE); + vle->v = w; + vle->next = vptr[v]; + vptr[v] = vle; + vle = dmp_talloc(pool, CFGVLE); + vle->v = v; + vle->next = vptr[w]; + vptr[w] = vle; + return; +} + +void cfg_add_clique(CFG *G, int size, const int ind[]) +{ int n = G->n; + int *pos = G->pos; + int *neg = G->neg; + DMP *pool = G->pool; + int nv_max = G->nv_max; + int *ref = G->ref; + CFGVLE **vptr = G->vptr; + CFGCLE **cptr = G->cptr; + int j, k, v; + xassert(2 <= size && size <= nv_max); + /* add new vertices to the conflict graph */ + for (k = 1; k <= size; k++) + { j = ind[k]; + if (j > 0) + { /* vertex corresponds to x[j] */ + xassert(1 <= j && j <= n); + if (pos[j] == 0) + { /* no such vertex exists; add it */ + v = pos[j] = ++(G->nv); + xassert(v <= nv_max); + ref[v] = j; + vptr[v] = NULL; + cptr[v] = NULL; + if (neg[j] != 0) + { /* now both vertices for x[j] and (1 - x[j]) exist */ + add_edge(G, v, neg[j]); + } + } + } + else + { /* vertex corresponds to (1 - x[j]) */ + j = -j; + xassert(1 <= j && j <= n); + if (neg[j] == 0) + { /* no such vertex exists; add it */ + v = neg[j] = ++(G->nv); + xassert(v <= nv_max); + ref[v] = j; + vptr[v] = NULL; + cptr[v] = NULL; + if (pos[j] != 0) + { /* now both vertices for x[j] and (1 - x[j]) exist */ + add_edge(G, v, pos[j]); + } + } + } + } + /* add specified clique to the conflict graph */ + if (size == 2) + add_edge(G, + ind[1] > 0 ? pos[+ind[1]] : neg[-ind[1]], + ind[2] > 0 ? pos[+ind[2]] : neg[-ind[2]]); + else + { CFGVLE *vp, *vle; + CFGCLE *cle; + /* build list of clique vertices */ + vp = NULL; + for (k = 1; k <= size; k++) + { vle = dmp_talloc(pool, CFGVLE); + vle->v = ind[k] > 0 ? pos[+ind[k]] : neg[-ind[k]]; + vle->next = vp; + vp = vle; + } + /* attach the clique to all its vertices */ + for (k = 1; k <= size; k++) + { cle = dmp_talloc(pool, CFGCLE); + cle->vptr = vp; + v = ind[k] > 0 ? pos[+ind[k]] : neg[-ind[k]]; + cle->next = cptr[v]; + cptr[v] = cle; + } + } + return; +} + +/*********************************************************************** +* cfg_get_adjacent - get vertices adjacent to specified vertex +* +* This routine stores numbers of all vertices adjacent to specified +* vertex v of the conflict graph in locations ind[1], ..., ind[len], +* and returns len, 1 <= len <= nv-1, where nv is the total number of +* vertices in the conflict graph. +* +* Note that the conflict graph defined by this routine has neither +* self-loops nor multiple edges. */ + +int cfg_get_adjacent(CFG *G, int v, int ind[]) +{ int nv = G->nv; + int *ref = G->ref; + CFGVLE **vptr = G->vptr; + CFGCLE **cptr = G->cptr; + CFGVLE *vle; + CFGCLE *cle; + int k, w, len; + xassert(1 <= v && v <= nv); + len = 0; + /* walk thru the list of adjacent vertices */ + for (vle = vptr[v]; vle != NULL; vle = vle->next) + { w = vle->v; + xassert(1 <= w && w <= nv); + xassert(w != v); + if (ref[w] > 0) + { ind[++len] = w; + ref[w] = -ref[w]; + } + } + /* walk thru the list of incident cliques */ + for (cle = cptr[v]; cle != NULL; cle = cle->next) + { /* walk thru the list of clique vertices */ + for (vle = cle->vptr; vle != NULL; vle = vle->next) + { w = vle->v; + xassert(1 <= w && w <= nv); + if (w != v && ref[w] > 0) + { ind[++len] = w; + ref[w] = -ref[w]; + } + } + } + xassert(1 <= len && len < nv); + /* unmark vertices included in the resultant adjacency list */ + for (k = 1; k <= len; k++) + { w = ind[k]; + ref[w] = -ref[w]; + } + return len; +} + +/*********************************************************************** +* cfg_expand_clique - expand specified clique to maximal clique +* +* Given some clique in the conflict graph this routine expands it to +* a maximal clique by including in it new vertices. +* +* On entry vertex indices constituting the initial clique should be +* stored in locations c_ind[1], ..., c_ind[c_len], where c_len is the +* initial clique size. On exit the routine stores new vertex indices +* to locations c_ind[c_len+1], ..., c_ind[c_len'], where c_len' is the +* size of the maximal clique found, and returns c_len'. +* +* ALGORITHM +* +* Let G = (V, E) be a graph, C within V be a current clique to be +* expanded, and D within V \ C be a subset of vertices adjacent to all +* vertices from C. On every iteration the routine chooses some vertex +* v in D, includes it into C, and removes from D the vertex v as well +* as all vertices not adjacent to v. Initially C is empty and D = V. +* Iterations repeat until D becomes an empty set. Obviously, the final +* set C is a maximal clique in G. +* +* Now let C0 be an initial clique, and we want C0 to be a subset of +* the final maximal clique C. To provide this condition the routine +* starts constructing C by choosing only such vertices v in D, which +* are in C0, until all vertices from C0 have been included in C. May +* note that if on some iteration C0 \ C is non-empty (i.e. if not all +* vertices from C0 have been included in C), C0 \ C is a subset of D, +* because C0 is a clique. */ + +static int intersection(int d_len, int d_ind[], int d_pos[], int len, + const int ind[]) +{ /* compute intersection D := D inter W, where W is some specified + * set of vertices */ + int k, t, v, new_len; + /* walk thru vertices in W and mark vertices in D */ + for (t = 1; t <= len; t++) + { /* v in W */ + v = ind[t]; + /* determine position of v in D */ + k = d_pos[v]; + if (k != 0) + { /* v in D */ + xassert(d_ind[k] == v); + /* mark v to keep it in D */ + d_ind[k] = -v; + } + } + /* remove all unmarked vertices from D */ + new_len = 0; + for (k = 1; k <= d_len; k++) + { /* v in D */ + v = d_ind[k]; + if (v < 0) + { /* v is marked; keep it */ + v = -v; + new_len++; + d_ind[new_len] = v; + d_pos[v] = new_len; + } + else + { /* v is not marked; remove it */ + d_pos[v] = 0; + } + } + return new_len; +} + +int cfg_expand_clique(CFG *G, int c_len, int c_ind[]) +{ int nv = G->nv; + int d_len, *d_ind, *d_pos, len, *ind; + int k, v; + xassert(0 <= c_len && c_len <= nv); + /* allocate working arrays */ + d_ind = talloc(1+nv, int); + d_pos = talloc(1+nv, int); + ind = talloc(1+nv, int); + /* initialize C := 0, D := V */ + d_len = nv; + for (k = 1; k <= nv; k++) + d_ind[k] = d_pos[k] = k; + /* expand C by vertices of specified initial clique C0 */ + for (k = 1; k <= c_len; k++) + { /* v in C0 */ + v = c_ind[k]; + xassert(1 <= v && v <= nv); + /* since C0 is clique, v should be in D */ + xassert(d_pos[v] != 0); + /* W := set of vertices adjacent to v */ + len = cfg_get_adjacent(G, v, ind); + /* D := D inter W */ + d_len = intersection(d_len, d_ind, d_pos, len, ind); + /* since v not in W, now v should be not in D */ + xassert(d_pos[v] == 0); + } + /* expand C by some other vertices until D is empty */ + while (d_len > 0) + { /* v in D */ + v = d_ind[1]; + xassert(1 <= v && v <= nv); + /* note that v is adjacent to all vertices in C (by design), + * so add v to C */ + c_ind[++c_len] = v; + /* W := set of vertices adjacent to v */ + len = cfg_get_adjacent(G, v, ind); + /* D := D inter W */ + d_len = intersection(d_len, d_ind, d_pos, len, ind); + /* since v not in W, now v should be not in D */ + xassert(d_pos[v] == 0); + } + /* free working arrays */ + tfree(d_ind); + tfree(d_pos); + tfree(ind); + /* bring maximal clique to calling routine */ + return c_len; +} + +/*********************************************************************** +* cfg_check_clique - check clique in conflict graph +* +* This routine checks that vertices of the conflict graph specified +* in locations c_ind[1], ..., c_ind[c_len] constitute a clique. +* +* NOTE: for testing/debugging only. */ + +void cfg_check_clique(CFG *G, int c_len, const int c_ind[]) +{ int nv = G->nv; + int k, kk, v, w, len, *ind; + char *flag; + ind = talloc(1+nv, int); + flag = talloc(1+nv, char); + memset(&flag[1], 0, nv); + /* walk thru clique vertices */ + xassert(c_len >= 0); + for (k = 1; k <= c_len; k++) + { /* get clique vertex v */ + v = c_ind[k]; + xassert(1 <= v && v <= nv); + /* get vertices adjacent to vertex v */ + len = cfg_get_adjacent(G, v, ind); + for (kk = 1; kk <= len; kk++) + { w = ind[kk]; + xassert(1 <= w && w <= nv); + xassert(w != v); + flag[w] = 1; + } + /* check that all clique vertices other than v are adjacent + to v */ + for (kk = 1; kk <= c_len; kk++) + { w = c_ind[kk]; + xassert(1 <= w && w <= nv); + if (w != v) + xassert(flag[w]); + } + /* reset vertex flags */ + for (kk = 1; kk <= len; kk++) + flag[ind[kk]] = 0; + } + tfree(ind); + tfree(flag); + return; +} + +/*********************************************************************** +* cfg_delete_graph - delete conflict graph +* +* This routine deletes the conflict graph by freeing all the memory +* allocated to this program object. */ + +void cfg_delete_graph(CFG *G) +{ tfree(G->pos); + tfree(G->neg); + dmp_delete_pool(G->pool); + tfree(G->ref); + tfree(G->vptr); + tfree(G->cptr); + tfree(G); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/cglib/cfg.h b/resources/3rdparty/glpk-4.53/src/cglib/cfg.h new file mode 100644 index 000000000..87b61c738 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/cglib/cfg.h @@ -0,0 +1,130 @@ +/* cfg.h (conflict graph) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef CFG_H +#define CFG_H + +#include "dmp.h" + +/*********************************************************************** +* The structure CFG describes the conflict graph. +* +* Conflict graph is an undirected graph G = (V, E), where V is a set +* of vertices, E <= V x V is a set of edges. Each vertex v in V of the +* conflict graph corresponds to a binary variable z[v], which is +* either an original binary variable x[j] or its complement 1 - x[j]. +* Edge (v,w) in E means that z[v] and z[w] cannot take the value 1 at +* the same time, i.e. it defines an inequality z[v] + z[w] <= 1, which +* is assumed to be valid for original MIP. +* +* Since the conflict graph may be dense, it is stored as an union of +* its cliques rather than explicitly. */ + +typedef struct CFG CFG; +typedef struct CFGVLE CFGVLE; +typedef struct CFGCLE CFGCLE; + +struct CFG +{ /* conflict graph descriptor */ + int n; + /* number of *all* variables (columns) in corresponding MIP */ + int *pos; /* int pos[1+n]; */ + /* pos[0] is not used; + * pos[j] = v, 1 <= j <= n, means that vertex v corresponds to + * original binary variable x[j], and pos[j] = 0 means that the + * conflict graph has no such vertex */ + int *neg; /* int neg[1+n]; */ + /* neg[0] is not used; + * neg[j] = v, 1 <= j <= n, means that vertex v corresponds to + * complement of original binary variable x[j], and neg[j] = 0 + * means that the conflict graph has no such vertex */ + DMP *pool; + /* memory pool to allocate elements of the conflict graph */ + int nv_max; + /* maximal number of vertices in the conflict graph */ + int nv; + /* current number of vertices in the conflict graph */ + int *ref; /* int ref[1+nv_max]; */ + /* ref[v] = j, 1 <= v <= nv, means that vertex v corresponds + * either to original binary variable x[j] or to its complement, + * i.e. either pos[j] = v or neg[j] = v */ + CFGVLE **vptr; /* CFGVLE *vptr[1+nv_max]; */ + /* vptr[v], 1 <= v <= nv, is an initial pointer to the list of + * vertices adjacent to vertex v */ + CFGCLE **cptr; /* CFGCLE *cptr[1+nv_max]; */ + /* cptr[v], 1 <= v <= nv, is an initial pointer to the list of + * cliques that contain vertex v */ +}; + +struct CFGVLE +{ /* vertex list element */ + int v; + /* vertex number, 1 <= v <= nv */ + CFGVLE *next; + /* pointer to next vertex list element */ +}; + +struct CFGCLE +{ /* clique list element */ + CFGVLE *vptr; + /* initial pointer to the list of clique vertices */ + CFGCLE *next; + /* pointer to next clique list element */ +}; + +#define cfg_create_graph _glp_cfg_create_graph +CFG *cfg_create_graph(int n, int nv_max); +/* create conflict graph */ + +#define cfg_add_clique _glp_cfg_add_clique +void cfg_add_clique(CFG *G, int size, const int ind[]); +/* add clique to conflict graph */ + +#define cfg_get_adjacent _glp_cfg_get_adjacent +int cfg_get_adjacent(CFG *G, int v, int ind[]); +/* get vertices adjacent to specified vertex */ + +#define cfg_expand_clique _glp_cfg_expand_clique +int cfg_expand_clique(CFG *G, int c_len, int c_ind[]); +/* expand specified clique to maximal clique */ + +#define cfg_check_clique _glp_cfg_check_clique +void cfg_check_clique(CFG *G, int c_len, const int c_ind[]); +/* check clique in conflict graph */ + +#define cfg_delete_graph _glp_cfg_delete_graph +void cfg_delete_graph(CFG *G); +/* delete conflict graph */ + +#define cfg_build_graph _glp_cfg_build_graph +CFG *cfg_build_graph(void /* glp_prob */ *P); +/* build conflict graph */ + +#define cfg_find_clique _glp_cfg_find_clique +int cfg_find_clique(void /* glp_prob */ *P, CFG *G, int ind[], + double *sum); +/* find maximum weight clique in conflict graph */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/cglib/cfg1.c b/resources/3rdparty/glpk-4.53/src/cglib/cfg1.c new file mode 100644 index 000000000..02317bffb --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/cglib/cfg1.c @@ -0,0 +1,703 @@ +/* cfg1.c (conflict graph) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "cfg.h" +#include "env.h" +#include "prob.h" +#include "wclique.h" +#include "wclique1.h" + +/*********************************************************************** +* cfg_build_graph - build conflict graph +* +* This routine builds the conflict graph. It analyzes the specified +* problem object to discover original and implied packing inequalities +* and adds corresponding cliques to the conflict graph. +* +* Packing inequality has the form: +* +* sum z[j] <= 1, (1) +* j in J +* +* where z[j] = x[j] or z[j] = 1 - x[j], x[j] is an original binary +* variable. Every packing inequality (1) is equivalent to a set of +* edge inequalities: +* +* z[i] + z[j] <= 1 for all i, j in J, i != j, (2) +* +* and since every edge inequality (2) defines an edge in the conflict +* graph, corresponding packing inequality (1) defines a clique. +* +* To discover packing inequalities the routine analyzes constraints +* of the specified MIP. To simplify the analysis each constraint is +* analyzed separately. The analysis is performed as follows. +* +* Let some original constraint be the following: +* +* L <= sum a[j] x[j] <= U. (3) +* +* To analyze it the routine analyzes two constraints of "not greater +* than" type: +* +* sum (-a[j]) x[j] <= -L, (4) +* +* sum (+a[j]) x[j] <= +U, (5) +* +* which are relaxations of the original constraint (3). (If, however, +* L = -oo, or U = +oo, corresponding constraint being redundant is not +* analyzed.) +* +* Let a constraint of "not greater than" type be the following: +* +* sum a[j] x[j] + sum a[j] x[j] <= b, (6) +* j in J j in J' +* +* where J is a subset of binary variables, J' is a subset of other +* (continues and non-binary integer) variables. The constraint (6) is +* is relaxed as follows, to eliminate non-binary variables: +* +* sum a[j] x[j] <= b - sum a[j] x[j] <= b', (7) +* j in J j in J' +* +* b' = sup(b - sum a[j] x[j]) = +* j in J' +* +* = b - inf(sum a[j] x[j]) = +* +* = b - sum inf(a[j] x[j]) = (8) +* +* = b - sum a[j] inf(x[j]) - sum a[j] sup(x[j]) = +* a[j]>0 a[j]<0 +* +* = b - sum a[j] l[j] - sum a[j] u[j], +* a[j]>0 a[j]<0 +* +* where l[j] and u[j] are, resp., lower and upper bounds of x[j]. +* +* Then the routine transforms the relaxed constraint containing only +* binary variables: +* +* sum a[j] x[j] <= b (9) +* +* to an equivalent 0-1 knapsack constraint as follows: +* +* sum a[j] x[j] + sum a[j] x[j] <= b ==> +* a[j]>0 a[j]<0 +* +* sum a[j] x[j] + sum a[j] (1 - x[j]) <= b ==> +* a[j]>0 a[j]<0 (10) +* +* sum (+a[j]) x[j] + sum (-a[j]) x[j] <= b + sum (-a[j]) ==> +* a[j]>0 a[j]<0 a[j]<0 +* +* sum a'[j] z[j] <= b', +* +* where a'[j] = |a[j]| > 0, and +* +* ( x[j] if a[j] > 0 +* z[j] = < +* ( 1 - x[j] if a[j] < 0 +* +* is a binary variable, which is either original binary variable x[j] +* or its complement. +* +* Finally, the routine analyzes the resultant 0-1 knapsack inequality: +* +* sum a[j] z[j] <= b, (11) +* j in J +* +* where all a[j] are positive, to discover clique inequalities (1), +* which are valid for (11) and therefore valid for (3). (It is assumed +* that the original MIP has been preprocessed, so it is not checked, +* for example, that b > 0 or that a[j] <= b.) +* +* In principle, to discover any edge inequalities valid for (11) it +* is sufficient to check whether a[i] + a[j] > b for all i, j in J, +* i < j. However, this way requires O(|J|^2) checks, so the routine +* analyses (11) in the following way, which is much more efficient in +* many practical cases. +* +* 1. Let a[p] and a[q] be two minimal coefficients: +* +* a[p] = min a[j], (12) +* +* a[q] = min a[j], j != p, (13) +* +* such that +* +* a[p] + a[q] > b. (14) +* +* This means that a[i] + a[j] > b for any i, j in J, i != j, so +* +* z[i] + z[j] <= 1 (15) +* +* are valid for (11) for any i, j in J, i != j. This case means that +* J define a clique in the conflict graph. +* +* 2. Otherwise, let a[p] and [q] be two maximal coefficients: +* +* a[p] = max a[j], (16) +* +* a[q] = max a[j], j != p, (17) +* +* such that +* +* a[p] + a[q] <= b. (18) +* +* This means that a[i] + a[j] <= b for any i, j in J, i != j, so in +* this case no valid edge inequalities for (11) exist. +* +* 3. Otherwise, let all a[j] be ordered by descending their values: +* +* a[1] >= a[2] >= ... >= a[p-1] >= a[p] >= a[p+1] >= ... (19) +* +* where p is such that +* +* a[p-1] + a[p] > b, (20) +* +* a[p] + a[p+1] <= b. (21) +* +* (May note that due to the former two cases in this case we always +* have 2 <= p <= |J|-1.) +* +* Since a[p] and a[p-1] are two minimal coefficients in the set +* J' = {1, ..., p}, J' define a clique in the conflict graph for the +* same reason as in the first case. Similarly, since a[p] and a[p+1] +* are two maximal coefficients in the set J" = {p, ..., |J|}, no edge +* inequalities exist for all i, j in J" for the same reason as in the +* second case. Thus, to discover other edge inequalities (15) valid +* for (11), the routine checks if a[i] + a[j] > b for all i in J', +* j in J", i != j. */ + +#define is_binary(j) \ + (P->col[j]->kind == GLP_IV && P->col[j]->type == GLP_DB && \ + P->col[j]->lb == 0.0 && P->col[j]->ub == 1.0) +/* check if x[j] is binary variable */ + +struct term { int ind; double val; }; +/* term a[j] * z[j] used to sort a[j]'s */ + +static int fcmp(const void *e1, const void *e2) +{ /* auxiliary routine called from qsort */ + const struct term *t1 = e1, *t2 = e2; + if (t1->val > t2->val) + return -1; + else if (t1->val < t2->val) + return +1; + else + return 0; +} + +static void analyze_ineq(glp_prob *P, CFG *G, int len, int ind[], + double val[], double rhs, struct term t[]) +{ /* analyze inequality constraint (6) */ + /* P is the original MIP + * G is the conflict graph to be built + * len is the number of terms in the constraint + * ind[1], ..., ind[len] are indices of variables x[j] + * val[1], ..., val[len] are constraint coefficients a[j] + * rhs is the right-hand side b + * t[1+len] is a working array */ + int j, k, kk, p, q, type, new_len; + /* eliminate non-binary variables; see (7) and (8) */ + new_len = 0; + for (k = 1; k <= len; k++) + { /* get index of variable x[j] */ + j = ind[k]; + if (is_binary(j)) + { /* x[j] remains in relaxed constraint */ + new_len++; + ind[new_len] = j; + val[new_len] = val[k]; + } + else if (val[k] > 0.0) + { /* eliminate non-binary x[j] in case a[j] > 0 */ + /* b := b - a[j] * l[j]; see (8) */ + type = P->col[j]->type; + if (type == GLP_FR || type == GLP_UP) + { /* x[j] has no lower bound */ + goto done; + } + rhs -= val[k] * P->col[j]->lb; + } + else /* val[j] < 0.0 */ + { /* eliminate non-binary x[j] in case a[j] < 0 */ + /* b := b - a[j] * u[j]; see (8) */ + type = P->col[j]->type; + if (type == GLP_FR || type == GLP_LO) + { /* x[j] has no upper bound */ + goto done; + } + rhs -= val[k] * P->col[j]->ub; + } + } + len = new_len; + /* now we have the constraint (9) */ + if (len <= 1) + { /* at least two terms are needed */ + goto done; + } + /* make all constraint coefficients positive; see (10) */ + for (k = 1; k <= len; k++) + { if (val[k] < 0.0) + { /* a[j] < 0; substitute x[j] = 1 - x'[j], where x'[j] is + * a complement binary variable */ + ind[k] = -ind[k]; + val[k] = -val[k]; + rhs += val[k]; + } + } + /* now we have 0-1 knapsack inequality (11) */ + /* increase the right-hand side a bit to avoid false checks due + * to rounding errors */ + rhs += 0.001 * (1.0 + fabs(rhs)); + /*** first case ***/ + /* find two minimal coefficients a[p] and a[q] */ + p = 0; + for (k = 1; k <= len; k++) + { if (p == 0 || val[p] > val[k]) + p = k; + } + q = 0; + for (k = 1; k <= len; k++) + { if (k != p && (q == 0 || val[q] > val[k])) + q = k; + } + xassert(p != 0 && q != 0 && p != q); + /* check condition (14) */ + if (val[p] + val[q] > rhs) + { /* all z[j] define a clique in the conflict graph */ + cfg_add_clique(G, len, ind); + goto done; + } + /*** second case ***/ + /* find two maximal coefficients a[p] and a[q] */ + p = 0; + for (k = 1; k <= len; k++) + { if (p == 0 || val[p] < val[k]) + p = k; + } + q = 0; + for (k = 1; k <= len; k++) + { if (k != p && (q == 0 || val[q] < val[k])) + q = k; + } + xassert(p != 0 && q != 0 && p != q); + /* check condition (18) */ + if (val[p] + val[q] <= rhs) + { /* no valid edge inequalities exist */ + goto done; + } + /*** third case ***/ + xassert(len >= 3); + /* sort terms in descending order of coefficient values */ + for (k = 1; k <= len; k++) + { t[k].ind = ind[k]; + t[k].val = val[k]; + } + qsort(&t[1], len, sizeof(struct term), fcmp); + for (k = 1; k <= len; k++) + { ind[k] = t[k].ind; + val[k] = t[k].val; + } + /* now a[1] >= a[2] >= ... >= a[len-1] >= a[len] */ + /* note that a[1] + a[2] > b and a[len-1] + a[len] <= b due two + * the former two cases */ + xassert(val[1] + val[2] > rhs); + xassert(val[len-1] + val[len] <= rhs); + /* find p according to conditions (20) and (21) */ + for (p = 2; p < len; p++) + { if (val[p] + val[p+1] <= rhs) + break; + } + xassert(p < len); + /* z[1], ..., z[p] define a clique in the conflict graph */ + cfg_add_clique(G, p, ind); + /* discover other edge inequalities */ + for (k = 1; k <= p; k++) + { for (kk = p; kk <= len; kk++) + { if (k != kk && val[k] + val[kk] > rhs) + { int iii[1+2]; + iii[1] = ind[k]; + iii[2] = ind[kk]; + cfg_add_clique(G, 2, iii); + } + } + } +done: return; +} + +CFG *cfg_build_graph(void *P_) +{ glp_prob *P = P_; + int m = P->m; + int n = P->n; + CFG *G; + int i, k, type, len, *ind; + double *val; + struct term *t; + /* create the conflict graph (number of its vertices cannot be + * greater than double number of binary variables) */ + G = cfg_create_graph(n, 2 * glp_get_num_bin(P)); + /* allocate working arrays */ + ind = talloc(1+n, int); + val = talloc(1+n, double); + t = talloc(1+n, struct term); + /* analyze constraints to discover edge inequalities */ + for (i = 1; i <= m; i++) + { type = P->row[i]->type; + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { /* i-th row has lower bound */ + /* analyze inequality sum (-a[j]) * x[j] <= -lb */ + len = glp_get_mat_row(P, i, ind, val); + for (k = 1; k <= len; k++) + val[k] = -val[k]; + analyze_ineq(P, G, len, ind, val, -P->row[i]->lb, t); + } + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { /* i-th row has upper bound */ + /* analyze inequality sum (+a[j]) * x[j] <= +ub */ + len = glp_get_mat_row(P, i, ind, val); + analyze_ineq(P, G, len, ind, val, +P->row[i]->ub, t); + } + } + /* free working arrays */ + tfree(ind); + tfree(val); + tfree(t); + return G; +} + +/*********************************************************************** +* cfg_find_clique - find maximum weight clique in conflict graph +* +* This routine finds a maximum weight clique in the conflict graph +* G = (V, E), where the weight of vertex v in V is the value of +* corresponding binary variable z (which is either an original binary +* variable or its complement) in the optimal solution to LP relaxation +* provided in the problem object. The goal is to find a clique in G, +* whose weight is greater than 1, in which case corresponding packing +* inequality is violated at the optimal point. +* +* On exit the routine stores vertex indices of the conflict graph +* included in the clique found to locations ind[1], ..., ind[len], and +* returns len, which is the clique size. The clique weight is stored +* in location pointed to by the parameter sum. If no clique has been +* found, the routine returns 0. +* +* Since the conflict graph may have a big number of vertices and be +* quite dense, the routine uses an induced subgraph G' = (V', E'), +* which is constructed as follows: +* +* 1. If the weight of some vertex v in V is zero (close to zero), it +* is not included in V'. Obviously, including in a clique +* zero-weight vertices does not change its weight, so if in G there +* exist a clique of a non-zero weight, in G' exists a clique of the +* same weight. This point is extremely important, because dropping +* out zero-weight vertices can be done without retrieving lists of +* adjacent vertices whose size may be very large. +* +* 2. Cumulative weight of vertex v in V is the sum of the weight of v +* and weights of all vertices in V adjacent to v. Obviously, if +* a clique includes a vertex v, the clique weight cannot be greater +* than the cumulative weight of v. Since we are interested only in +* cliques whose weight is greater than 1, vertices of V, whose +* cumulative weight is not greater than 1, are not included in V'. +* +* May note that in many practical cases the size of the induced +* subgraph G' is much less than the size of the original conflict +* graph G due to many binary variables, whose optimal values are zero +* or close to zero. For example, it may happen that |V| = 100,000 and +* |E| = 1e9 while |V'| = 50 and |E'| = 1000. */ + +struct csa +{ /* common storage area */ + glp_prob *P; + /* original MIP */ + CFG *G; + /* original conflict graph G = (V, E), |V| = nv */ + int *ind; /* int ind[1+nv]; */ + /* working array */ + /*--------------------------------------------------------------*/ + /* induced subgraph G' = (V', E') of original conflict graph */ + int nn; + /* number of vertices in V' */ + int *vtoi; /* int vtoi[1+nv]; */ + /* vtoi[v] = i, 1 <= v <= nv, means that vertex v in V is vertex + * i in V'; vtoi[v] = 0 means that vertex v is not included in + * the subgraph */ + int *itov; /* int itov[1+nv]; */ + /* itov[i] = v, 1 <= i <= nn, means that vertex i in V' is vertex + * v in V */ + double *wgt; /* double wgt[1+nv]; */ + /* wgt[i], 1 <= i <= nn, is a weight of vertex i in V', which is + * the value of corresponding binary variable in optimal solution + * to LP relaxation */ +}; + +static void build_subgraph(struct csa *csa) +{ /* build induced subgraph */ + glp_prob *P = csa->P; + int n = P->n; + CFG *G = csa->G; + int *ind = csa->ind; + int *pos = G->pos; + int *neg = G->neg; + int nv = G->nv; + int *ref = G->ref; + int *vtoi = csa->vtoi; + int *itov = csa->itov; + double *wgt = csa->wgt; + int j, k, v, w, nn, len; + double z, sum; + /* initially induced subgraph is empty */ + nn = 0; + /* walk thru vertices of original conflict graph */ + for (v = 1; v <= nv; v++) + { /* determine value of binary variable z[j] that corresponds to + * vertex v */ + j = ref[v]; + xassert(1 <= j && j <= n); + if (pos[j] == v) + { /* z[j] = x[j], where x[j] is original variable */ + z = P->col[j]->prim; + } + else if (neg[j] == v) + { /* z[j] = 1 - x[j], where x[j] is original variable */ + z = 1.0 - P->col[j]->prim; + } + else + xassert(v != v); + /* if z[j] is close to zero, do not include v in the induced + * subgraph */ + if (z < 0.001) + { vtoi[v] = 0; + continue; + } + /* calculate cumulative weight of vertex v */ + sum = z; + /* walk thru all vertices adjacent to v */ + len = cfg_get_adjacent(G, v, ind); + for (k = 1; k <= len; k++) + { /* there is an edge (v,w) in the conflict graph */ + w = ind[k]; + xassert(w != v); + /* add value of z[j] that corresponds to vertex w */ + j = ref[w]; + xassert(1 <= j && j <= n); + if (pos[j] == w) + sum += P->col[j]->prim; + else if (neg[j] == w) + sum += 1.0 - P->col[j]->prim; + else + xassert(w != w); + } + /* cumulative weight of vertex v is an upper bound of weight + * of any clique containing v; so if it not greater than 1, do + * not include v in the induced subgraph */ + if (sum < 1.010) + { vtoi[v] = 0; + continue; + } + /* include vertex v in the induced subgraph */ + nn++; + vtoi[v] = nn; + itov[nn] = v; + wgt[nn] = z; + } + /* induced subgraph has been built */ + csa->nn = nn; + return; +} + +static int sub_adjacent(struct csa *csa, int i, int adj[]) +{ /* retrieve vertices of induced subgraph adjacent to specified + * vertex */ + CFG *G = csa->G; + int nv = G->nv; + int *ind = csa->ind; + int nn = csa->nn; + int *vtoi = csa->vtoi; + int *itov = csa->itov; + int j, k, v, w, len, len1; + /* determine original vertex v corresponding to vertex i */ + xassert(1 <= i && i <= nn); + v = itov[i]; + /* retrieve vertices adjacent to vertex v in original graph */ + len1 = cfg_get_adjacent(G, v, ind); + /* keep only adjacent vertices which are in induced subgraph and + * change their numbers appropriately */ + len = 0; + for (k = 1; k <= len1; k++) + { /* there exists edge (v, w) in original graph */ + w = ind[k]; + xassert(1 <= w && w <= nv && w != v); + j = vtoi[w]; + if (j != 0) + { /* vertex w is vertex j in induced subgraph */ + xassert(1 <= j && j <= nn && j != i); + adj[++len] = j; + } + } + return len; +} + +static int find_clique(struct csa *csa, int c_ind[]) +{ /* find maximum weight clique in induced subgraph with exact + * Ostergard's algorithm */ + int nn = csa->nn; + double *wgt = csa->wgt; + int i, j, k, p, q, t, ne, nb, len, *iwt, *ind; + unsigned char *a; + xassert(nn >= 2); + /* allocate working array */ + ind = talloc(1+nn, int); + /* calculate the number of elements in lower triangle (without + * diagonal) of adjacency matrix of induced subgraph */ + ne = (nn * (nn - 1)) / 2; + /* calculate the number of bytes needed to store lower triangle + * of adjacency matrix */ + nb = (ne + (CHAR_BIT - 1)) / CHAR_BIT; + /* allocate lower triangle of adjacency matrix */ + a = talloc(nb, unsigned char); + /* fill lower triangle of adjacency matrix */ + memset(a, 0, nb); + for (p = 1; p <= nn; p++) + { /* retrieve vertices adjacent to vertex p */ + len = sub_adjacent(csa, p, ind); + for (k = 1; k <= len; k++) + { /* there exists edge (p, q) in induced subgraph */ + q = ind[k]; + xassert(1 <= q && q <= nn && q != p); + /* determine row and column indices of this edge in lower + * triangle of adjacency matrix */ + if (p > q) + i = p, j = q; + else /* p < q */ + i = q, j = p; + /* set bit a[i,j] to 1, i > j */ + t = ((i - 1) * (i - 2)) / 2 + (j - 1); + a[t / CHAR_BIT] |= + (unsigned char)(1 << ((CHAR_BIT - 1) - t % CHAR_BIT)); + } + } + /* scale vertex weights by 1000 and convert them to integers as + * required by Ostergard's algorithm */ + iwt = ind; + for (i = 1; i <= nn; i++) + { /* it is assumed that 0 <= wgt[i] <= 1 */ + t = (int)(1000.0 * wgt[i] + 0.5); + if (t < 0) + t = 0; + else if (t > 1000) + t = 1000; + iwt[i] = t; + } + /* find maximum weight clique */ + len = wclique(nn, iwt, a, c_ind); + /* free working arrays */ + tfree(ind); + tfree(a); + /* return clique size to calling routine */ + return len; +} + +static int func(void *info, int i, int ind[]) +{ /* auxiliary routine used by routine find_clique1 */ + struct csa *csa = info; + xassert(1 <= i && i <= csa->nn); + return sub_adjacent(csa, i, ind); +} + +static int find_clique1(struct csa *csa, int c_ind[]) +{ /* find maximum weight clique in induced subgraph with greedy + * heuristic */ + int nn = csa->nn; + double *wgt = csa->wgt; + int len; + xassert(nn >= 2); + len = wclique1(nn, wgt, func, csa, c_ind); + /* return clique size to calling routine */ + return len; +} + +int cfg_find_clique(void *P, CFG *G, int ind[], double *sum_) +{ int nv = G->nv; + struct csa csa; + int i, k, len; + double sum; + /* initialize common storage area */ + csa.P = P; + csa.G = G; + csa.ind = talloc(1+nv, int); + csa.nn = -1; + csa.vtoi = talloc(1+nv, int); + csa.itov = talloc(1+nv, int); + csa.wgt = talloc(1+nv, double); + /* build induced subgraph */ + build_subgraph(&csa); +#ifdef GLP_DEBUG + xprintf("nn = %d\n", csa.nn); +#endif + /* if subgraph has less than two vertices, do nothing */ + if (csa.nn < 2) + { len = 0; + sum = 0.0; + goto skip; + } + /* find maximum weight clique in induced subgraph */ +#if 1 /* FIXME */ + if (csa.nn <= 50) +#endif + { /* induced subgraph is small; use exact algorithm */ + len = find_clique(&csa, ind); + } + else + { /* induced subgraph is large; use greedy heuristic */ + len = find_clique1(&csa, ind); + } + /* do not report clique, if it has less than two vertices */ + if (len < 2) + { len = 0; + sum = 0.0; + goto skip; + } + /* convert indices of clique vertices from induced subgraph to + * original conflict graph and compute clique weight */ + sum = 0.0; + for (k = 1; k <= len; k++) + { i = ind[k]; + xassert(1 <= i && i <= csa.nn); + sum += csa.wgt[i]; + ind[k] = csa.itov[i]; + } +skip: /* free working arrays */ + tfree(csa.ind); + tfree(csa.vtoi); + tfree(csa.itov); + tfree(csa.wgt); + /* return to calling routine */ + *sum_ = sum; + return len; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/colamd/COPYING b/resources/3rdparty/glpk-4.53/src/colamd/COPYING new file mode 100644 index 000000000..84bba36d0 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/colamd/COPYING @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/resources/3rdparty/glpk-4.53/src/colamd/README b/resources/3rdparty/glpk-4.53/src/colamd/README new file mode 100644 index 000000000..a365059fe --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/colamd/README @@ -0,0 +1,98 @@ +NOTE: Files in this subdirectory are NOT part of the GLPK package, but + are used with GLPK. + + The original code was modified according to GLPK requirements by + Andrew Makhorin <mao@gnu.org>. +************************************************************************ +COLAMD/SYMAMD Version 2.7, Copyright (C) 1998-2007, Timothy A. Davis, +All Rights Reserved. + +Description: + + colamd: an approximate minimum degree column ordering algorithm, + for LU factorization of symmetric or unsymmetric matrices, + QR factorization, least squares, interior point methods for + linear programming problems, and other related problems. + + symamd: an approximate minimum degree ordering algorithm for + Cholesky factorization of symmetric matrices. + +Purpose: + + Colamd computes a permutation Q such that the Cholesky factorization + of (AQ)'(AQ) has less fill-in and requires fewer floating point + operations than A'A. This also provides a good ordering for sparse + partial pivoting methods, P(AQ) = LU, where Q is computed prior to + numerical factorization, and P is computed during numerical + factorization via conventional partial pivoting with row + interchanges. Colamd is the column ordering method used in SuperLU, + part of the ScaLAPACK library. It is also available as built-in + function in MATLAB Version 6, available from MathWorks, Inc. + (http://www.mathworks.com). This routine can be used in place of + colmmd in MATLAB. + + Symamd computes a permutation P of a symmetric matrix A such that + the Cholesky factorization of PAP' has less fill-in and requires + fewer floating point operations than A. Symamd constructs a matrix + M such that M'M has the same nonzero pattern of A, and then orders + the columns of M using colmmd. The column ordering of M is then + returned as the row and column ordering P of A. + +Authors: + + The authors of the code itself are Stefan I. Larimore and Timothy A. + Davis (davis at cise.ufl.edu), University of Florida. The algorithm + was developed in collaboration with John Gilbert, Xerox PARC, and + Esmond Ng, Oak Ridge National Laboratory. + +Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974 and DMS-9803599. + +License: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA. + + Permission is hereby granted to use or copy this program under the + terms of the GNU LGPL, provided that the Copyright, this License, + and the Availability of the original version is retained on all + copies. User documentation of any code that uses this code or any + modified version of this code must cite the Copyright, this License, + the Availability note, and "Used by permission." Permission to + modify the code and to distribute modified code is granted, provided + the Copyright, this License, and the Availability note are retained, + and a notice that the code was modified is included. + + COLAMD is also available under alternate licenses, contact T. Davis + for details. + +Availability: + + The colamd/symamd library is available at: + + http://www.cise.ufl.edu/research/sparse/colamd/ + +References: + + T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate + column minimum degree ordering algorithm, ACM Transactions on + Mathematical Software, vol. 30, no. 3., pp. 353-376, 2004. + + T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: + COLAMD, an approximate column minimum degree ordering algorithm, ACM + Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380, + 2004. diff --git a/resources/3rdparty/glpk-4.53/src/colamd/colamd.c b/resources/3rdparty/glpk-4.53/src/colamd/colamd.c new file mode 100644 index 000000000..86ddd6b74 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/colamd/colamd.c @@ -0,0 +1,3622 @@ +/* ========================================================================== */ +/* === colamd/symamd - a sparse matrix column ordering algorithm ============ */ +/* ========================================================================== */ + +/* COLAMD / SYMAMD + + colamd: an approximate minimum degree column ordering algorithm, + for LU factorization of symmetric or unsymmetric matrices, + QR factorization, least squares, interior point methods for + linear programming problems, and other related problems. + + symamd: an approximate minimum degree ordering algorithm for Cholesky + factorization of symmetric matrices. + + Purpose: + + Colamd computes a permutation Q such that the Cholesky factorization of + (AQ)'(AQ) has less fill-in and requires fewer floating point operations + than A'A. This also provides a good ordering for sparse partial + pivoting methods, P(AQ) = LU, where Q is computed prior to numerical + factorization, and P is computed during numerical factorization via + conventional partial pivoting with row interchanges. Colamd is the + column ordering method used in SuperLU, part of the ScaLAPACK library. + It is also available as built-in function in MATLAB Version 6, + available from MathWorks, Inc. (http://www.mathworks.com). This + routine can be used in place of colmmd in MATLAB. + + Symamd computes a permutation P of a symmetric matrix A such that the + Cholesky factorization of PAP' has less fill-in and requires fewer + floating point operations than A. Symamd constructs a matrix M such + that M'M has the same nonzero pattern of A, and then orders the columns + of M using colmmd. The column ordering of M is then returned as the + row and column ordering P of A. + + Authors: + + The authors of the code itself are Stefan I. Larimore and Timothy A. + Davis (davis at cise.ufl.edu), University of Florida. The algorithm was + developed in collaboration with John Gilbert, Xerox PARC, and Esmond + Ng, Oak Ridge National Laboratory. + + Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974 and DMS-9803599. + + Copyright and License: + + Copyright (c) 1998-2007, Timothy A. Davis, All Rights Reserved. + COLAMD is also available under alternate licenses, contact T. Davis + for details. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA + + Permission is hereby granted to use or copy this program under the + terms of the GNU LGPL, provided that the Copyright, this License, + and the Availability of the original version is retained on all copies. + User documentation of any code that uses this code or any modified + version of this code must cite the Copyright, this License, the + Availability note, and "Used by permission." Permission to modify + the code and to distribute modified code is granted, provided the + Copyright, this License, and the Availability note are retained, + and a notice that the code was modified is included. + + Availability: + + The colamd/symamd library is available at + + http://www.cise.ufl.edu/research/sparse/colamd/ + + This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.c + file. It requires the colamd.h file. It is required by the colamdmex.c + and symamdmex.c files, for the MATLAB interface to colamd and symamd. + Appears as ACM Algorithm 836. + + See the ChangeLog file for changes since Version 1.0. + + References: + + T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate column + minimum degree ordering algorithm, ACM Transactions on Mathematical + Software, vol. 30, no. 3., pp. 353-376, 2004. + + T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD, + an approximate column minimum degree ordering algorithm, ACM + Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380, + 2004. + +*/ + +/* ========================================================================== */ +/* === Description of user-callable routines ================================ */ +/* ========================================================================== */ + +/* COLAMD includes both int and UF_long versions of all its routines. The + * description below is for the int version. For UF_long, all int arguments + * become UF_long. UF_long is normally defined as long, except for WIN64. + + ---------------------------------------------------------------------------- + colamd_recommended: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + size_t colamd_recommended (int nnz, int n_row, int n_col) ; + size_t colamd_l_recommended (UF_long nnz, UF_long n_row, + UF_long n_col) ; + + Purpose: + + Returns recommended value of Alen for use by colamd. Returns 0 + if any input argument is negative. The use of this routine + is optional. Not needed for symamd, which dynamically allocates + its own memory. + + Note that in v2.4 and earlier, these routines returned int or long. + They now return a value of type size_t. + + Arguments (all input arguments): + + int nnz ; Number of nonzeros in the matrix A. This must + be the same value as p [n_col] in the call to + colamd - otherwise you will get a wrong value + of the recommended memory to use. + + int n_row ; Number of rows in the matrix A. + + int n_col ; Number of columns in the matrix A. + + ---------------------------------------------------------------------------- + colamd_set_defaults: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + colamd_set_defaults (double knobs [COLAMD_KNOBS]) ; + colamd_l_set_defaults (double knobs [COLAMD_KNOBS]) ; + + Purpose: + + Sets the default parameters. The use of this routine is optional. + + Arguments: + + double knobs [COLAMD_KNOBS] ; Output only. + + NOTE: the meaning of the dense row/col knobs has changed in v2.4 + + knobs [0] and knobs [1] control dense row and col detection: + + Colamd: rows with more than + max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n_col)) + entries are removed prior to ordering. Columns with more than + max (16, knobs [COLAMD_DENSE_COL] * sqrt (MIN (n_row,n_col))) + entries are removed prior to + ordering, and placed last in the output column ordering. + + Symamd: uses only knobs [COLAMD_DENSE_ROW], which is knobs [0]. + Rows and columns with more than + max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n)) + entries are removed prior to ordering, and placed last in the + output ordering. + + COLAMD_DENSE_ROW and COLAMD_DENSE_COL are defined as 0 and 1, + respectively, in colamd.h. Default values of these two knobs + are both 10. Currently, only knobs [0] and knobs [1] are + used, but future versions may use more knobs. If so, they will + be properly set to their defaults by the future version of + colamd_set_defaults, so that the code that calls colamd will + not need to change, assuming that you either use + colamd_set_defaults, or pass a (double *) NULL pointer as the + knobs array to colamd or symamd. + + knobs [2]: aggressive absorption + + knobs [COLAMD_AGGRESSIVE] controls whether or not to do + aggressive absorption during the ordering. Default is TRUE. + + + ---------------------------------------------------------------------------- + colamd: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + int colamd (int n_row, int n_col, int Alen, int *A, int *p, + double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS]) ; + UF_long colamd_l (UF_long n_row, UF_long n_col, UF_long Alen, + UF_long *A, UF_long *p, double knobs [COLAMD_KNOBS], + UF_long stats [COLAMD_STATS]) ; + + Purpose: + + Computes a column ordering (Q) of A such that P(AQ)=LU or + (AQ)'AQ=LL' have less fill-in and require fewer floating point + operations than factorizing the unpermuted matrix A or A'A, + respectively. + + Returns: + + TRUE (1) if successful, FALSE (0) otherwise. + + Arguments: + + int n_row ; Input argument. + + Number of rows in the matrix A. + Restriction: n_row >= 0. + Colamd returns FALSE if n_row is negative. + + int n_col ; Input argument. + + Number of columns in the matrix A. + Restriction: n_col >= 0. + Colamd returns FALSE if n_col is negative. + + int Alen ; Input argument. + + Restriction (see note): + Alen >= 2*nnz + 6*(n_col+1) + 4*(n_row+1) + n_col + Colamd returns FALSE if these conditions are not met. + + Note: this restriction makes an modest assumption regarding + the size of the two typedef's structures in colamd.h. + We do, however, guarantee that + + Alen >= colamd_recommended (nnz, n_row, n_col) + + will be sufficient. Note: the macro version does not check + for integer overflow, and thus is not recommended. Use + the colamd_recommended routine instead. + + int A [Alen] ; Input argument, undefined on output. + + A is an integer array of size Alen. Alen must be at least as + large as the bare minimum value given above, but this is very + low, and can result in excessive run time. For best + performance, we recommend that Alen be greater than or equal to + colamd_recommended (nnz, n_row, n_col), which adds + nnz/5 to the bare minimum value given above. + + On input, the row indices of the entries in column c of the + matrix are held in A [(p [c]) ... (p [c+1]-1)]. The row indices + in a given column c need not be in ascending order, and + duplicate row indices may be be present. However, colamd will + work a little faster if both of these conditions are met + (Colamd puts the matrix into this format, if it finds that the + the conditions are not met). + + The matrix is 0-based. That is, rows are in the range 0 to + n_row-1, and columns are in the range 0 to n_col-1. Colamd + returns FALSE if any row index is out of range. + + The contents of A are modified during ordering, and are + undefined on output. + + int p [n_col+1] ; Both input and output argument. + + p is an integer array of size n_col+1. On input, it holds the + "pointers" for the column form of the matrix A. Column c of + the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first + entry, p [0], must be zero, and p [c] <= p [c+1] must hold + for all c in the range 0 to n_col-1. The value p [n_col] is + thus the total number of entries in the pattern of the matrix A. + Colamd returns FALSE if these conditions are not met. + + On output, if colamd returns TRUE, the array p holds the column + permutation (Q, for P(AQ)=LU or (AQ)'(AQ)=LL'), where p [0] is + the first column index in the new ordering, and p [n_col-1] is + the last. That is, p [k] = j means that column j of A is the + kth pivot column, in AQ, where k is in the range 0 to n_col-1 + (p [0] = j means that column j of A is the first column in AQ). + + If colamd returns FALSE, then no permutation is returned, and + p is undefined on output. + + double knobs [COLAMD_KNOBS] ; Input argument. + + See colamd_set_defaults for a description. + + int stats [COLAMD_STATS] ; Output argument. + + Statistics on the ordering, and error status. + See colamd.h for related definitions. + Colamd returns FALSE if stats is not present. + + stats [0]: number of dense or empty rows ignored. + + stats [1]: number of dense or empty columns ignored (and + ordered last in the output permutation p) + Note that a row can become "empty" if it + contains only "dense" and/or "empty" columns, + and similarly a column can become "empty" if it + only contains "dense" and/or "empty" rows. + + stats [2]: number of garbage collections performed. + This can be excessively high if Alen is close + to the minimum required value. + + stats [3]: status code. < 0 is an error code. + > 1 is a warning or notice. + + 0 OK. Each column of the input matrix contained + row indices in increasing order, with no + duplicates. + + 1 OK, but columns of input matrix were jumbled + (unsorted columns or duplicate entries). Colamd + had to do some extra work to sort the matrix + first and remove duplicate entries, but it + still was able to return a valid permutation + (return value of colamd was TRUE). + + stats [4]: highest numbered column that + is unsorted or has duplicate + entries. + stats [5]: last seen duplicate or + unsorted row index. + stats [6]: number of duplicate or + unsorted row indices. + + -1 A is a null pointer + + -2 p is a null pointer + + -3 n_row is negative + + stats [4]: n_row + + -4 n_col is negative + + stats [4]: n_col + + -5 number of nonzeros in matrix is negative + + stats [4]: number of nonzeros, p [n_col] + + -6 p [0] is nonzero + + stats [4]: p [0] + + -7 A is too small + + stats [4]: required size + stats [5]: actual size (Alen) + + -8 a column has a negative number of entries + + stats [4]: column with < 0 entries + stats [5]: number of entries in col + + -9 a row index is out of bounds + + stats [4]: column with bad row index + stats [5]: bad row index + stats [6]: n_row, # of rows of matrx + + -10 (unused; see symamd.c) + + -999 (unused; see symamd.c) + + Future versions may return more statistics in the stats array. + + Example: + + See http://www.cise.ufl.edu/research/sparse/colamd/example.c + for a complete example. + + To order the columns of a 5-by-4 matrix with 11 nonzero entries in + the following nonzero pattern + + x 0 x 0 + x 0 x x + 0 x x 0 + 0 0 x x + x x 0 0 + + with default knobs and no output statistics, do the following: + + #include "colamd.h" + #define ALEN 100 + int A [ALEN] = {0, 1, 4, 2, 4, 0, 1, 2, 3, 1, 3} ; + int p [ ] = {0, 3, 5, 9, 11} ; + int stats [COLAMD_STATS] ; + colamd (5, 4, ALEN, A, p, (double *) NULL, stats) ; + + The permutation is returned in the array p, and A is destroyed. + + ---------------------------------------------------------------------------- + symamd: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + int symamd (int n, int *A, int *p, int *perm, + double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS], + void (*allocate) (size_t, size_t), void (*release) (void *)) ; + UF_long symamd_l (UF_long n, UF_long *A, UF_long *p, UF_long *perm, + double knobs [COLAMD_KNOBS], UF_long stats [COLAMD_STATS], + void (*allocate) (size_t, size_t), void (*release) (void *)) ; + + Purpose: + + The symamd routine computes an ordering P of a symmetric sparse + matrix A such that the Cholesky factorization PAP' = LL' remains + sparse. It is based on a column ordering of a matrix M constructed + so that the nonzero pattern of M'M is the same as A. The matrix A + is assumed to be symmetric; only the strictly lower triangular part + is accessed. You must pass your selected memory allocator (usually + calloc/free or mxCalloc/mxFree) to symamd, for it to allocate + memory for the temporary matrix M. + + Returns: + + TRUE (1) if successful, FALSE (0) otherwise. + + Arguments: + + int n ; Input argument. + + Number of rows and columns in the symmetrix matrix A. + Restriction: n >= 0. + Symamd returns FALSE if n is negative. + + int A [nnz] ; Input argument. + + A is an integer array of size nnz, where nnz = p [n]. + + The row indices of the entries in column c of the matrix are + held in A [(p [c]) ... (p [c+1]-1)]. The row indices in a + given column c need not be in ascending order, and duplicate + row indices may be present. However, symamd will run faster + if the columns are in sorted order with no duplicate entries. + + The matrix is 0-based. That is, rows are in the range 0 to + n-1, and columns are in the range 0 to n-1. Symamd + returns FALSE if any row index is out of range. + + The contents of A are not modified. + + int p [n+1] ; Input argument. + + p is an integer array of size n+1. On input, it holds the + "pointers" for the column form of the matrix A. Column c of + the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first + entry, p [0], must be zero, and p [c] <= p [c+1] must hold + for all c in the range 0 to n-1. The value p [n] is + thus the total number of entries in the pattern of the matrix A. + Symamd returns FALSE if these conditions are not met. + + The contents of p are not modified. + + int perm [n+1] ; Output argument. + + On output, if symamd returns TRUE, the array perm holds the + permutation P, where perm [0] is the first index in the new + ordering, and perm [n-1] is the last. That is, perm [k] = j + means that row and column j of A is the kth column in PAP', + where k is in the range 0 to n-1 (perm [0] = j means + that row and column j of A are the first row and column in + PAP'). The array is used as a workspace during the ordering, + which is why it must be of length n+1, not just n. + + double knobs [COLAMD_KNOBS] ; Input argument. + + See colamd_set_defaults for a description. + + int stats [COLAMD_STATS] ; Output argument. + + Statistics on the ordering, and error status. + See colamd.h for related definitions. + Symamd returns FALSE if stats is not present. + + stats [0]: number of dense or empty row and columns ignored + (and ordered last in the output permutation + perm). Note that a row/column can become + "empty" if it contains only "dense" and/or + "empty" columns/rows. + + stats [1]: (same as stats [0]) + + stats [2]: number of garbage collections performed. + + stats [3]: status code. < 0 is an error code. + > 1 is a warning or notice. + + 0 OK. Each column of the input matrix contained + row indices in increasing order, with no + duplicates. + + 1 OK, but columns of input matrix were jumbled + (unsorted columns or duplicate entries). Symamd + had to do some extra work to sort the matrix + first and remove duplicate entries, but it + still was able to return a valid permutation + (return value of symamd was TRUE). + + stats [4]: highest numbered column that + is unsorted or has duplicate + entries. + stats [5]: last seen duplicate or + unsorted row index. + stats [6]: number of duplicate or + unsorted row indices. + + -1 A is a null pointer + + -2 p is a null pointer + + -3 (unused, see colamd.c) + + -4 n is negative + + stats [4]: n + + -5 number of nonzeros in matrix is negative + + stats [4]: # of nonzeros (p [n]). + + -6 p [0] is nonzero + + stats [4]: p [0] + + -7 (unused) + + -8 a column has a negative number of entries + + stats [4]: column with < 0 entries + stats [5]: number of entries in col + + -9 a row index is out of bounds + + stats [4]: column with bad row index + stats [5]: bad row index + stats [6]: n_row, # of rows of matrx + + -10 out of memory (unable to allocate temporary + workspace for M or count arrays using the + "allocate" routine passed into symamd). + + Future versions may return more statistics in the stats array. + + void * (*allocate) (size_t, size_t) + + A pointer to a function providing memory allocation. The + allocated memory must be returned initialized to zero. For a + C application, this argument should normally be a pointer to + calloc. For a MATLAB mexFunction, the routine mxCalloc is + passed instead. + + void (*release) (size_t, size_t) + + A pointer to a function that frees memory allocated by the + memory allocation routine above. For a C application, this + argument should normally be a pointer to free. For a MATLAB + mexFunction, the routine mxFree is passed instead. + + + ---------------------------------------------------------------------------- + colamd_report: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + colamd_report (int stats [COLAMD_STATS]) ; + colamd_l_report (UF_long stats [COLAMD_STATS]) ; + + Purpose: + + Prints the error status and statistics recorded in the stats + array on the standard error output (for a standard C routine) + or on the MATLAB output (for a mexFunction). + + Arguments: + + int stats [COLAMD_STATS] ; Input only. Statistics from colamd. + + + ---------------------------------------------------------------------------- + symamd_report: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + symamd_report (int stats [COLAMD_STATS]) ; + symamd_l_report (UF_long stats [COLAMD_STATS]) ; + + Purpose: + + Prints the error status and statistics recorded in the stats + array on the standard error output (for a standard C routine) + or on the MATLAB output (for a mexFunction). + + Arguments: + + int stats [COLAMD_STATS] ; Input only. Statistics from symamd. + + +*/ + +/* ========================================================================== */ +/* === Scaffolding code definitions ======================================== */ +/* ========================================================================== */ + +/* Ensure that debugging is turned off: */ +#ifndef NDEBUG +#define NDEBUG +#endif + +/* turn on debugging by uncommenting the following line + #undef NDEBUG +*/ + +/* + Our "scaffolding code" philosophy: In our opinion, well-written library + code should keep its "debugging" code, and just normally have it turned off + by the compiler so as not to interfere with performance. This serves + several purposes: + + (1) assertions act as comments to the reader, telling you what the code + expects at that point. All assertions will always be true (unless + there really is a bug, of course). + + (2) leaving in the scaffolding code assists anyone who would like to modify + the code, or understand the algorithm (by reading the debugging output, + one can get a glimpse into what the code is doing). + + (3) (gasp!) for actually finding bugs. This code has been heavily tested + and "should" be fully functional and bug-free ... but you never know... + + The code will become outrageously slow when debugging is + enabled. To control the level of debugging output, set an environment + variable D to 0 (little), 1 (some), 2, 3, or 4 (lots). When debugging, + you should see the following message on the standard output: + + colamd: debug version, D = 1 (THIS WILL BE SLOW!) + + or a similar message for symamd. If you don't, then debugging has not + been enabled. + +*/ + +/* ========================================================================== */ +/* === Include files ======================================================== */ +/* ========================================================================== */ + +#include "colamd.h" + +#if 0 /* by mao */ +#include <limits.h> +#include <math.h> + +#ifdef MATLAB_MEX_FILE +#include "mex.h" +#include "matrix.h" +#endif /* MATLAB_MEX_FILE */ + +#if !defined (NPRINT) || !defined (NDEBUG) +#include <stdio.h> +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif +#endif + +/* ========================================================================== */ +/* === int or UF_long ======================================================= */ +/* ========================================================================== */ + +#if 0 /* by mao */ +/* define UF_long */ +#include "UFconfig.h" +#endif + +#ifdef DLONG + +#define Int UF_long +#define ID UF_long_id +#define Int_MAX UF_long_max + +#define COLAMD_recommended colamd_l_recommended +#define COLAMD_set_defaults colamd_l_set_defaults +#define COLAMD_MAIN colamd_l +#define SYMAMD_MAIN symamd_l +#define COLAMD_report colamd_l_report +#define SYMAMD_report symamd_l_report + +#else + +#define Int int +#define ID "%d" +#define Int_MAX INT_MAX + +#define COLAMD_recommended colamd_recommended +#define COLAMD_set_defaults colamd_set_defaults +#define COLAMD_MAIN colamd +#define SYMAMD_MAIN symamd +#define COLAMD_report colamd_report +#define SYMAMD_report symamd_report + +#endif + +/* ========================================================================== */ +/* === Row and Column structures ============================================ */ +/* ========================================================================== */ + +/* User code that makes use of the colamd/symamd routines need not directly */ +/* reference these structures. They are used only for colamd_recommended. */ + +typedef struct Colamd_Col_struct +{ + Int start ; /* index for A of first row in this column, or DEAD */ + /* if column is dead */ + Int length ; /* number of rows in this column */ + union + { + Int thickness ; /* number of original columns represented by this */ + /* col, if the column is alive */ + Int parent ; /* parent in parent tree super-column structure, if */ + /* the column is dead */ + } shared1 ; + union + { + Int score ; /* the score used to maintain heap, if col is alive */ + Int order ; /* pivot ordering of this column, if col is dead */ + } shared2 ; + union + { + Int headhash ; /* head of a hash bucket, if col is at the head of */ + /* a degree list */ + Int hash ; /* hash value, if col is not in a degree list */ + Int prev ; /* previous column in degree list, if col is in a */ + /* degree list (but not at the head of a degree list) */ + } shared3 ; + union + { + Int degree_next ; /* next column, if col is in a degree list */ + Int hash_next ; /* next column, if col is in a hash list */ + } shared4 ; + +} Colamd_Col ; + +typedef struct Colamd_Row_struct +{ + Int start ; /* index for A of first col in this row */ + Int length ; /* number of principal columns in this row */ + union + { + Int degree ; /* number of principal & non-principal columns in row */ + Int p ; /* used as a row pointer in init_rows_cols () */ + } shared1 ; + union + { + Int mark ; /* for computing set differences and marking dead rows*/ + Int first_column ;/* first column in row (used in garbage collection) */ + } shared2 ; + +} Colamd_Row ; + +/* ========================================================================== */ +/* === Definitions ========================================================== */ +/* ========================================================================== */ + +/* Routines are either PUBLIC (user-callable) or PRIVATE (not user-callable) */ +#define PUBLIC +#define PRIVATE static + +#define DENSE_DEGREE(alpha,n) \ + ((Int) MAX (16.0, (alpha) * sqrt ((double) (n)))) + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +#define ONES_COMPLEMENT(r) (-(r)-1) + +/* -------------------------------------------------------------------------- */ +/* Change for version 2.1: define TRUE and FALSE only if not yet defined */ +/* -------------------------------------------------------------------------- */ + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +/* -------------------------------------------------------------------------- */ + +#define EMPTY (-1) + +/* Row and column status */ +#define ALIVE (0) +#define DEAD (-1) + +/* Column status */ +#define DEAD_PRINCIPAL (-1) +#define DEAD_NON_PRINCIPAL (-2) + +/* Macros for row and column status update and checking. */ +#define ROW_IS_DEAD(r) ROW_IS_MARKED_DEAD (Row[r].shared2.mark) +#define ROW_IS_MARKED_DEAD(row_mark) (row_mark < ALIVE) +#define ROW_IS_ALIVE(r) (Row [r].shared2.mark >= ALIVE) +#define COL_IS_DEAD(c) (Col [c].start < ALIVE) +#define COL_IS_ALIVE(c) (Col [c].start >= ALIVE) +#define COL_IS_DEAD_PRINCIPAL(c) (Col [c].start == DEAD_PRINCIPAL) +#define KILL_ROW(r) { Row [r].shared2.mark = DEAD ; } +#define KILL_PRINCIPAL_COL(c) { Col [c].start = DEAD_PRINCIPAL ; } +#define KILL_NON_PRINCIPAL_COL(c) { Col [c].start = DEAD_NON_PRINCIPAL ; } + +/* ========================================================================== */ +/* === Colamd reporting mechanism =========================================== */ +/* ========================================================================== */ + +#if defined (MATLAB_MEX_FILE) || defined (MATHWORKS) +/* In MATLAB, matrices are 1-based to the user, but 0-based internally */ +#define INDEX(i) ((i)+1) +#else +/* In C, matrices are 0-based and indices are reported as such in *_report */ +#define INDEX(i) (i) +#endif + +/* All output goes through the PRINTF macro. */ +#define PRINTF(params) { if (colamd_printf != NULL) (void) colamd_printf params ; } + +/* ========================================================================== */ +/* === Prototypes of PRIVATE routines ======================================= */ +/* ========================================================================== */ + +PRIVATE Int init_rows_cols +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int p [], + Int stats [COLAMD_STATS] +) ; + +PRIVATE void init_scoring +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int head [], + double knobs [COLAMD_KNOBS], + Int *p_n_row2, + Int *p_n_col2, + Int *p_max_deg +) ; + +PRIVATE Int find_ordering +( + Int n_row, + Int n_col, + Int Alen, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int head [], + Int n_col2, + Int max_deg, + Int pfree, + Int aggressive +) ; + +PRIVATE void order_children +( + Int n_col, + Colamd_Col Col [], + Int p [] +) ; + +PRIVATE void detect_super_cols +( + +#ifndef NDEBUG + Int n_col, + Colamd_Row Row [], +#endif /* NDEBUG */ + + Colamd_Col Col [], + Int A [], + Int head [], + Int row_start, + Int row_length +) ; + +PRIVATE Int garbage_collection +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int *pfree +) ; + +PRIVATE Int clear_mark +( + Int tag_mark, + Int max_mark, + Int n_row, + Colamd_Row Row [] +) ; + +PRIVATE void print_report +( + char *method, + Int stats [COLAMD_STATS] +) ; + +/* ========================================================================== */ +/* === Debugging prototypes and definitions ================================= */ +/* ========================================================================== */ + +#ifndef NDEBUG + +#if 0 /* by mao */ +#include <assert.h> +#endif + +/* colamd_debug is the *ONLY* global variable, and is only */ +/* present when debugging */ + +PRIVATE Int colamd_debug = 0 ; /* debug print level */ + +#define DEBUG0(params) { PRINTF (params) ; } +#define DEBUG1(params) { if (colamd_debug >= 1) PRINTF (params) ; } +#define DEBUG2(params) { if (colamd_debug >= 2) PRINTF (params) ; } +#define DEBUG3(params) { if (colamd_debug >= 3) PRINTF (params) ; } +#define DEBUG4(params) { if (colamd_debug >= 4) PRINTF (params) ; } + +#if 0 /* by mao */ +#ifdef MATLAB_MEX_FILE +#define ASSERT(expression) (mxAssert ((expression), "")) +#else +#define ASSERT(expression) (assert (expression)) +#endif /* MATLAB_MEX_FILE */ +#else +#define ASSERT xassert +#endif + +PRIVATE void colamd_get_debug /* gets the debug print level from getenv */ +( + char *method +) ; + +PRIVATE void debug_deg_lists +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int head [], + Int min_score, + Int should, + Int max_deg +) ; + +PRIVATE void debug_mark +( + Int n_row, + Colamd_Row Row [], + Int tag_mark, + Int max_mark +) ; + +PRIVATE void debug_matrix +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [] +) ; + +PRIVATE void debug_structures +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int n_col2 +) ; + +#else /* NDEBUG */ + +/* === No debugging ========================================================= */ + +#define DEBUG0(params) ; +#define DEBUG1(params) ; +#define DEBUG2(params) ; +#define DEBUG3(params) ; +#define DEBUG4(params) ; + +#define ASSERT(expression) + +#endif /* NDEBUG */ + +/* ========================================================================== */ +/* === USER-CALLABLE ROUTINES: ============================================== */ +/* ========================================================================== */ + +/* ========================================================================== */ +/* === colamd_recommended =================================================== */ +/* ========================================================================== */ + +/* + The colamd_recommended routine returns the suggested size for Alen. This + value has been determined to provide good balance between the number of + garbage collections and the memory requirements for colamd. If any + argument is negative, or if integer overflow occurs, a 0 is returned as an + error condition. 2*nnz space is required for the row and column + indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is + required for the Col and Row arrays, respectively, which are internal to + colamd (roughly 6*n_col + 4*n_row). An additional n_col space is the + minimal amount of "elbow room", and nnz/5 more space is recommended for + run time efficiency. + + Alen is approximately 2.2*nnz + 7*n_col + 4*n_row + 10. + + This function is not needed when using symamd. +*/ + +/* add two values of type size_t, and check for integer overflow */ +static size_t t_add (size_t a, size_t b, int *ok) +{ + (*ok) = (*ok) && ((a + b) >= MAX (a,b)) ; + return ((*ok) ? (a + b) : 0) ; +} + +/* compute a*k where k is a small integer, and check for integer overflow */ +static size_t t_mult (size_t a, size_t k, int *ok) +{ + size_t i, s = 0 ; + for (i = 0 ; i < k ; i++) + { + s = t_add (s, a, ok) ; + } + return (s) ; +} + +/* size of the Col and Row structures */ +#define COLAMD_C(n_col,ok) \ + ((t_mult (t_add (n_col, 1, ok), sizeof (Colamd_Col), ok) / sizeof (Int))) + +#define COLAMD_R(n_row,ok) \ + ((t_mult (t_add (n_row, 1, ok), sizeof (Colamd_Row), ok) / sizeof (Int))) + + +PUBLIC size_t COLAMD_recommended /* returns recommended value of Alen. */ +( + /* === Parameters ======================================================= */ + + Int nnz, /* number of nonzeros in A */ + Int n_row, /* number of rows in A */ + Int n_col /* number of columns in A */ +) +{ + size_t s, c, r ; + int ok = TRUE ; + if (nnz < 0 || n_row < 0 || n_col < 0) + { + return (0) ; + } + s = t_mult (nnz, 2, &ok) ; /* 2*nnz */ + c = COLAMD_C (n_col, &ok) ; /* size of column structures */ + r = COLAMD_R (n_row, &ok) ; /* size of row structures */ + s = t_add (s, c, &ok) ; + s = t_add (s, r, &ok) ; + s = t_add (s, n_col, &ok) ; /* elbow room */ + s = t_add (s, nnz/5, &ok) ; /* elbow room */ + ok = ok && (s < Int_MAX) ; + return (ok ? s : 0) ; +} + + +/* ========================================================================== */ +/* === colamd_set_defaults ================================================== */ +/* ========================================================================== */ + +/* + The colamd_set_defaults routine sets the default values of the user- + controllable parameters for colamd and symamd: + + Colamd: rows with more than max (16, knobs [0] * sqrt (n_col)) + entries are removed prior to ordering. Columns with more than + max (16, knobs [1] * sqrt (MIN (n_row,n_col))) entries are removed + prior to ordering, and placed last in the output column ordering. + + Symamd: Rows and columns with more than max (16, knobs [0] * sqrt (n)) + entries are removed prior to ordering, and placed last in the + output ordering. + + knobs [0] dense row control + + knobs [1] dense column control + + knobs [2] if nonzero, do aggresive absorption + + knobs [3..19] unused, but future versions might use this + +*/ + +PUBLIC void COLAMD_set_defaults +( + /* === Parameters ======================================================= */ + + double knobs [COLAMD_KNOBS] /* knob array */ +) +{ + /* === Local variables ================================================== */ + + Int i ; + + if (!knobs) + { + return ; /* no knobs to initialize */ + } + for (i = 0 ; i < COLAMD_KNOBS ; i++) + { + knobs [i] = 0 ; + } + knobs [COLAMD_DENSE_ROW] = 10 ; + knobs [COLAMD_DENSE_COL] = 10 ; + knobs [COLAMD_AGGRESSIVE] = TRUE ; /* default: do aggressive absorption*/ +} + + +/* ========================================================================== */ +/* === symamd =============================================================== */ +/* ========================================================================== */ + +PUBLIC Int SYMAMD_MAIN /* return TRUE if OK, FALSE otherwise */ +( + /* === Parameters ======================================================= */ + + Int n, /* number of rows and columns of A */ + Int A [], /* row indices of A */ + Int p [], /* column pointers of A */ + Int perm [], /* output permutation, size n+1 */ + double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */ + Int stats [COLAMD_STATS], /* output statistics and error codes */ + void * (*allocate) (size_t, size_t), + /* pointer to calloc (ANSI C) or */ + /* mxCalloc (for MATLAB mexFunction) */ + void (*release) (void *) + /* pointer to free (ANSI C) or */ + /* mxFree (for MATLAB mexFunction) */ +) +{ + /* === Local variables ================================================== */ + + Int *count ; /* length of each column of M, and col pointer*/ + Int *mark ; /* mark array for finding duplicate entries */ + Int *M ; /* row indices of matrix M */ + size_t Mlen ; /* length of M */ + Int n_row ; /* number of rows in M */ + Int nnz ; /* number of entries in A */ + Int i ; /* row index of A */ + Int j ; /* column index of A */ + Int k ; /* row index of M */ + Int mnz ; /* number of nonzeros in M */ + Int pp ; /* index into a column of A */ + Int last_row ; /* last row seen in the current column */ + Int length ; /* number of nonzeros in a column */ + + double cknobs [COLAMD_KNOBS] ; /* knobs for colamd */ + double default_knobs [COLAMD_KNOBS] ; /* default knobs for colamd */ + +#ifndef NDEBUG + colamd_get_debug ("symamd") ; +#endif /* NDEBUG */ + + /* === Check the input arguments ======================================== */ + + if (!stats) + { + DEBUG0 (("symamd: stats not present\n")) ; + return (FALSE) ; + } + for (i = 0 ; i < COLAMD_STATS ; i++) + { + stats [i] = 0 ; + } + stats [COLAMD_STATUS] = COLAMD_OK ; + stats [COLAMD_INFO1] = -1 ; + stats [COLAMD_INFO2] = -1 ; + + if (!A) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ; + DEBUG0 (("symamd: A not present\n")) ; + return (FALSE) ; + } + + if (!p) /* p is not present */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ; + DEBUG0 (("symamd: p not present\n")) ; + return (FALSE) ; + } + + if (n < 0) /* n must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ; + stats [COLAMD_INFO1] = n ; + DEBUG0 (("symamd: n negative %d\n", n)) ; + return (FALSE) ; + } + + nnz = p [n] ; + if (nnz < 0) /* nnz must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ; + stats [COLAMD_INFO1] = nnz ; + DEBUG0 (("symamd: number of entries negative %d\n", nnz)) ; + return (FALSE) ; + } + + if (p [0] != 0) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ; + stats [COLAMD_INFO1] = p [0] ; + DEBUG0 (("symamd: p[0] not zero %d\n", p [0])) ; + return (FALSE) ; + } + + /* === If no knobs, set default knobs =================================== */ + + if (!knobs) + { + COLAMD_set_defaults (default_knobs) ; + knobs = default_knobs ; + } + + /* === Allocate count and mark ========================================== */ + + count = (Int *) ((*allocate) (n+1, sizeof (Int))) ; + if (!count) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; + DEBUG0 (("symamd: allocate count (size %d) failed\n", n+1)) ; + return (FALSE) ; + } + + mark = (Int *) ((*allocate) (n+1, sizeof (Int))) ; + if (!mark) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; + (*release) ((void *) count) ; + DEBUG0 (("symamd: allocate mark (size %d) failed\n", n+1)) ; + return (FALSE) ; + } + + /* === Compute column counts of M, check if A is valid ================== */ + + stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/ + + for (i = 0 ; i < n ; i++) + { + mark [i] = -1 ; + } + + for (j = 0 ; j < n ; j++) + { + last_row = -1 ; + + length = p [j+1] - p [j] ; + if (length < 0) + { + /* column pointers must be non-decreasing */ + stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ; + stats [COLAMD_INFO1] = j ; + stats [COLAMD_INFO2] = length ; + (*release) ((void *) count) ; + (*release) ((void *) mark) ; + DEBUG0 (("symamd: col %d negative length %d\n", j, length)) ; + return (FALSE) ; + } + + for (pp = p [j] ; pp < p [j+1] ; pp++) + { + i = A [pp] ; + if (i < 0 || i >= n) + { + /* row index i, in column j, is out of bounds */ + stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ; + stats [COLAMD_INFO1] = j ; + stats [COLAMD_INFO2] = i ; + stats [COLAMD_INFO3] = n ; + (*release) ((void *) count) ; + (*release) ((void *) mark) ; + DEBUG0 (("symamd: row %d col %d out of bounds\n", i, j)) ; + return (FALSE) ; + } + + if (i <= last_row || mark [i] == j) + { + /* row index is unsorted or repeated (or both), thus col */ + /* is jumbled. This is a notice, not an error condition. */ + stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ; + stats [COLAMD_INFO1] = j ; + stats [COLAMD_INFO2] = i ; + (stats [COLAMD_INFO3]) ++ ; + DEBUG1 (("symamd: row %d col %d unsorted/duplicate\n", i, j)) ; + } + + if (i > j && mark [i] != j) + { + /* row k of M will contain column indices i and j */ + count [i]++ ; + count [j]++ ; + } + + /* mark the row as having been seen in this column */ + mark [i] = j ; + + last_row = i ; + } + } + + /* v2.4: removed free(mark) */ + + /* === Compute column pointers of M ===================================== */ + + /* use output permutation, perm, for column pointers of M */ + perm [0] = 0 ; + for (j = 1 ; j <= n ; j++) + { + perm [j] = perm [j-1] + count [j-1] ; + } + for (j = 0 ; j < n ; j++) + { + count [j] = perm [j] ; + } + + /* === Construct M ====================================================== */ + + mnz = perm [n] ; + n_row = mnz / 2 ; + Mlen = COLAMD_recommended (mnz, n_row, n) ; + M = (Int *) ((*allocate) (Mlen, sizeof (Int))) ; + DEBUG0 (("symamd: M is %d-by-%d with %d entries, Mlen = %g\n", + n_row, n, mnz, (double) Mlen)) ; + + if (!M) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; + (*release) ((void *) count) ; + (*release) ((void *) mark) ; + DEBUG0 (("symamd: allocate M (size %g) failed\n", (double) Mlen)) ; + return (FALSE) ; + } + + k = 0 ; + + if (stats [COLAMD_STATUS] == COLAMD_OK) + { + /* Matrix is OK */ + for (j = 0 ; j < n ; j++) + { + ASSERT (p [j+1] - p [j] >= 0) ; + for (pp = p [j] ; pp < p [j+1] ; pp++) + { + i = A [pp] ; + ASSERT (i >= 0 && i < n) ; + if (i > j) + { + /* row k of M contains column indices i and j */ + M [count [i]++] = k ; + M [count [j]++] = k ; + k++ ; + } + } + } + } + else + { + /* Matrix is jumbled. Do not add duplicates to M. Unsorted cols OK. */ + DEBUG0 (("symamd: Duplicates in A.\n")) ; + for (i = 0 ; i < n ; i++) + { + mark [i] = -1 ; + } + for (j = 0 ; j < n ; j++) + { + ASSERT (p [j+1] - p [j] >= 0) ; + for (pp = p [j] ; pp < p [j+1] ; pp++) + { + i = A [pp] ; + ASSERT (i >= 0 && i < n) ; + if (i > j && mark [i] != j) + { + /* row k of M contains column indices i and j */ + M [count [i]++] = k ; + M [count [j]++] = k ; + k++ ; + mark [i] = j ; + } + } + } + /* v2.4: free(mark) moved below */ + } + + /* count and mark no longer needed */ + (*release) ((void *) count) ; + (*release) ((void *) mark) ; /* v2.4: free (mark) moved here */ + ASSERT (k == n_row) ; + + /* === Adjust the knobs for M =========================================== */ + + for (i = 0 ; i < COLAMD_KNOBS ; i++) + { + cknobs [i] = knobs [i] ; + } + + /* there are no dense rows in M */ + cknobs [COLAMD_DENSE_ROW] = -1 ; + cknobs [COLAMD_DENSE_COL] = knobs [COLAMD_DENSE_ROW] ; + + /* === Order the columns of M =========================================== */ + + /* v2.4: colamd cannot fail here, so the error check is removed */ + (void) COLAMD_MAIN (n_row, n, (Int) Mlen, M, perm, cknobs, stats) ; + + /* Note that the output permutation is now in perm */ + + /* === get the statistics for symamd from colamd ======================== */ + + /* a dense column in colamd means a dense row and col in symamd */ + stats [COLAMD_DENSE_ROW] = stats [COLAMD_DENSE_COL] ; + + /* === Free M =========================================================== */ + + (*release) ((void *) M) ; + DEBUG0 (("symamd: done.\n")) ; + return (TRUE) ; + +} + +/* ========================================================================== */ +/* === colamd =============================================================== */ +/* ========================================================================== */ + +/* + The colamd routine computes a column ordering Q of a sparse matrix + A such that the LU factorization P(AQ) = LU remains sparse, where P is + selected via partial pivoting. The routine can also be viewed as + providing a permutation Q such that the Cholesky factorization + (AQ)'(AQ) = LL' remains sparse. +*/ + +PUBLIC Int COLAMD_MAIN /* returns TRUE if successful, FALSE otherwise*/ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows in A */ + Int n_col, /* number of columns in A */ + Int Alen, /* length of A */ + Int A [], /* row indices of A */ + Int p [], /* pointers to columns in A */ + double knobs [COLAMD_KNOBS],/* parameters (uses defaults if NULL) */ + Int stats [COLAMD_STATS] /* output statistics and error codes */ +) +{ + /* === Local variables ================================================== */ + + Int i ; /* loop index */ + Int nnz ; /* nonzeros in A */ + size_t Row_size ; /* size of Row [], in integers */ + size_t Col_size ; /* size of Col [], in integers */ + size_t need ; /* minimum required length of A */ + Colamd_Row *Row ; /* pointer into A of Row [0..n_row] array */ + Colamd_Col *Col ; /* pointer into A of Col [0..n_col] array */ + Int n_col2 ; /* number of non-dense, non-empty columns */ + Int n_row2 ; /* number of non-dense, non-empty rows */ + Int ngarbage ; /* number of garbage collections performed */ + Int max_deg ; /* maximum row degree */ + double default_knobs [COLAMD_KNOBS] ; /* default knobs array */ + Int aggressive ; /* do aggressive absorption */ + int ok ; + +#ifndef NDEBUG + colamd_get_debug ("colamd") ; +#endif /* NDEBUG */ + + /* === Check the input arguments ======================================== */ + + if (!stats) + { + DEBUG0 (("colamd: stats not present\n")) ; + return (FALSE) ; + } + for (i = 0 ; i < COLAMD_STATS ; i++) + { + stats [i] = 0 ; + } + stats [COLAMD_STATUS] = COLAMD_OK ; + stats [COLAMD_INFO1] = -1 ; + stats [COLAMD_INFO2] = -1 ; + + if (!A) /* A is not present */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ; + DEBUG0 (("colamd: A not present\n")) ; + return (FALSE) ; + } + + if (!p) /* p is not present */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ; + DEBUG0 (("colamd: p not present\n")) ; + return (FALSE) ; + } + + if (n_row < 0) /* n_row must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_nrow_negative ; + stats [COLAMD_INFO1] = n_row ; + DEBUG0 (("colamd: nrow negative %d\n", n_row)) ; + return (FALSE) ; + } + + if (n_col < 0) /* n_col must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ; + stats [COLAMD_INFO1] = n_col ; + DEBUG0 (("colamd: ncol negative %d\n", n_col)) ; + return (FALSE) ; + } + + nnz = p [n_col] ; + if (nnz < 0) /* nnz must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ; + stats [COLAMD_INFO1] = nnz ; + DEBUG0 (("colamd: number of entries negative %d\n", nnz)) ; + return (FALSE) ; + } + + if (p [0] != 0) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ; + stats [COLAMD_INFO1] = p [0] ; + DEBUG0 (("colamd: p[0] not zero %d\n", p [0])) ; + return (FALSE) ; + } + + /* === If no knobs, set default knobs =================================== */ + + if (!knobs) + { + COLAMD_set_defaults (default_knobs) ; + knobs = default_knobs ; + } + + aggressive = (knobs [COLAMD_AGGRESSIVE] != FALSE) ; + + /* === Allocate the Row and Col arrays from array A ===================== */ + + ok = TRUE ; + Col_size = COLAMD_C (n_col, &ok) ; /* size of Col array of structs */ + Row_size = COLAMD_R (n_row, &ok) ; /* size of Row array of structs */ + + /* need = 2*nnz + n_col + Col_size + Row_size ; */ + need = t_mult (nnz, 2, &ok) ; + need = t_add (need, n_col, &ok) ; + need = t_add (need, Col_size, &ok) ; + need = t_add (need, Row_size, &ok) ; + + if (!ok || need > (size_t) Alen || need > Int_MAX) + { + /* not enough space in array A to perform the ordering */ + stats [COLAMD_STATUS] = COLAMD_ERROR_A_too_small ; + stats [COLAMD_INFO1] = need ; + stats [COLAMD_INFO2] = Alen ; + DEBUG0 (("colamd: Need Alen >= %d, given only Alen = %d\n", need,Alen)); + return (FALSE) ; + } + + Alen -= Col_size + Row_size ; + Col = (Colamd_Col *) &A [Alen] ; + Row = (Colamd_Row *) &A [Alen + Col_size] ; + + /* === Construct the row and column data structures ===================== */ + + if (!init_rows_cols (n_row, n_col, Row, Col, A, p, stats)) + { + /* input matrix is invalid */ + DEBUG0 (("colamd: Matrix invalid\n")) ; + return (FALSE) ; + } + + /* === Initialize scores, kill dense rows/columns ======================= */ + + init_scoring (n_row, n_col, Row, Col, A, p, knobs, + &n_row2, &n_col2, &max_deg) ; + + /* === Order the supercolumns =========================================== */ + + ngarbage = find_ordering (n_row, n_col, Alen, Row, Col, A, p, + n_col2, max_deg, 2*nnz, aggressive) ; + + /* === Order the non-principal columns ================================== */ + + order_children (n_col, Col, p) ; + + /* === Return statistics in stats ======================================= */ + + stats [COLAMD_DENSE_ROW] = n_row - n_row2 ; + stats [COLAMD_DENSE_COL] = n_col - n_col2 ; + stats [COLAMD_DEFRAG_COUNT] = ngarbage ; + DEBUG0 (("colamd: done.\n")) ; + return (TRUE) ; +} + + +/* ========================================================================== */ +/* === colamd_report ======================================================== */ +/* ========================================================================== */ + +PUBLIC void COLAMD_report +( + Int stats [COLAMD_STATS] +) +{ + print_report ("colamd", stats) ; +} + + +/* ========================================================================== */ +/* === symamd_report ======================================================== */ +/* ========================================================================== */ + +PUBLIC void SYMAMD_report +( + Int stats [COLAMD_STATS] +) +{ + print_report ("symamd", stats) ; +} + + + +/* ========================================================================== */ +/* === NON-USER-CALLABLE ROUTINES: ========================================== */ +/* ========================================================================== */ + +/* There are no user-callable routines beyond this point in the file */ + + +/* ========================================================================== */ +/* === init_rows_cols ======================================================= */ +/* ========================================================================== */ + +/* + Takes the column form of the matrix in A and creates the row form of the + matrix. Also, row and column attributes are stored in the Col and Row + structs. If the columns are un-sorted or contain duplicate row indices, + this routine will also sort and remove duplicate row indices from the + column form of the matrix. Returns FALSE if the matrix is invalid, + TRUE otherwise. Not user-callable. +*/ + +PRIVATE Int init_rows_cols /* returns TRUE if OK, or FALSE otherwise */ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* row indices of A, of size Alen */ + Int p [], /* pointers to columns in A, of size n_col+1 */ + Int stats [COLAMD_STATS] /* colamd statistics */ +) +{ + /* === Local variables ================================================== */ + + Int col ; /* a column index */ + Int row ; /* a row index */ + Int *cp ; /* a column pointer */ + Int *cp_end ; /* a pointer to the end of a column */ + Int *rp ; /* a row pointer */ + Int *rp_end ; /* a pointer to the end of a row */ + Int last_row ; /* previous row */ + + /* === Initialize columns, and check column pointers ==================== */ + + for (col = 0 ; col < n_col ; col++) + { + Col [col].start = p [col] ; + Col [col].length = p [col+1] - p [col] ; + + if (Col [col].length < 0) + { + /* column pointers must be non-decreasing */ + stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = Col [col].length ; + DEBUG0 (("colamd: col %d length %d < 0\n", col, Col [col].length)) ; + return (FALSE) ; + } + + Col [col].shared1.thickness = 1 ; + Col [col].shared2.score = 0 ; + Col [col].shared3.prev = EMPTY ; + Col [col].shared4.degree_next = EMPTY ; + } + + /* p [0..n_col] no longer needed, used as "head" in subsequent routines */ + + /* === Scan columns, compute row degrees, and check row indices ========= */ + + stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/ + + for (row = 0 ; row < n_row ; row++) + { + Row [row].length = 0 ; + Row [row].shared2.mark = -1 ; + } + + for (col = 0 ; col < n_col ; col++) + { + last_row = -1 ; + + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + + while (cp < cp_end) + { + row = *cp++ ; + + /* make sure row indices within range */ + if (row < 0 || row >= n_row) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = row ; + stats [COLAMD_INFO3] = n_row ; + DEBUG0 (("colamd: row %d col %d out of bounds\n", row, col)) ; + return (FALSE) ; + } + + if (row <= last_row || Row [row].shared2.mark == col) + { + /* row index are unsorted or repeated (or both), thus col */ + /* is jumbled. This is a notice, not an error condition. */ + stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = row ; + (stats [COLAMD_INFO3]) ++ ; + DEBUG1 (("colamd: row %d col %d unsorted/duplicate\n",row,col)); + } + + if (Row [row].shared2.mark != col) + { + Row [row].length++ ; + } + else + { + /* this is a repeated entry in the column, */ + /* it will be removed */ + Col [col].length-- ; + } + + /* mark the row as having been seen in this column */ + Row [row].shared2.mark = col ; + + last_row = row ; + } + } + + /* === Compute row pointers ============================================= */ + + /* row form of the matrix starts directly after the column */ + /* form of matrix in A */ + Row [0].start = p [n_col] ; + Row [0].shared1.p = Row [0].start ; + Row [0].shared2.mark = -1 ; + for (row = 1 ; row < n_row ; row++) + { + Row [row].start = Row [row-1].start + Row [row-1].length ; + Row [row].shared1.p = Row [row].start ; + Row [row].shared2.mark = -1 ; + } + + /* === Create row form ================================================== */ + + if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED) + { + /* if cols jumbled, watch for repeated row indices */ + for (col = 0 ; col < n_col ; col++) + { + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + while (cp < cp_end) + { + row = *cp++ ; + if (Row [row].shared2.mark != col) + { + A [(Row [row].shared1.p)++] = col ; + Row [row].shared2.mark = col ; + } + } + } + } + else + { + /* if cols not jumbled, we don't need the mark (this is faster) */ + for (col = 0 ; col < n_col ; col++) + { + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + while (cp < cp_end) + { + A [(Row [*cp++].shared1.p)++] = col ; + } + } + } + + /* === Clear the row marks and set row degrees ========================== */ + + for (row = 0 ; row < n_row ; row++) + { + Row [row].shared2.mark = 0 ; + Row [row].shared1.degree = Row [row].length ; + } + + /* === See if we need to re-create columns ============================== */ + + if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED) + { + DEBUG0 (("colamd: reconstructing column form, matrix jumbled\n")) ; + +#ifndef NDEBUG + /* make sure column lengths are correct */ + for (col = 0 ; col < n_col ; col++) + { + p [col] = Col [col].length ; + } + for (row = 0 ; row < n_row ; row++) + { + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) + { + p [*rp++]-- ; + } + } + for (col = 0 ; col < n_col ; col++) + { + ASSERT (p [col] == 0) ; + } + /* now p is all zero (different than when debugging is turned off) */ +#endif /* NDEBUG */ + + /* === Compute col pointers ========================================= */ + + /* col form of the matrix starts at A [0]. */ + /* Note, we may have a gap between the col form and the row */ + /* form if there were duplicate entries, if so, it will be */ + /* removed upon the first garbage collection */ + Col [0].start = 0 ; + p [0] = Col [0].start ; + for (col = 1 ; col < n_col ; col++) + { + /* note that the lengths here are for pruned columns, i.e. */ + /* no duplicate row indices will exist for these columns */ + Col [col].start = Col [col-1].start + Col [col-1].length ; + p [col] = Col [col].start ; + } + + /* === Re-create col form =========================================== */ + + for (row = 0 ; row < n_row ; row++) + { + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) + { + A [(p [*rp++])++] = row ; + } + } + } + + /* === Done. Matrix is not (or no longer) jumbled ====================== */ + + return (TRUE) ; +} + + +/* ========================================================================== */ +/* === init_scoring ========================================================= */ +/* ========================================================================== */ + +/* + Kills dense or empty columns and rows, calculates an initial score for + each column, and places all columns in the degree lists. Not user-callable. +*/ + +PRIVATE void init_scoring +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* column form and row form of A */ + Int head [], /* of size n_col+1 */ + double knobs [COLAMD_KNOBS],/* parameters */ + Int *p_n_row2, /* number of non-dense, non-empty rows */ + Int *p_n_col2, /* number of non-dense, non-empty columns */ + Int *p_max_deg /* maximum row degree */ +) +{ + /* === Local variables ================================================== */ + + Int c ; /* a column index */ + Int r, row ; /* a row index */ + Int *cp ; /* a column pointer */ + Int deg ; /* degree of a row or column */ + Int *cp_end ; /* a pointer to the end of a column */ + Int *new_cp ; /* new column pointer */ + Int col_length ; /* length of pruned column */ + Int score ; /* current column score */ + Int n_col2 ; /* number of non-dense, non-empty columns */ + Int n_row2 ; /* number of non-dense, non-empty rows */ + Int dense_row_count ; /* remove rows with more entries than this */ + Int dense_col_count ; /* remove cols with more entries than this */ + Int min_score ; /* smallest column score */ + Int max_deg ; /* maximum row degree */ + Int next_col ; /* Used to add to degree list.*/ + +#ifndef NDEBUG + Int debug_count ; /* debug only. */ +#endif /* NDEBUG */ + + /* === Extract knobs ==================================================== */ + + /* Note: if knobs contains a NaN, this is undefined: */ + if (knobs [COLAMD_DENSE_ROW] < 0) + { + /* only remove completely dense rows */ + dense_row_count = n_col-1 ; + } + else + { + dense_row_count = DENSE_DEGREE (knobs [COLAMD_DENSE_ROW], n_col) ; + } + if (knobs [COLAMD_DENSE_COL] < 0) + { + /* only remove completely dense columns */ + dense_col_count = n_row-1 ; + } + else + { + dense_col_count = + DENSE_DEGREE (knobs [COLAMD_DENSE_COL], MIN (n_row, n_col)) ; + } + + DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ; + max_deg = 0 ; + n_col2 = n_col ; + n_row2 = n_row ; + + /* === Kill empty columns =============================================== */ + + /* Put the empty columns at the end in their natural order, so that LU */ + /* factorization can proceed as far as possible. */ + for (c = n_col-1 ; c >= 0 ; c--) + { + deg = Col [c].length ; + if (deg == 0) + { + /* this is a empty column, kill and order it last */ + Col [c].shared2.order = --n_col2 ; + KILL_PRINCIPAL_COL (c) ; + } + } + DEBUG1 (("colamd: null columns killed: %d\n", n_col - n_col2)) ; + + /* === Kill dense columns =============================================== */ + + /* Put the dense columns at the end, in their natural order */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* skip any dead columns */ + if (COL_IS_DEAD (c)) + { + continue ; + } + deg = Col [c].length ; + if (deg > dense_col_count) + { + /* this is a dense column, kill and order it last */ + Col [c].shared2.order = --n_col2 ; + /* decrement the row degrees */ + cp = &A [Col [c].start] ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + Row [*cp++].shared1.degree-- ; + } + KILL_PRINCIPAL_COL (c) ; + } + } + DEBUG1 (("colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ; + + /* === Kill dense and empty rows ======================================== */ + + for (r = 0 ; r < n_row ; r++) + { + deg = Row [r].shared1.degree ; + ASSERT (deg >= 0 && deg <= n_col) ; + if (deg > dense_row_count || deg == 0) + { + /* kill a dense or empty row */ + KILL_ROW (r) ; + --n_row2 ; + } + else + { + /* keep track of max degree of remaining rows */ + max_deg = MAX (max_deg, deg) ; + } + } + DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ; + + /* === Compute initial column scores ==================================== */ + + /* At this point the row degrees are accurate. They reflect the number */ + /* of "live" (non-dense) columns in each row. No empty rows exist. */ + /* Some "live" columns may contain only dead rows, however. These are */ + /* pruned in the code below. */ + + /* now find the initial matlab score for each column */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* skip dead column */ + if (COL_IS_DEAD (c)) + { + continue ; + } + score = 0 ; + cp = &A [Col [c].start] ; + new_cp = cp ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + /* skip if dead */ + if (ROW_IS_DEAD (row)) + { + continue ; + } + /* compact the column */ + *new_cp++ = row ; + /* add row's external degree */ + score += Row [row].shared1.degree - 1 ; + /* guard against integer overflow */ + score = MIN (score, n_col) ; + } + /* determine pruned column length */ + col_length = (Int) (new_cp - &A [Col [c].start]) ; + if (col_length == 0) + { + /* a newly-made null column (all rows in this col are "dense" */ + /* and have already been killed) */ + DEBUG2 (("Newly null killed: %d\n", c)) ; + Col [c].shared2.order = --n_col2 ; + KILL_PRINCIPAL_COL (c) ; + } + else + { + /* set column length and set score */ + ASSERT (score >= 0) ; + ASSERT (score <= n_col) ; + Col [c].length = col_length ; + Col [c].shared2.score = score ; + } + } + DEBUG1 (("colamd: Dense, null, and newly-null columns killed: %d\n", + n_col-n_col2)) ; + + /* At this point, all empty rows and columns are dead. All live columns */ + /* are "clean" (containing no dead rows) and simplicial (no supercolumns */ + /* yet). Rows may contain dead columns, but all live rows contain at */ + /* least one live column. */ + +#ifndef NDEBUG + debug_structures (n_row, n_col, Row, Col, A, n_col2) ; +#endif /* NDEBUG */ + + /* === Initialize degree lists ========================================== */ + +#ifndef NDEBUG + debug_count = 0 ; +#endif /* NDEBUG */ + + /* clear the hash buckets */ + for (c = 0 ; c <= n_col ; c++) + { + head [c] = EMPTY ; + } + min_score = n_col ; + /* place in reverse order, so low column indices are at the front */ + /* of the lists. This is to encourage natural tie-breaking */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* only add principal columns to degree lists */ + if (COL_IS_ALIVE (c)) + { + DEBUG4 (("place %d score %d minscore %d ncol %d\n", + c, Col [c].shared2.score, min_score, n_col)) ; + + /* === Add columns score to DList =============================== */ + + score = Col [c].shared2.score ; + + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (score >= 0) ; + ASSERT (score <= n_col) ; + ASSERT (head [score] >= EMPTY) ; + + /* now add this column to dList at proper score location */ + next_col = head [score] ; + Col [c].shared3.prev = EMPTY ; + Col [c].shared4.degree_next = next_col ; + + /* if there already was a column with the same score, set its */ + /* previous pointer to this new column */ + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = c ; + } + head [score] = c ; + + /* see if this score is less than current min */ + min_score = MIN (min_score, score) ; + +#ifndef NDEBUG + debug_count++ ; +#endif /* NDEBUG */ + + } + } + +#ifndef NDEBUG + DEBUG1 (("colamd: Live cols %d out of %d, non-princ: %d\n", + debug_count, n_col, n_col-debug_count)) ; + ASSERT (debug_count == n_col2) ; + debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2, max_deg) ; +#endif /* NDEBUG */ + + /* === Return number of remaining columns, and max row degree =========== */ + + *p_n_col2 = n_col2 ; + *p_n_row2 = n_row2 ; + *p_max_deg = max_deg ; +} + + +/* ========================================================================== */ +/* === find_ordering ======================================================== */ +/* ========================================================================== */ + +/* + Order the principal columns of the supercolumn form of the matrix + (no supercolumns on input). Uses a minimum approximate column minimum + degree ordering method. Not user-callable. +*/ + +PRIVATE Int find_ordering /* return the number of garbage collections */ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Int Alen, /* size of A, 2*nnz + n_col or larger */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* column form and row form of A */ + Int head [], /* of size n_col+1 */ + Int n_col2, /* Remaining columns to order */ + Int max_deg, /* Maximum row degree */ + Int pfree, /* index of first free slot (2*nnz on entry) */ + Int aggressive +) +{ + /* === Local variables ================================================== */ + + Int k ; /* current pivot ordering step */ + Int pivot_col ; /* current pivot column */ + Int *cp ; /* a column pointer */ + Int *rp ; /* a row pointer */ + Int pivot_row ; /* current pivot row */ + Int *new_cp ; /* modified column pointer */ + Int *new_rp ; /* modified row pointer */ + Int pivot_row_start ; /* pointer to start of pivot row */ + Int pivot_row_degree ; /* number of columns in pivot row */ + Int pivot_row_length ; /* number of supercolumns in pivot row */ + Int pivot_col_score ; /* score of pivot column */ + Int needed_memory ; /* free space needed for pivot row */ + Int *cp_end ; /* pointer to the end of a column */ + Int *rp_end ; /* pointer to the end of a row */ + Int row ; /* a row index */ + Int col ; /* a column index */ + Int max_score ; /* maximum possible score */ + Int cur_score ; /* score of current column */ + unsigned Int hash ; /* hash value for supernode detection */ + Int head_column ; /* head of hash bucket */ + Int first_col ; /* first column in hash bucket */ + Int tag_mark ; /* marker value for mark array */ + Int row_mark ; /* Row [row].shared2.mark */ + Int set_difference ; /* set difference size of row with pivot row */ + Int min_score ; /* smallest column score */ + Int col_thickness ; /* "thickness" (no. of columns in a supercol) */ + Int max_mark ; /* maximum value of tag_mark */ + Int pivot_col_thickness ; /* number of columns represented by pivot col */ + Int prev_col ; /* Used by Dlist operations. */ + Int next_col ; /* Used by Dlist operations. */ + Int ngarbage ; /* number of garbage collections performed */ + +#ifndef NDEBUG + Int debug_d ; /* debug loop counter */ + Int debug_step = 0 ; /* debug loop counter */ +#endif /* NDEBUG */ + + /* === Initialization and clear mark ==================================== */ + + max_mark = INT_MAX - n_col ; /* INT_MAX defined in <limits.h> */ + tag_mark = clear_mark (0, max_mark, n_row, Row) ; + min_score = 0 ; + ngarbage = 0 ; + DEBUG1 (("colamd: Ordering, n_col2=%d\n", n_col2)) ; + + /* === Order the columns ================================================ */ + + for (k = 0 ; k < n_col2 ; /* 'k' is incremented below */) + { + +#ifndef NDEBUG + if (debug_step % 100 == 0) + { + DEBUG2 (("\n... Step k: %d out of n_col2: %d\n", k, n_col2)) ; + } + else + { + DEBUG3 (("\n----------Step k: %d out of n_col2: %d\n", k, n_col2)) ; + } + debug_step++ ; + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k, max_deg) ; + debug_matrix (n_row, n_col, Row, Col, A) ; +#endif /* NDEBUG */ + + /* === Select pivot column, and order it ============================ */ + + /* make sure degree list isn't empty */ + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (head [min_score] >= EMPTY) ; + +#ifndef NDEBUG + for (debug_d = 0 ; debug_d < min_score ; debug_d++) + { + ASSERT (head [debug_d] == EMPTY) ; + } +#endif /* NDEBUG */ + + /* get pivot column from head of minimum degree list */ + while (head [min_score] == EMPTY && min_score < n_col) + { + min_score++ ; + } + pivot_col = head [min_score] ; + ASSERT (pivot_col >= 0 && pivot_col <= n_col) ; + next_col = Col [pivot_col].shared4.degree_next ; + head [min_score] = next_col ; + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = EMPTY ; + } + + ASSERT (COL_IS_ALIVE (pivot_col)) ; + + /* remember score for defrag check */ + pivot_col_score = Col [pivot_col].shared2.score ; + + /* the pivot column is the kth column in the pivot order */ + Col [pivot_col].shared2.order = k ; + + /* increment order count by column thickness */ + pivot_col_thickness = Col [pivot_col].shared1.thickness ; + k += pivot_col_thickness ; + ASSERT (pivot_col_thickness > 0) ; + DEBUG3 (("Pivot col: %d thick %d\n", pivot_col, pivot_col_thickness)) ; + + /* === Garbage_collection, if necessary ============================= */ + + needed_memory = MIN (pivot_col_score, n_col - k) ; + if (pfree + needed_memory >= Alen) + { + pfree = garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ; + ngarbage++ ; + /* after garbage collection we will have enough */ + ASSERT (pfree + needed_memory < Alen) ; + /* garbage collection has wiped out the Row[].shared2.mark array */ + tag_mark = clear_mark (0, max_mark, n_row, Row) ; + +#ifndef NDEBUG + debug_matrix (n_row, n_col, Row, Col, A) ; +#endif /* NDEBUG */ + } + + /* === Compute pivot row pattern ==================================== */ + + /* get starting location for this new merged row */ + pivot_row_start = pfree ; + + /* initialize new row counts to zero */ + pivot_row_degree = 0 ; + + /* tag pivot column as having been visited so it isn't included */ + /* in merged pivot row */ + Col [pivot_col].shared1.thickness = -pivot_col_thickness ; + + /* pivot row is the union of all rows in the pivot column pattern */ + cp = &A [Col [pivot_col].start] ; + cp_end = cp + Col [pivot_col].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + DEBUG4 (("Pivot col pattern %d %d\n", ROW_IS_ALIVE (row), row)) ; + /* skip if row is dead */ + if (ROW_IS_ALIVE (row)) + { + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) + { + /* get a column */ + col = *rp++ ; + /* add the column, if alive and untagged */ + col_thickness = Col [col].shared1.thickness ; + if (col_thickness > 0 && COL_IS_ALIVE (col)) + { + /* tag column in pivot row */ + Col [col].shared1.thickness = -col_thickness ; + ASSERT (pfree < Alen) ; + /* place column in pivot row */ + A [pfree++] = col ; + pivot_row_degree += col_thickness ; + } + } + } + } + + /* clear tag on pivot column */ + Col [pivot_col].shared1.thickness = pivot_col_thickness ; + max_deg = MAX (max_deg, pivot_row_degree) ; + +#ifndef NDEBUG + DEBUG3 (("check2\n")) ; + debug_mark (n_row, Row, tag_mark, max_mark) ; +#endif /* NDEBUG */ + + /* === Kill all rows used to construct pivot row ==================== */ + + /* also kill pivot row, temporarily */ + cp = &A [Col [pivot_col].start] ; + cp_end = cp + Col [pivot_col].length ; + while (cp < cp_end) + { + /* may be killing an already dead row */ + row = *cp++ ; + DEBUG3 (("Kill row in pivot col: %d\n", row)) ; + KILL_ROW (row) ; + } + + /* === Select a row index to use as the new pivot row =============== */ + + pivot_row_length = pfree - pivot_row_start ; + if (pivot_row_length > 0) + { + /* pick the "pivot" row arbitrarily (first row in col) */ + pivot_row = A [Col [pivot_col].start] ; + DEBUG3 (("Pivotal row is %d\n", pivot_row)) ; + } + else + { + /* there is no pivot row, since it is of zero length */ + pivot_row = EMPTY ; + ASSERT (pivot_row_length == 0) ; + } + ASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ; + + /* === Approximate degree computation =============================== */ + + /* Here begins the computation of the approximate degree. The column */ + /* score is the sum of the pivot row "length", plus the size of the */ + /* set differences of each row in the column minus the pattern of the */ + /* pivot row itself. The column ("thickness") itself is also */ + /* excluded from the column score (we thus use an approximate */ + /* external degree). */ + + /* The time taken by the following code (compute set differences, and */ + /* add them up) is proportional to the size of the data structure */ + /* being scanned - that is, the sum of the sizes of each column in */ + /* the pivot row. Thus, the amortized time to compute a column score */ + /* is proportional to the size of that column (where size, in this */ + /* context, is the column "length", or the number of row indices */ + /* in that column). The number of row indices in a column is */ + /* monotonically non-decreasing, from the length of the original */ + /* column on input to colamd. */ + + /* === Compute set differences ====================================== */ + + DEBUG3 (("** Computing set differences phase. **\n")) ; + + /* pivot row is currently dead - it will be revived later. */ + + DEBUG3 (("Pivot row: ")) ; + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + col = *rp++ ; + ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ; + DEBUG3 (("Col: %d\n", col)) ; + + /* clear tags used to construct pivot row pattern */ + col_thickness = -Col [col].shared1.thickness ; + ASSERT (col_thickness > 0) ; + Col [col].shared1.thickness = col_thickness ; + + /* === Remove column from degree list =========================== */ + + cur_score = Col [col].shared2.score ; + prev_col = Col [col].shared3.prev ; + next_col = Col [col].shared4.degree_next ; + ASSERT (cur_score >= 0) ; + ASSERT (cur_score <= n_col) ; + ASSERT (cur_score >= EMPTY) ; + if (prev_col == EMPTY) + { + head [cur_score] = next_col ; + } + else + { + Col [prev_col].shared4.degree_next = next_col ; + } + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = prev_col ; + } + + /* === Scan the column ========================================== */ + + cp = &A [Col [col].start] ; + cp_end = cp + Col [col].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + row_mark = Row [row].shared2.mark ; + /* skip if dead */ + if (ROW_IS_MARKED_DEAD (row_mark)) + { + continue ; + } + ASSERT (row != pivot_row) ; + set_difference = row_mark - tag_mark ; + /* check if the row has been seen yet */ + if (set_difference < 0) + { + ASSERT (Row [row].shared1.degree <= max_deg) ; + set_difference = Row [row].shared1.degree ; + } + /* subtract column thickness from this row's set difference */ + set_difference -= col_thickness ; + ASSERT (set_difference >= 0) ; + /* absorb this row if the set difference becomes zero */ + if (set_difference == 0 && aggressive) + { + DEBUG3 (("aggressive absorption. Row: %d\n", row)) ; + KILL_ROW (row) ; + } + else + { + /* save the new mark */ + Row [row].shared2.mark = set_difference + tag_mark ; + } + } + } + +#ifndef NDEBUG + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k-pivot_row_degree, max_deg) ; +#endif /* NDEBUG */ + + /* === Add up set differences for each column ======================= */ + + DEBUG3 (("** Adding set differences phase. **\n")) ; + + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + /* get a column */ + col = *rp++ ; + ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ; + hash = 0 ; + cur_score = 0 ; + cp = &A [Col [col].start] ; + /* compact the column */ + new_cp = cp ; + cp_end = cp + Col [col].length ; + + DEBUG4 (("Adding set diffs for Col: %d.\n", col)) ; + + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + ASSERT(row >= 0 && row < n_row) ; + row_mark = Row [row].shared2.mark ; + /* skip if dead */ + if (ROW_IS_MARKED_DEAD (row_mark)) + { + DEBUG4 ((" Row %d, dead\n", row)) ; + continue ; + } + DEBUG4 ((" Row %d, set diff %d\n", row, row_mark-tag_mark)); + ASSERT (row_mark >= tag_mark) ; + /* compact the column */ + *new_cp++ = row ; + /* compute hash function */ + hash += row ; + /* add set difference */ + cur_score += row_mark - tag_mark ; + /* integer overflow... */ + cur_score = MIN (cur_score, n_col) ; + } + + /* recompute the column's length */ + Col [col].length = (Int) (new_cp - &A [Col [col].start]) ; + + /* === Further mass elimination ================================= */ + + if (Col [col].length == 0) + { + DEBUG4 (("further mass elimination. Col: %d\n", col)) ; + /* nothing left but the pivot row in this column */ + KILL_PRINCIPAL_COL (col) ; + pivot_row_degree -= Col [col].shared1.thickness ; + ASSERT (pivot_row_degree >= 0) ; + /* order it */ + Col [col].shared2.order = k ; + /* increment order count by column thickness */ + k += Col [col].shared1.thickness ; + } + else + { + /* === Prepare for supercolumn detection ==================== */ + + DEBUG4 (("Preparing supercol detection for Col: %d.\n", col)) ; + + /* save score so far */ + Col [col].shared2.score = cur_score ; + + /* add column to hash table, for supercolumn detection */ + hash %= n_col + 1 ; + + DEBUG4 ((" Hash = %d, n_col = %d.\n", hash, n_col)) ; + ASSERT (((Int) hash) <= n_col) ; + + head_column = head [hash] ; + if (head_column > EMPTY) + { + /* degree list "hash" is non-empty, use prev (shared3) of */ + /* first column in degree list as head of hash bucket */ + first_col = Col [head_column].shared3.headhash ; + Col [head_column].shared3.headhash = col ; + } + else + { + /* degree list "hash" is empty, use head as hash bucket */ + first_col = - (head_column + 2) ; + head [hash] = - (col + 2) ; + } + Col [col].shared4.hash_next = first_col ; + + /* save hash function in Col [col].shared3.hash */ + Col [col].shared3.hash = (Int) hash ; + ASSERT (COL_IS_ALIVE (col)) ; + } + } + + /* The approximate external column degree is now computed. */ + + /* === Supercolumn detection ======================================== */ + + DEBUG3 (("** Supercolumn detection phase. **\n")) ; + + detect_super_cols ( + +#ifndef NDEBUG + n_col, Row, +#endif /* NDEBUG */ + + Col, A, head, pivot_row_start, pivot_row_length) ; + + /* === Kill the pivotal column ====================================== */ + + KILL_PRINCIPAL_COL (pivot_col) ; + + /* === Clear mark =================================================== */ + + tag_mark = clear_mark (tag_mark+max_deg+1, max_mark, n_row, Row) ; + +#ifndef NDEBUG + DEBUG3 (("check3\n")) ; + debug_mark (n_row, Row, tag_mark, max_mark) ; +#endif /* NDEBUG */ + + /* === Finalize the new pivot row, and column scores ================ */ + + DEBUG3 (("** Finalize scores phase. **\n")) ; + + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + /* compact the pivot row */ + new_rp = rp ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + col = *rp++ ; + /* skip dead columns */ + if (COL_IS_DEAD (col)) + { + continue ; + } + *new_rp++ = col ; + /* add new pivot row to column */ + A [Col [col].start + (Col [col].length++)] = pivot_row ; + + /* retrieve score so far and add on pivot row's degree. */ + /* (we wait until here for this in case the pivot */ + /* row's degree was reduced due to mass elimination). */ + cur_score = Col [col].shared2.score + pivot_row_degree ; + + /* calculate the max possible score as the number of */ + /* external columns minus the 'k' value minus the */ + /* columns thickness */ + max_score = n_col - k - Col [col].shared1.thickness ; + + /* make the score the external degree of the union-of-rows */ + cur_score -= Col [col].shared1.thickness ; + + /* make sure score is less or equal than the max score */ + cur_score = MIN (cur_score, max_score) ; + ASSERT (cur_score >= 0) ; + + /* store updated score */ + Col [col].shared2.score = cur_score ; + + /* === Place column back in degree list ========================= */ + + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (cur_score >= 0) ; + ASSERT (cur_score <= n_col) ; + ASSERT (head [cur_score] >= EMPTY) ; + next_col = head [cur_score] ; + Col [col].shared4.degree_next = next_col ; + Col [col].shared3.prev = EMPTY ; + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = col ; + } + head [cur_score] = col ; + + /* see if this score is less than current min */ + min_score = MIN (min_score, cur_score) ; + + } + +#ifndef NDEBUG + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k, max_deg) ; +#endif /* NDEBUG */ + + /* === Resurrect the new pivot row ================================== */ + + if (pivot_row_degree > 0) + { + /* update pivot row length to reflect any cols that were killed */ + /* during super-col detection and mass elimination */ + Row [pivot_row].start = pivot_row_start ; + Row [pivot_row].length = (Int) (new_rp - &A[pivot_row_start]) ; + ASSERT (Row [pivot_row].length > 0) ; + Row [pivot_row].shared1.degree = pivot_row_degree ; + Row [pivot_row].shared2.mark = 0 ; + /* pivot row is no longer dead */ + + DEBUG1 (("Resurrect Pivot_row %d deg: %d\n", + pivot_row, pivot_row_degree)) ; + } + } + + /* === All principal columns have now been ordered ====================== */ + + return (ngarbage) ; +} + + +/* ========================================================================== */ +/* === order_children ======================================================= */ +/* ========================================================================== */ + +/* + The find_ordering routine has ordered all of the principal columns (the + representatives of the supercolumns). The non-principal columns have not + yet been ordered. This routine orders those columns by walking up the + parent tree (a column is a child of the column which absorbed it). The + final permutation vector is then placed in p [0 ... n_col-1], with p [0] + being the first column, and p [n_col-1] being the last. It doesn't look + like it at first glance, but be assured that this routine takes time linear + in the number of columns. Although not immediately obvious, the time + taken by this routine is O (n_col), that is, linear in the number of + columns. Not user-callable. +*/ + +PRIVATE void order_children +( + /* === Parameters ======================================================= */ + + Int n_col, /* number of columns of A */ + Colamd_Col Col [], /* of size n_col+1 */ + Int p [] /* p [0 ... n_col-1] is the column permutation*/ +) +{ + /* === Local variables ================================================== */ + + Int i ; /* loop counter for all columns */ + Int c ; /* column index */ + Int parent ; /* index of column's parent */ + Int order ; /* column's order */ + + /* === Order each non-principal column ================================== */ + + for (i = 0 ; i < n_col ; i++) + { + /* find an un-ordered non-principal column */ + ASSERT (COL_IS_DEAD (i)) ; + if (!COL_IS_DEAD_PRINCIPAL (i) && Col [i].shared2.order == EMPTY) + { + parent = i ; + /* once found, find its principal parent */ + do + { + parent = Col [parent].shared1.parent ; + } while (!COL_IS_DEAD_PRINCIPAL (parent)) ; + + /* now, order all un-ordered non-principal columns along path */ + /* to this parent. collapse tree at the same time */ + c = i ; + /* get order of parent */ + order = Col [parent].shared2.order ; + + do + { + ASSERT (Col [c].shared2.order == EMPTY) ; + + /* order this column */ + Col [c].shared2.order = order++ ; + /* collaps tree */ + Col [c].shared1.parent = parent ; + + /* get immediate parent of this column */ + c = Col [c].shared1.parent ; + + /* continue until we hit an ordered column. There are */ + /* guarranteed not to be anymore unordered columns */ + /* above an ordered column */ + } while (Col [c].shared2.order == EMPTY) ; + + /* re-order the super_col parent to largest order for this group */ + Col [parent].shared2.order = order ; + } + } + + /* === Generate the permutation ========================================= */ + + for (c = 0 ; c < n_col ; c++) + { + p [Col [c].shared2.order] = c ; + } +} + + +/* ========================================================================== */ +/* === detect_super_cols ==================================================== */ +/* ========================================================================== */ + +/* + Detects supercolumns by finding matches between columns in the hash buckets. + Check amongst columns in the set A [row_start ... row_start + row_length-1]. + The columns under consideration are currently *not* in the degree lists, + and have already been placed in the hash buckets. + + The hash bucket for columns whose hash function is equal to h is stored + as follows: + + if head [h] is >= 0, then head [h] contains a degree list, so: + + head [h] is the first column in degree bucket h. + Col [head [h]].headhash gives the first column in hash bucket h. + + otherwise, the degree list is empty, and: + + -(head [h] + 2) is the first column in hash bucket h. + + For a column c in a hash bucket, Col [c].shared3.prev is NOT a "previous + column" pointer. Col [c].shared3.hash is used instead as the hash number + for that column. The value of Col [c].shared4.hash_next is the next column + in the same hash bucket. + + Assuming no, or "few" hash collisions, the time taken by this routine is + linear in the sum of the sizes (lengths) of each column whose score has + just been computed in the approximate degree computation. + Not user-callable. +*/ + +PRIVATE void detect_super_cols +( + /* === Parameters ======================================================= */ + +#ifndef NDEBUG + /* these two parameters are only needed when debugging is enabled: */ + Int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ +#endif /* NDEBUG */ + + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* row indices of A */ + Int head [], /* head of degree lists and hash buckets */ + Int row_start, /* pointer to set of columns to check */ + Int row_length /* number of columns to check */ +) +{ + /* === Local variables ================================================== */ + + Int hash ; /* hash value for a column */ + Int *rp ; /* pointer to a row */ + Int c ; /* a column index */ + Int super_c ; /* column index of the column to absorb into */ + Int *cp1 ; /* column pointer for column super_c */ + Int *cp2 ; /* column pointer for column c */ + Int length ; /* length of column super_c */ + Int prev_c ; /* column preceding c in hash bucket */ + Int i ; /* loop counter */ + Int *rp_end ; /* pointer to the end of the row */ + Int col ; /* a column index in the row to check */ + Int head_column ; /* first column in hash bucket or degree list */ + Int first_col ; /* first column in hash bucket */ + + /* === Consider each column in the row ================================== */ + + rp = &A [row_start] ; + rp_end = rp + row_length ; + while (rp < rp_end) + { + col = *rp++ ; + if (COL_IS_DEAD (col)) + { + continue ; + } + + /* get hash number for this column */ + hash = Col [col].shared3.hash ; + ASSERT (hash <= n_col) ; + + /* === Get the first column in this hash bucket ===================== */ + + head_column = head [hash] ; + if (head_column > EMPTY) + { + first_col = Col [head_column].shared3.headhash ; + } + else + { + first_col = - (head_column + 2) ; + } + + /* === Consider each column in the hash bucket ====================== */ + + for (super_c = first_col ; super_c != EMPTY ; + super_c = Col [super_c].shared4.hash_next) + { + ASSERT (COL_IS_ALIVE (super_c)) ; + ASSERT (Col [super_c].shared3.hash == hash) ; + length = Col [super_c].length ; + + /* prev_c is the column preceding column c in the hash bucket */ + prev_c = super_c ; + + /* === Compare super_c with all columns after it ================ */ + + for (c = Col [super_c].shared4.hash_next ; + c != EMPTY ; c = Col [c].shared4.hash_next) + { + ASSERT (c != super_c) ; + ASSERT (COL_IS_ALIVE (c)) ; + ASSERT (Col [c].shared3.hash == hash) ; + + /* not identical if lengths or scores are different */ + if (Col [c].length != length || + Col [c].shared2.score != Col [super_c].shared2.score) + { + prev_c = c ; + continue ; + } + + /* compare the two columns */ + cp1 = &A [Col [super_c].start] ; + cp2 = &A [Col [c].start] ; + + for (i = 0 ; i < length ; i++) + { + /* the columns are "clean" (no dead rows) */ + ASSERT (ROW_IS_ALIVE (*cp1)) ; + ASSERT (ROW_IS_ALIVE (*cp2)) ; + /* row indices will same order for both supercols, */ + /* no gather scatter nessasary */ + if (*cp1++ != *cp2++) + { + break ; + } + } + + /* the two columns are different if the for-loop "broke" */ + if (i != length) + { + prev_c = c ; + continue ; + } + + /* === Got it! two columns are identical =================== */ + + ASSERT (Col [c].shared2.score == Col [super_c].shared2.score) ; + + Col [super_c].shared1.thickness += Col [c].shared1.thickness ; + Col [c].shared1.parent = super_c ; + KILL_NON_PRINCIPAL_COL (c) ; + /* order c later, in order_children() */ + Col [c].shared2.order = EMPTY ; + /* remove c from hash bucket */ + Col [prev_c].shared4.hash_next = Col [c].shared4.hash_next ; + } + } + + /* === Empty this hash bucket ======================================= */ + + if (head_column > EMPTY) + { + /* corresponding degree list "hash" is not empty */ + Col [head_column].shared3.headhash = EMPTY ; + } + else + { + /* corresponding degree list "hash" is empty */ + head [hash] = EMPTY ; + } + } +} + + +/* ========================================================================== */ +/* === garbage_collection =================================================== */ +/* ========================================================================== */ + +/* + Defragments and compacts columns and rows in the workspace A. Used when + all avaliable memory has been used while performing row merging. Returns + the index of the first free position in A, after garbage collection. The + time taken by this routine is linear is the size of the array A, which is + itself linear in the number of nonzeros in the input matrix. + Not user-callable. +*/ + +PRIVATE Int garbage_collection /* returns the new value of pfree */ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows */ + Int n_col, /* number of columns */ + Colamd_Row Row [], /* row info */ + Colamd_Col Col [], /* column info */ + Int A [], /* A [0 ... Alen-1] holds the matrix */ + Int *pfree /* &A [0] ... pfree is in use */ +) +{ + /* === Local variables ================================================== */ + + Int *psrc ; /* source pointer */ + Int *pdest ; /* destination pointer */ + Int j ; /* counter */ + Int r ; /* a row index */ + Int c ; /* a column index */ + Int length ; /* length of a row or column */ + +#ifndef NDEBUG + Int debug_rows ; + DEBUG2 (("Defrag..\n")) ; + for (psrc = &A[0] ; psrc < pfree ; psrc++) ASSERT (*psrc >= 0) ; + debug_rows = 0 ; +#endif /* NDEBUG */ + + /* === Defragment the columns =========================================== */ + + pdest = &A[0] ; + for (c = 0 ; c < n_col ; c++) + { + if (COL_IS_ALIVE (c)) + { + psrc = &A [Col [c].start] ; + + /* move and compact the column */ + ASSERT (pdest <= psrc) ; + Col [c].start = (Int) (pdest - &A [0]) ; + length = Col [c].length ; + for (j = 0 ; j < length ; j++) + { + r = *psrc++ ; + if (ROW_IS_ALIVE (r)) + { + *pdest++ = r ; + } + } + Col [c].length = (Int) (pdest - &A [Col [c].start]) ; + } + } + + /* === Prepare to defragment the rows =================================== */ + + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_DEAD (r) || (Row [r].length == 0)) + { + /* This row is already dead, or is of zero length. Cannot compact + * a row of zero length, so kill it. NOTE: in the current version, + * there are no zero-length live rows. Kill the row (for the first + * time, or again) just to be safe. */ + KILL_ROW (r) ; + } + else + { + /* save first column index in Row [r].shared2.first_column */ + psrc = &A [Row [r].start] ; + Row [r].shared2.first_column = *psrc ; + ASSERT (ROW_IS_ALIVE (r)) ; + /* flag the start of the row with the one's complement of row */ + *psrc = ONES_COMPLEMENT (r) ; +#ifndef NDEBUG + debug_rows++ ; +#endif /* NDEBUG */ + } + } + + /* === Defragment the rows ============================================== */ + + psrc = pdest ; + while (psrc < pfree) + { + /* find a negative number ... the start of a row */ + if (*psrc++ < 0) + { + psrc-- ; + /* get the row index */ + r = ONES_COMPLEMENT (*psrc) ; + ASSERT (r >= 0 && r < n_row) ; + /* restore first column index */ + *psrc = Row [r].shared2.first_column ; + ASSERT (ROW_IS_ALIVE (r)) ; + ASSERT (Row [r].length > 0) ; + /* move and compact the row */ + ASSERT (pdest <= psrc) ; + Row [r].start = (Int) (pdest - &A [0]) ; + length = Row [r].length ; + for (j = 0 ; j < length ; j++) + { + c = *psrc++ ; + if (COL_IS_ALIVE (c)) + { + *pdest++ = c ; + } + } + Row [r].length = (Int) (pdest - &A [Row [r].start]) ; + ASSERT (Row [r].length > 0) ; +#ifndef NDEBUG + debug_rows-- ; +#endif /* NDEBUG */ + } + } + /* ensure we found all the rows */ + ASSERT (debug_rows == 0) ; + + /* === Return the new value of pfree ==================================== */ + + return ((Int) (pdest - &A [0])) ; +} + + +/* ========================================================================== */ +/* === clear_mark =========================================================== */ +/* ========================================================================== */ + +/* + Clears the Row [].shared2.mark array, and returns the new tag_mark. + Return value is the new tag_mark. Not user-callable. +*/ + +PRIVATE Int clear_mark /* return the new value for tag_mark */ +( + /* === Parameters ======================================================= */ + + Int tag_mark, /* new value of tag_mark */ + Int max_mark, /* max allowed value of tag_mark */ + + Int n_row, /* number of rows in A */ + Colamd_Row Row [] /* Row [0 ... n_row-1].shared2.mark is set to zero */ +) +{ + /* === Local variables ================================================== */ + + Int r ; + + if (tag_mark <= 0 || tag_mark >= max_mark) + { + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_ALIVE (r)) + { + Row [r].shared2.mark = 0 ; + } + } + tag_mark = 1 ; + } + + return (tag_mark) ; +} + + +/* ========================================================================== */ +/* === print_report ========================================================= */ +/* ========================================================================== */ + +PRIVATE void print_report +( + char *method, + Int stats [COLAMD_STATS] +) +{ + + Int i1, i2, i3 ; + + PRINTF (("\n%s version %d.%d, %s: ", method, + COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE)) ; + + if (!stats) + { + PRINTF (("No statistics available.\n")) ; + return ; + } + + i1 = stats [COLAMD_INFO1] ; + i2 = stats [COLAMD_INFO2] ; + i3 = stats [COLAMD_INFO3] ; + + if (stats [COLAMD_STATUS] >= 0) + { + PRINTF (("OK. ")) ; + } + else + { + PRINTF (("ERROR. ")) ; + } + + switch (stats [COLAMD_STATUS]) + { + + case COLAMD_OK_BUT_JUMBLED: + + PRINTF(("Matrix has unsorted or duplicate row indices.\n")) ; + + PRINTF(("%s: number of duplicate or out-of-order row indices: %d\n", + method, i3)) ; + + PRINTF(("%s: last seen duplicate or out-of-order row index: %d\n", + method, INDEX (i2))) ; + + PRINTF(("%s: last seen in column: %d", + method, INDEX (i1))) ; + + /* no break - fall through to next case instead */ + + case COLAMD_OK: + + PRINTF(("\n")) ; + + PRINTF(("%s: number of dense or empty rows ignored: %d\n", + method, stats [COLAMD_DENSE_ROW])) ; + + PRINTF(("%s: number of dense or empty columns ignored: %d\n", + method, stats [COLAMD_DENSE_COL])) ; + + PRINTF(("%s: number of garbage collections performed: %d\n", + method, stats [COLAMD_DEFRAG_COUNT])) ; + break ; + + case COLAMD_ERROR_A_not_present: + + PRINTF(("Array A (row indices of matrix) not present.\n")) ; + break ; + + case COLAMD_ERROR_p_not_present: + + PRINTF(("Array p (column pointers for matrix) not present.\n")) ; + break ; + + case COLAMD_ERROR_nrow_negative: + + PRINTF(("Invalid number of rows (%d).\n", i1)) ; + break ; + + case COLAMD_ERROR_ncol_negative: + + PRINTF(("Invalid number of columns (%d).\n", i1)) ; + break ; + + case COLAMD_ERROR_nnz_negative: + + PRINTF(("Invalid number of nonzero entries (%d).\n", i1)) ; + break ; + + case COLAMD_ERROR_p0_nonzero: + + PRINTF(("Invalid column pointer, p [0] = %d, must be zero.\n", i1)); + break ; + + case COLAMD_ERROR_A_too_small: + + PRINTF(("Array A too small.\n")) ; + PRINTF((" Need Alen >= %d, but given only Alen = %d.\n", + i1, i2)) ; + break ; + + case COLAMD_ERROR_col_length_negative: + + PRINTF + (("Column %d has a negative number of nonzero entries (%d).\n", + INDEX (i1), i2)) ; + break ; + + case COLAMD_ERROR_row_index_out_of_bounds: + + PRINTF + (("Row index (row %d) out of bounds (%d to %d) in column %d.\n", + INDEX (i2), INDEX (0), INDEX (i3-1), INDEX (i1))) ; + break ; + + case COLAMD_ERROR_out_of_memory: + + PRINTF(("Out of memory.\n")) ; + break ; + + /* v2.4: internal-error case deleted */ + } +} + + + + +/* ========================================================================== */ +/* === colamd debugging routines ============================================ */ +/* ========================================================================== */ + +/* When debugging is disabled, the remainder of this file is ignored. */ + +#ifndef NDEBUG + + +/* ========================================================================== */ +/* === debug_structures ===================================================== */ +/* ========================================================================== */ + +/* + At this point, all empty rows and columns are dead. All live columns + are "clean" (containing no dead rows) and simplicial (no supercolumns + yet). Rows may contain dead columns, but all live rows contain at + least one live column. +*/ + +PRIVATE void debug_structures +( + /* === Parameters ======================================================= */ + + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int n_col2 +) +{ + /* === Local variables ================================================== */ + + Int i ; + Int c ; + Int *cp ; + Int *cp_end ; + Int len ; + Int score ; + Int r ; + Int *rp ; + Int *rp_end ; + Int deg ; + + /* === Check A, Row, and Col ============================================ */ + + for (c = 0 ; c < n_col ; c++) + { + if (COL_IS_ALIVE (c)) + { + len = Col [c].length ; + score = Col [c].shared2.score ; + DEBUG4 (("initial live col %5d %5d %5d\n", c, len, score)) ; + ASSERT (len > 0) ; + ASSERT (score >= 0) ; + ASSERT (Col [c].shared1.thickness == 1) ; + cp = &A [Col [c].start] ; + cp_end = cp + len ; + while (cp < cp_end) + { + r = *cp++ ; + ASSERT (ROW_IS_ALIVE (r)) ; + } + } + else + { + i = Col [c].shared2.order ; + ASSERT (i >= n_col2 && i < n_col) ; + } + } + + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_ALIVE (r)) + { + i = 0 ; + len = Row [r].length ; + deg = Row [r].shared1.degree ; + ASSERT (len > 0) ; + ASSERT (deg > 0) ; + rp = &A [Row [r].start] ; + rp_end = rp + len ; + while (rp < rp_end) + { + c = *rp++ ; + if (COL_IS_ALIVE (c)) + { + i++ ; + } + } + ASSERT (i > 0) ; + } + } +} + + +/* ========================================================================== */ +/* === debug_deg_lists ====================================================== */ +/* ========================================================================== */ + +/* + Prints the contents of the degree lists. Counts the number of columns + in the degree list and compares it to the total it should have. Also + checks the row degrees. +*/ + +PRIVATE void debug_deg_lists +( + /* === Parameters ======================================================= */ + + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int head [], + Int min_score, + Int should, + Int max_deg +) +{ + /* === Local variables ================================================== */ + + Int deg ; + Int col ; + Int have ; + Int row ; + + /* === Check the degree lists =========================================== */ + + if (n_col > 10000 && colamd_debug <= 0) + { + return ; + } + have = 0 ; + DEBUG4 (("Degree lists: %d\n", min_score)) ; + for (deg = 0 ; deg <= n_col ; deg++) + { + col = head [deg] ; + if (col == EMPTY) + { + continue ; + } + DEBUG4 (("%d:", deg)) ; + while (col != EMPTY) + { + DEBUG4 ((" %d", col)) ; + have += Col [col].shared1.thickness ; + ASSERT (COL_IS_ALIVE (col)) ; + col = Col [col].shared4.degree_next ; + } + DEBUG4 (("\n")) ; + } + DEBUG4 (("should %d have %d\n", should, have)) ; + ASSERT (should == have) ; + + /* === Check the row degrees ============================================ */ + + if (n_row > 10000 && colamd_debug <= 0) + { + return ; + } + for (row = 0 ; row < n_row ; row++) + { + if (ROW_IS_ALIVE (row)) + { + ASSERT (Row [row].shared1.degree <= max_deg) ; + } + } +} + + +/* ========================================================================== */ +/* === debug_mark =========================================================== */ +/* ========================================================================== */ + +/* + Ensures that the tag_mark is less that the maximum and also ensures that + each entry in the mark array is less than the tag mark. +*/ + +PRIVATE void debug_mark +( + /* === Parameters ======================================================= */ + + Int n_row, + Colamd_Row Row [], + Int tag_mark, + Int max_mark +) +{ + /* === Local variables ================================================== */ + + Int r ; + + /* === Check the Row marks ============================================== */ + + ASSERT (tag_mark > 0 && tag_mark <= max_mark) ; + if (n_row > 10000 && colamd_debug <= 0) + { + return ; + } + for (r = 0 ; r < n_row ; r++) + { + ASSERT (Row [r].shared2.mark < tag_mark) ; + } +} + + +/* ========================================================================== */ +/* === debug_matrix ========================================================= */ +/* ========================================================================== */ + +/* + Prints out the contents of the columns and the rows. +*/ + +PRIVATE void debug_matrix +( + /* === Parameters ======================================================= */ + + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [] +) +{ + /* === Local variables ================================================== */ + + Int r ; + Int c ; + Int *rp ; + Int *rp_end ; + Int *cp ; + Int *cp_end ; + + /* === Dump the rows and columns of the matrix ========================== */ + + if (colamd_debug < 3) + { + return ; + } + DEBUG3 (("DUMP MATRIX:\n")) ; + for (r = 0 ; r < n_row ; r++) + { + DEBUG3 (("Row %d alive? %d\n", r, ROW_IS_ALIVE (r))) ; + if (ROW_IS_DEAD (r)) + { + continue ; + } + DEBUG3 (("start %d length %d degree %d\n", + Row [r].start, Row [r].length, Row [r].shared1.degree)) ; + rp = &A [Row [r].start] ; + rp_end = rp + Row [r].length ; + while (rp < rp_end) + { + c = *rp++ ; + DEBUG4 ((" %d col %d\n", COL_IS_ALIVE (c), c)) ; + } + } + + for (c = 0 ; c < n_col ; c++) + { + DEBUG3 (("Col %d alive? %d\n", c, COL_IS_ALIVE (c))) ; + if (COL_IS_DEAD (c)) + { + continue ; + } + DEBUG3 (("start %d length %d shared1 %d shared2 %d\n", + Col [c].start, Col [c].length, + Col [c].shared1.thickness, Col [c].shared2.score)) ; + cp = &A [Col [c].start] ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + r = *cp++ ; + DEBUG4 ((" %d row %d\n", ROW_IS_ALIVE (r), r)) ; + } + } +} + +PRIVATE void colamd_get_debug +( + char *method +) +{ + FILE *f ; + colamd_debug = 0 ; /* no debug printing */ + f = fopen ("debug", "r") ; + if (f == (FILE *) NULL) + { + colamd_debug = 0 ; + } + else + { + fscanf (f, "%d", &colamd_debug) ; + fclose (f) ; + } + DEBUG0 (("%s: debug version, D = %d (THIS WILL BE SLOW!)\n", + method, colamd_debug)) ; +} + +#endif /* NDEBUG */ diff --git a/resources/3rdparty/glpk-4.53/src/colamd/colamd.h b/resources/3rdparty/glpk-4.53/src/colamd/colamd.h new file mode 100644 index 000000000..511735e5c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/colamd/colamd.h @@ -0,0 +1,69 @@ +/* colamd.h */ + +/* Written by Andrew Makhorin <mao@gnu.org>. */ + +#ifndef COLAMD_H +#define COLAMD_H + +#define _GLPSTD_STDIO +#include "env.h" + +#define COLAMD_DATE "Nov 1, 2007" +#define COLAMD_VERSION_CODE(main, sub) ((main) * 1000 + (sub)) +#define COLAMD_MAIN_VERSION 2 +#define COLAMD_SUB_VERSION 7 +#define COLAMD_SUBSUB_VERSION 1 +#define COLAMD_VERSION \ + COLAMD_VERSION_CODE(COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION) + +#define COLAMD_KNOBS 20 +#define COLAMD_STATS 20 +#define COLAMD_DENSE_ROW 0 +#define COLAMD_DENSE_COL 1 +#define COLAMD_AGGRESSIVE 2 +#define COLAMD_DEFRAG_COUNT 2 +#define COLAMD_STATUS 3 +#define COLAMD_INFO1 4 +#define COLAMD_INFO2 5 +#define COLAMD_INFO3 6 + +#define COLAMD_OK (0) +#define COLAMD_OK_BUT_JUMBLED (1) +#define COLAMD_ERROR_A_not_present (-1) +#define COLAMD_ERROR_p_not_present (-2) +#define COLAMD_ERROR_nrow_negative (-3) +#define COLAMD_ERROR_ncol_negative (-4) +#define COLAMD_ERROR_nnz_negative (-5) +#define COLAMD_ERROR_p0_nonzero (-6) +#define COLAMD_ERROR_A_too_small (-7) +#define COLAMD_ERROR_col_length_negative (-8) +#define COLAMD_ERROR_row_index_out_of_bounds (-9) +#define COLAMD_ERROR_out_of_memory (-10) +#define COLAMD_ERROR_internal_error (-999) + +#define colamd_recommended _glp_colamd_recommended +size_t colamd_recommended(int nnz, int n_row, int n_col); + +#define colamd_set_defaults _glp_colamd_set_defaults +void colamd_set_defaults(double knobs [COLAMD_KNOBS]); + +#define colamd _glp_colamd +int colamd(int n_row, int n_col, int Alen, int A[], int p[], + double knobs[COLAMD_KNOBS], int stats[COLAMD_STATS]); + +#define symamd _glp_symamd +int symamd(int n, int A[], int p[], int perm[], + double knobs[COLAMD_KNOBS], int stats[COLAMD_STATS], + void *(*allocate)(size_t, size_t), void(*release)(void *)); + +#define colamd_report _glp_colamd_report +void colamd_report(int stats[COLAMD_STATS]); + +#define symamd_report _glp_symamd_report +void symamd_report(int stats[COLAMD_STATS]); + +#define colamd_printf xprintf + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/draft.h b/resources/3rdparty/glpk-4.53/src/draft.h new file mode 100644 index 000000000..b453acd48 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/draft.h @@ -0,0 +1,32 @@ +/* draft.h */ + +/* (reserved for copyright notice) */ + +#ifndef DRAFT_H +#define DRAFT_H + +#include "glpk.h" + +#if 1 /* 28/XI-2009 */ +int _glp_analyze_row(glp_prob *P, int len, const int ind[], + const double val[], int type, double rhs, double eps, int *_piv, + double *_x, double *_dx, double *_y, double *_dy, double *_dz); +/* simulate one iteration of dual simplex method */ +#endif + +#if 1 /* 08/XII-2009 */ +void _glp_mpl_init_rand(glp_tran *tran, int seed); +#endif + +#define glp_skpgen _glp_skpgen +void glp_skpgen(int n, int r, int type, int v, int s, int a[], + int *b, int c[]); +/* Pisinger's 0-1 single knapsack problem generator */ + +#if 1 /* 28/V-2010 */ +int _glp_intopt1(glp_prob *P, const glp_iocp *parm); +#endif + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/env/alloc.c b/resources/3rdparty/glpk-4.53/src/env/alloc.c new file mode 100644 index 000000000..5a9d5b766 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/env/alloc.c @@ -0,0 +1,252 @@ +/* alloc.c (dynamic memory allocation) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" + +#define ALIGN 16 +/* some processors need data to be properly aligned, so this macro + * defines the alignment boundary, in bytes, provided by glpk memory + * allocation routines; looks like 16-byte alignment boundary is + * sufficient for all 32- and 64-bit platforms (8-byte boundary is not + * sufficient for some 64-bit platforms because of jmp_buf) */ + +#define MBD_SIZE (((sizeof(MBD) + (ALIGN - 1)) / ALIGN) * ALIGN) +/* size of memory block descriptor, in bytes, rounded up to multiple + * of the alignment boundary */ + +/*********************************************************************** +* dma - dynamic memory allocation (basic routine) +* +* This routine performs dynamic memory allocation. It is similar to +* the standard realloc function, however, it provides every allocated +* memory block with a descriptor, which is used for sanity checks on +* reallocating/freeing previously allocated memory blocks as well as +* for book-keeping the memory usage statistics. */ + +static void *dma(const char *func, void *ptr, size_t size) +{ ENV *env = get_env_ptr(); + MBD *mbd; + if (ptr == NULL) + { /* new memory block will be allocated */ + mbd = NULL; + } + else + { /* allocated memory block will be reallocated or freed */ + /* get pointer to the block descriptor */ + mbd = (MBD *)((char *)ptr - MBD_SIZE); + /* make sure that the block descriptor is valid */ + if (mbd->self != mbd) + xerror("%s: ptr = %p; invalid pointer\n", func, ptr); + /* remove the block from the linked list */ + mbd->self = NULL; + if (mbd->prev == NULL) + env->mem_ptr = mbd->next; + else + mbd->prev->next = mbd->next; + if (mbd->next == NULL) + ; + else + mbd->next->prev = mbd->prev; + /* decrease usage counts */ + if (!(env->mem_count >= 1 && env->mem_total >= mbd->size)) + xerror("%s: memory allocation error\n", func); + env->mem_count--; + env->mem_total -= mbd->size; + if (size == 0) + { /* free the memory block */ + free(mbd); + return NULL; + } + } + /* allocate/reallocate memory block */ + if (size > SIZE_T_MAX - MBD_SIZE) + xerror("%s: block too large\n", func); + size += MBD_SIZE; + if (size > env->mem_limit - env->mem_total) + xerror("%s: memory allocation limit exceeded\n", func); + if (env->mem_count == INT_MAX) + xerror("%s: too many memory blocks allocated\n", func); + mbd = (mbd == NULL ? malloc(size) : realloc(mbd, size)); + if (mbd == NULL) + xerror("%s: no memory available\n", func); + /* setup the block descriptor */ + mbd->size = size; + mbd->self = mbd; + mbd->prev = NULL; + mbd->next = env->mem_ptr; + /* add the block to the beginning of the linked list */ + if (mbd->next != NULL) + mbd->next->prev = mbd; + env->mem_ptr = mbd; + /* increase usage counts */ + env->mem_count++; + if (env->mem_cpeak < env->mem_count) + env->mem_cpeak = env->mem_count; + env->mem_total += size; + if (env->mem_tpeak < env->mem_total) + env->mem_tpeak = env->mem_total; + return (char *)mbd + MBD_SIZE; +} + +/*********************************************************************** +* NAME +* +* glp_alloc - allocate memory block +* +* SYNOPSIS +* +* void *glp_alloc(int n, int size); +* +* DESCRIPTION +* +* The routine glp_alloc allocates a memory block of n * size bytes +* long. +* +* Note that being allocated the memory block contains arbitrary data +* (not binary zeros!). +* +* RETURNS +* +* The routine glp_alloc returns a pointer to the block allocated. +* To free this block the routine glp_free (not free!) must be used. */ + +void *glp_alloc(int n, int size) +{ if (n < 1) + xerror("glp_alloc: n = %d; invalid parameter\n", n); + if (size < 1) + xerror("glp_alloc: size = %d; invalid parameter\n", size); + if ((size_t)n > SIZE_T_MAX / (size_t)size) + xerror("glp_alloc: n = %d, size = %d; block too large\n", + n, size); + return dma("glp_alloc", NULL, (size_t)n * (size_t)size); +} + +/**********************************************************************/ + +void *glp_realloc(void *ptr, int n, int size) +{ /* reallocate memory block */ + if (ptr == NULL) + xerror("glp_realloc: ptr = %p; invalid pointer\n", ptr); + if (n < 1) + xerror("glp_realloc: n = %d; invalid parameter\n", n); + if (size < 1) + xerror("glp_realloc: size = %d; invalid parameter\n", size); + if ((size_t)n > SIZE_T_MAX / (size_t)size) + xerror("glp_realloc: n = %d, size = %d; block too large\n", + n, size); + return dma("glp_realloc", ptr, (size_t)n * (size_t)size); +} + +/*********************************************************************** +* NAME +* +* glp_free - free (deallocate) memory block +* +* SYNOPSIS +* +* void glp_free(void *ptr); +* +* DESCRIPTION +* +* The routine glp_free frees (deallocates) a memory block pointed to +* by ptr, which was previuosly allocated by the routine glp_alloc or +* reallocated by the routine glp_realloc. */ + +void glp_free(void *ptr) +{ if (ptr == NULL) + xerror("glp_free: ptr = %p; invalid pointer\n", ptr); + dma("glp_free", ptr, 0); + return; +} + +/*********************************************************************** +* NAME +* +* glp_mem_limit - set memory usage limit +* +* SYNOPSIS +* +* void glp_mem_limit(int limit); +* +* DESCRIPTION +* +* The routine glp_mem_limit limits the amount of memory available for +* dynamic allocation (in GLPK routines) to limit megabytes. */ + +void glp_mem_limit(int limit) +{ ENV *env = get_env_ptr(); + if (limit < 1) + xerror("glp_mem_limit: limit = %d; invalid parameter\n", + limit); + if ((size_t)limit <= (SIZE_T_MAX >> 20)) + env->mem_limit = (size_t)limit << 20; + else + env->mem_limit = SIZE_T_MAX; + return; +} + +/*********************************************************************** +* NAME +* +* glp_mem_usage - get memory usage information +* +* SYNOPSIS +* +* void glp_mem_usage(int *count, int *cpeak, size_t *total, +* size_t *tpeak); +* +* DESCRIPTION +* +* The routine glp_mem_usage reports some information about utilization +* of the memory by GLPK routines. Information is stored to locations +* specified by corresponding parameters (see below). Any parameter can +* be specified as NULL, in which case its value is not stored. +* +* *count is the number of the memory blocks currently allocated by the +* routines glp_malloc and glp_calloc (one call to glp_malloc or +* glp_calloc results in allocating one memory block). +* +* *cpeak is the peak value of *count reached since the initialization +* of the GLPK library environment. +* +* *total is the total amount, in bytes, of the memory blocks currently +* allocated by the routines glp_malloc and glp_calloc. +* +* *tpeak is the peak value of *total reached since the initialization +* of the GLPK library envirionment. */ + +void glp_mem_usage(int *count, int *cpeak, size_t *total, + size_t *tpeak) +{ ENV *env = get_env_ptr(); + if (count != NULL) + *count = env->mem_count; + if (cpeak != NULL) + *cpeak = env->mem_cpeak; + if (total != NULL) + *total = env->mem_total; + if (tpeak != NULL) + *tpeak = env->mem_tpeak; + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/env/dlsup.c b/resources/3rdparty/glpk-4.53/src/env/dlsup.c new file mode 100644 index 000000000..0987bd5cf --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/env/dlsup.c @@ -0,0 +1,167 @@ +/* dlsup.c (dynamic linking support) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "env.h" + +/* GNU version ********************************************************/ + +#if defined(HAVE_LTDL) + +#include <ltdl.h> + +void *xdlopen(const char *module) +{ /* open dynamically linked library */ + void *h = NULL; + if (lt_dlinit() != 0) + { put_err_msg(lt_dlerror()); + goto done; + } + h = lt_dlopen(module); + if (h == NULL) + { put_err_msg(lt_dlerror()); + if (lt_dlexit() != 0) + xerror("xdlopen: %s\n", lt_dlerror()); + } +done: return h; +} + +void *xdlsym(void *h, const char *symbol) +{ /* obtain address of symbol from dynamically linked library */ + void *ptr; + xassert(h != NULL); + ptr = lt_dlsym(h, symbol); + if (ptr == NULL) + xerror("xdlsym: %s: %s\n", symbol, lt_dlerror()); + return ptr; +} + +void xdlclose(void *h) +{ /* close dynamically linked library */ + xassert(h != NULL); + if (lt_dlclose(h) != 0) + xerror("xdlclose: %s\n", lt_dlerror()); + if (lt_dlexit() != 0) + xerror("xdlclose: %s\n", lt_dlerror()); + return; +} + +/* POSIX version ******************************************************/ + +#elif defined(HAVE_DLFCN) + +#include <dlfcn.h> + +void *xdlopen(const char *module) +{ /* open dynamically linked library */ + void *h; + h = dlopen(module, RTLD_NOW); + if (h == NULL) + put_err_msg(dlerror()); + return h; +} + +void *xdlsym(void *h, const char *symbol) +{ /* obtain address of symbol from dynamically linked library */ + void *ptr; + xassert(h != NULL); + ptr = dlsym(h, symbol); + if (ptr == NULL) + xerror("xdlsym: %s: %s\n", symbol, dlerror()); + return ptr; +} + +void xdlclose(void *h) +{ /* close dynamically linked library */ + xassert(h != NULL); + if (dlclose(h) != 0) + xerror("xdlclose: %s\n", dlerror()); + return; +} + +/* MS Windows version *************************************************/ + +#elif defined(__WOE__) + +#include <windows.h> + +void *xdlopen(const char *module) +{ /* open dynamically linked library */ + void *h; + h = LoadLibrary(module); + if (h == NULL) + { char msg[20]; + sprintf(msg, "Error %d", GetLastError()); + put_err_msg(msg); + } + return h; +} + +void *xdlsym(void *h, const char *symbol) +{ /* obtain address of symbol from dynamically linked library */ + void *ptr; + xassert(h != NULL); + ptr = GetProcAddress(h, symbol); + if (ptr == NULL) + xerror("xdlsym: %s: Error %d\n", symbol, GetLastError()); + return ptr; +} + +void xdlclose(void *h) +{ /* close dynamically linked library */ + xassert(h != NULL); + if (!FreeLibrary(h)) + xerror("xdlclose: Error %d\n", GetLastError()); + return; +} + +/* NULL version *******************************************************/ + +#else + +void *xdlopen(const char *module) +{ /* open dynamically linked library */ + xassert(module == module); + put_err_msg("Shared libraries not supported"); + return NULL; +} + +void *xdlsym(void *h, const char *symbol) +{ /* obtain address of symbol from dynamically linked library */ + xassert(h != h); + xassert(symbol != symbol); + return NULL; +} + +void xdlclose(void *h) +{ /* close dynamically linked library */ + xassert(h != h); + return; +} + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/env/env.c b/resources/3rdparty/glpk-4.53/src/env/env.c new file mode 100644 index 000000000..56bd7540b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/env/env.c @@ -0,0 +1,237 @@ +/* env.c (GLPK environment initialization/termination) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "glpk.h" +#include "env.h" + +/*********************************************************************** +* NAME +* +* glp_init_env - initialize GLPK environment +* +* SYNOPSIS +* +* int glp_init_env(void); +* +* DESCRIPTION +* +* The routine glp_init_env initializes the GLPK environment. Normally +* the application program does not need to call this routine, because +* it is called automatically on the first call to any API routine. +* +* RETURNS +* +* The routine glp_init_env returns one of the following codes: +* +* 0 - initialization successful; +* 1 - environment has been already initialized; +* 2 - initialization failed (insufficient memory); +* 3 - initialization failed (unsupported programming model). */ + +int glp_init_env(void) +{ ENV *env; + int ok; + /* check if the programming model is supported */ + ok = (CHAR_BIT == 8 && sizeof(char) == 1 && + sizeof(short) == 2 && sizeof(int) == 4 && + (sizeof(void *) == 4 || sizeof(void *) == 8)); + if (!ok) + return 3; + /* check if the environment is already initialized */ + if (tls_get_ptr() != NULL) + return 1; + /* allocate and initialize the environment block */ + env = malloc(sizeof(ENV)); + if (env == NULL) + return 2; + memset(env, 0, sizeof(ENV)); + sprintf(env->version, "%d.%d", + GLP_MAJOR_VERSION, GLP_MINOR_VERSION); + env->self = env; + env->term_buf = malloc(TBUF_SIZE); + if (env->term_buf == NULL) + { free(env); + return 2; + } + env->term_out = GLP_ON; + env->term_hook = NULL; + env->term_info = NULL; + env->tee_file = NULL; + env->err_file = NULL; + env->err_line = 0; + env->err_hook = NULL; + env->err_info = NULL; + env->err_buf = malloc(EBUF_SIZE); + if (env->err_buf == NULL) + { free(env->term_buf); + free(env); + return 2; + } + env->err_buf[0] = '\0'; + env->mem_limit = SIZE_T_MAX; + env->mem_ptr = NULL; + env->mem_count = env->mem_cpeak = 0; + env->mem_total = env->mem_tpeak = 0; + env->h_odbc = env->h_mysql = NULL; + /* save pointer to the environment block */ + tls_set_ptr(env); + /* initialization successful */ + return 0; +} + +/*********************************************************************** +* NAME +* +* get_env_ptr - retrieve pointer to environment block +* +* SYNOPSIS +* +* #include "env.h" +* ENV *get_env_ptr(void); +* +* DESCRIPTION +* +* The routine get_env_ptr retrieves and returns a pointer to the GLPK +* environment block. +* +* If the GLPK environment has not been initialized yet, the routine +* performs initialization. If initialization fails, the routine prints +* an error message to stderr and terminates the program. +* +* RETURNS +* +* The routine returns a pointer to the environment block. */ + +ENV *get_env_ptr(void) +{ ENV *env = tls_get_ptr(); + /* check if the environment has been initialized */ + if (env == NULL) + { /* not initialized yet; perform initialization */ + if (glp_init_env() != 0) + { /* initialization failed; display an error message */ + fprintf(stderr, "GLPK initialization failed\n"); + fflush(stderr); + /* and abnormally terminate the program */ + abort(); + } + /* initialization successful; retrieve the pointer */ + env = tls_get_ptr(); + } + /* check if the environment block is valid */ + if (env->self != env) + { fprintf(stderr, "Invalid GLPK environment\n"); + fflush(stderr); + abort(); + } + return env; +} + +/*********************************************************************** +* NAME +* +* glp_version - determine library version +* +* SYNOPSIS +* +* const char *glp_version(void); +* +* RETURNS +* +* The routine glp_version returns a pointer to a null-terminated +* character string, which specifies the version of the GLPK library in +* the form "X.Y", where X is the major version number, and Y is the +* minor version number, for example, "4.16". */ + +const char *glp_version(void) +{ ENV *env = get_env_ptr(); + return env->version; +} + +/*********************************************************************** +* NAME +* +* glp_free_env - free GLPK environment +* +* SYNOPSIS +* +* int glp_free_env(void); +* +* DESCRIPTION +* +* The routine glp_free_env frees all resources used by GLPK routines +* (memory blocks, etc.) which are currently still in use. +* +* Normally the application program does not need to call this routine, +* because GLPK routines always free all unused resources. However, if +* the application program even has deleted all problem objects, there +* will be several memory blocks still allocated for the library needs. +* For some reasons the application program may want GLPK to free this +* memory, in which case it should call glp_free_env. +* +* Note that a call to glp_free_env invalidates all problem objects as +* if no GLPK routine were called. +* +* RETURNS +* +* 0 - termination successful; +* 1 - environment is inactive (was not initialized). */ + +int glp_free_env(void) +{ ENV *env = tls_get_ptr(); + MBD *desc; + /* check if the environment is active */ + if (env == NULL) + return 1; + /* check if the environment block is valid */ + if (env->self != env) + { fprintf(stderr, "Invalid GLPK environment\n"); + fflush(stderr); + abort(); + } + /* close handles to shared libraries */ + if (env->h_odbc != NULL) + xdlclose(env->h_odbc); + if (env->h_mysql != NULL) + xdlclose(env->h_mysql); + /* free memory blocks which are still allocated */ + while (env->mem_ptr != NULL) + { desc = env->mem_ptr; + env->mem_ptr = desc->next; + free(desc); + } + /* close text file used for copying terminal output */ + if (env->tee_file != NULL) + fclose(env->tee_file); + /* invalidate the environment block */ + env->self = NULL; + /* free memory allocated to the environment block */ + free(env->term_buf); + free(env->err_buf); + free(env); + /* reset a pointer to the environment block */ + tls_set_ptr(NULL); + /* termination successful */ + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/env/env.h b/resources/3rdparty/glpk-4.53/src/env/env.h new file mode 100644 index 000000000..2c013dce7 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/env/env.h @@ -0,0 +1,258 @@ +/* env.h (GLPK environment) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef ENV_H +#define ENV_H + +#include "stdc.h" + +typedef struct ENV ENV; +typedef struct MBD MBD; + +#define SIZE_T_MAX (~(size_t)0) +/* largest value of size_t type */ + +#define TBUF_SIZE 4096 +/* terminal output buffer size, in bytes */ + +#define EBUF_SIZE 1024 +/* error message buffer size, in bytes */ + +/* enable/disable flag: */ +#define GLP_ON 1 +#define GLP_OFF 0 + +struct ENV +{ /* GLPK environment block */ + char version[7+1]; + /* version string returned by the routine glp_version */ + ENV *self; + /* pointer to this block to check its validity */ + /*--------------------------------------------------------------*/ + /* terminal output */ + char *term_buf; /* char term_buf[TBUF_SIZE]; */ + /* terminal output buffer */ + int term_out; + /* flag to enable/disable terminal output */ + int (*term_hook)(void *info, const char *s); + /* user-defined routine to intercept terminal output */ + void *term_info; + /* transit pointer (cookie) passed to the routine term_hook */ + FILE *tee_file; + /* output stream used to copy terminal output */ + /*--------------------------------------------------------------*/ + /* error handling */ + const char *err_file; + /* value of the __FILE__ macro passed to glp_error */ + int err_line; + /* value of the __LINE__ macro passed to glp_error */ + void (*err_hook)(void *info); + /* user-defined routine to intercept abnormal termination */ + void *err_info; + /* transit pointer (cookie) passed to the routine err_hook */ + char *err_buf; /* char err_buf[EBUF_SIZE]; */ + /* buffer to store error messages (used by I/O routines) */ + /*--------------------------------------------------------------*/ + /* dynamic memory allocation */ + size_t mem_limit; + /* maximal amount of memory, in bytes, available for dynamic + * allocation */ + MBD *mem_ptr; + /* pointer to the linked list of allocated memory blocks */ + int mem_count; + /* total number of currently allocated memory blocks */ + int mem_cpeak; + /* peak value of mem_count */ + size_t mem_total; + /* total amount of currently allocated memory, in bytes; it is + * the sum of the size field over all memory block descriptors */ + size_t mem_tpeak; + /* peak value of mem_total */ + /*--------------------------------------------------------------*/ + /* dynamic linking support (optional) */ + void *h_odbc; + /* handle to ODBC shared library */ + void *h_mysql; + /* handle to MySQL shared library */ +}; + +struct MBD +{ /* memory block descriptor */ + size_t size; + /* size of block, in bytes, including descriptor */ + MBD *self; + /* pointer to this descriptor to check its validity */ + MBD *prev; + /* pointer to previous memory block descriptor */ + MBD *next; + /* pointer to next memory block descriptor */ +}; + +#define get_env_ptr _glp_get_env_ptr +ENV *get_env_ptr(void); +/* retrieve pointer to environment block */ + +#define tls_set_ptr _glp_tls_set_ptr +void tls_set_ptr(void *ptr); +/* store global pointer in TLS */ + +#define tls_get_ptr _glp_tls_get_ptr +void *tls_get_ptr(void); +/* retrieve global pointer from TLS */ + +#define xputs glp_puts +void glp_puts(const char *s); +/* write string on terminal */ + +#define xprintf glp_printf +void glp_printf(const char *fmt, ...); +/* write formatted output on terminal */ + +#define xvprintf glp_vprintf +void glp_vprintf(const char *fmt, va_list arg); +/* write formatted output on terminal */ + +int glp_term_out(int flag); +/* enable/disable terminal output */ + +void glp_term_hook(int (*func)(void *info, const char *s), void *info); +/* install hook to intercept terminal output */ + +int glp_open_tee(const char *fname); +/* start copying terminal output to text file */ + +int glp_close_tee(void); +/* stop copying terminal output to text file */ + +#ifndef GLP_ERRFUNC_DEFINED +#define GLP_ERRFUNC_DEFINED +typedef void (*glp_errfunc)(const char *fmt, ...); +#endif + +#define xerror glp_error_(__FILE__, __LINE__) +glp_errfunc glp_error_(const char *file, int line); +/* display fatal error message and terminate execution */ + +#define xassert(expr) \ + ((void)((expr) || (glp_assert_(#expr, __FILE__, __LINE__), 1))) +void glp_assert_(const char *expr, const char *file, int line); +/* check for logical condition */ + +void glp_error_hook(void (*func)(void *info), void *info); +/* install hook to intercept abnormal termination */ + +#define put_err_msg _glp_put_err_msg +void put_err_msg(const char *msg); +/* provide error message string */ + +#define get_err_msg _glp_get_err_msg +const char *get_err_msg(void); +/* obtain error message string */ + +#define xmalloc(size) glp_alloc(1, size) +/* allocate memory block (obsolete) */ + +#define xcalloc(n, size) glp_alloc(n, size) +/* allocate memory block (obsolete) */ + +#define xalloc(n, size) glp_alloc(n, size) +#define talloc(n, type) ((type *)glp_alloc(n, sizeof(type))) +void *glp_alloc(int n, int size); +/* allocate memory block */ + +#define xrealloc(ptr, n, size) glp_realloc(ptr, n, size) +#define trealloc(ptr, n, type) ((type *)glp_realloc(ptr, n, \ + sizeof(type))) +void *glp_realloc(void *ptr, int n, int size); +/* reallocate memory block */ + +#define xfree(ptr) glp_free(ptr) +#define tfree(ptr) glp_free(ptr) +void glp_free(void *ptr); +/* free memory block */ + +void glp_mem_limit(int limit); +/* set memory usage limit */ + +void glp_mem_usage(int *count, int *cpeak, size_t *total, + size_t *tpeak); +/* get memory usage information */ + +typedef struct glp_file glp_file; +/* sequential stream descriptor */ + +#define glp_open _glp_open +glp_file *glp_open(const char *name, const char *mode); +/* open stream */ + +#define glp_eof _glp_eof +int glp_eof(glp_file *f); +/* test end-of-file indicator */ + +#define glp_ioerr _glp_ioerr +int glp_ioerr(glp_file *f); +/* test I/O error indicator */ + +#define glp_read _glp_read +int glp_read(glp_file *f, void *buf, int nnn); +/* read data from stream */ + +#define glp_getc _glp_getc +int glp_getc(glp_file *f); +/* read character from stream */ + +#define glp_write _glp_write +int glp_write(glp_file *f, const void *buf, int nnn); +/* write data to stream */ + +#define glp_format _glp_format +int glp_format(glp_file *f, const char *fmt, ...); +/* write formatted data to stream */ + +#define glp_close _glp_close +int glp_close(glp_file *f); +/* close stream */ + +#define xtime glp_time +double glp_time(void); +/* determine current universal time */ + +#define xdifftime glp_difftime +double glp_difftime(double t1, double t0); +/* compute difference between two time values */ + +#define xdlopen _glp_dlopen +void *xdlopen(const char *module); +/* open dynamically linked library */ + +#define xdlsym _glp_dlsym +void *xdlsym(void *h, const char *symbol); +/* obtain address of symbol from dynamically linked library */ + +#define xdlclose _glp_dlclose +void xdlclose(void *h); +/* close dynamically linked library */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/env/error.c b/resources/3rdparty/glpk-4.53/src/env/error.c new file mode 100644 index 000000000..3dec72125 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/env/error.c @@ -0,0 +1,170 @@ +/* error.c (error handling) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" + +/*********************************************************************** +* NAME +* +* glp_error - display fatal error message and terminate execution +* +* SYNOPSIS +* +* void glp_error(const char *fmt, ...); +* +* DESCRIPTION +* +* The routine glp_error (implemented as a macro) formats its +* parameters using the format control string fmt, writes the formatted +* message on the terminal, and abnormally terminates the program. */ + +static void errfunc(const char *fmt, ...) +{ ENV *env = get_env_ptr(); + va_list arg; + env->term_out = GLP_ON; + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + xprintf("Error detected in file %s at line %d\n", + env->err_file, env->err_line); + if (env->err_hook != NULL) + env->err_hook(env->err_info); + abort(); + exit(EXIT_FAILURE); + /* no return */ +} + +glp_errfunc glp_error_(const char *file, int line) +{ ENV *env = get_env_ptr(); + env->err_file = file; + env->err_line = line; + return errfunc; +} + +/*********************************************************************** +* NAME +* +* glp_assert - check for logical condition +* +* SYNOPSIS +* +* void glp_assert(int expr); +* +* DESCRIPTION +* +* The routine glp_assert (implemented as a macro) checks for a logical +* condition specified by the parameter expr. If the condition is false +* (i.e. the value of expr is zero), the routine writes a message on +* the terminal and abnormally terminates the program. */ + +void glp_assert_(const char *expr, const char *file, int line) +{ glp_error_(file, line)("Assertion failed: %s\n", expr); + /* no return */ +} + +/*********************************************************************** +* NAME +* +* glp_error_hook - install hook to intercept abnormal termination +* +* SYNOPSIS +* +* void glp_error_hook(void (*func)(void *info), void *info); +* +* DESCRIPTION +* +* The routine glp_error_hook installs a user-defined hook routine to +* intercept abnormal termination. +* +* The parameter func specifies the user-defined hook routine. It is +* called from the routine glp_error before the latter calls the abort +* function to abnormally terminate the application program because of +* fatal error. The parameter info is a transit pointer, specified in +* the corresponding call to the routine glp_error_hook; it may be used +* to pass some information to the hook routine. +* +* To uninstall the hook routine the parameters func and info should be +* both specified as NULL. */ + +void glp_error_hook(void (*func)(void *info), void *info) +{ ENV *env = get_env_ptr(); + if (func == NULL) + { env->err_hook = NULL; + env->err_info = NULL; + } + else + { env->err_hook = func; + env->err_info = info; + } + return; +} + +/*********************************************************************** +* NAME +* +* put_err_msg - provide error message string +* +* SYNOPSIS +* +* #include "env.h" +* void put_err_msg(const char *msg); +* +* DESCRIPTION +* +* The routine put_err_msg stores an error message string pointed to by +* msg to the environment block. */ + +void put_err_msg(const char *msg) +{ ENV *env = get_env_ptr(); + int len; + len = strlen(msg); + if (len >= EBUF_SIZE) + len = EBUF_SIZE - 1; + memcpy(env->err_buf, msg, len); + if (len > 0 && env->err_buf[len-1] == '\n') + len--; + env->err_buf[len] = '\0'; + return; +} + +/*********************************************************************** +* NAME +* +* get_err_msg - obtain error message string +* +* SYNOPSIS +* +* #include "env.h" +* const char *get_err_msg(void); +* +* RETURNS +* +* The routine get_err_msg returns a pointer to an error message string +* previously stored by the routine put_err_msg. */ + +const char *get_err_msg(void) +{ ENV *env = get_env_ptr(); + return env->err_buf; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/env/stdc.h b/resources/3rdparty/glpk-4.53/src/env/stdc.h new file mode 100644 index 000000000..2d0416370 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/env/stdc.h @@ -0,0 +1,42 @@ +/* stdc.h (standard ANSI C headers) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef STDC_H +#define STDC_H + +#include <ctype.h> +#include <errno.h> +#include <float.h> +#include <limits.h> +#include <math.h> +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/env/stdout.c b/resources/3rdparty/glpk-4.53/src/env/stdout.c new file mode 100644 index 000000000..fc44e1218 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/env/stdout.c @@ -0,0 +1,262 @@ +/* stdout.c (terminal output) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#undef NDEBUG +#include <assert.h> +#include "env.h" + +/*********************************************************************** +* NAME +* +* glp_puts - write string on terminal +* +* SYNOPSIS +* +* void glp_puts(const char *s); +* +* The routine glp_puts writes the string s on the terminal. */ + +void glp_puts(const char *s) +{ ENV *env = get_env_ptr(); + /* if terminal output is disabled, do nothing */ + if (!env->term_out) + goto skip; + /* pass the string to the hook routine, if defined */ + if (env->term_hook != NULL) + { if (env->term_hook(env->term_info, s) != 0) + goto skip; + } + /* write the string on the terminal */ + fputs(s, stdout); + fflush(stdout); + /* write the string on the tee file, if required */ + if (env->tee_file != NULL) + { fputs(s, env->tee_file); + fflush(env->tee_file); + } +skip: return; +} + +/*********************************************************************** +* NAME +* +* glp_printf - write formatted output on terminal +* +* SYNOPSIS +* +* void glp_printf(const char *fmt, ...); +* +* DESCRIPTION +* +* The routine glp_printf uses the format control string fmt to format +* its parameters and writes the formatted output on the terminal. */ + +void glp_printf(const char *fmt, ...) +{ ENV *env = get_env_ptr(); + va_list arg; + /* if terminal output is disabled, do nothing */ + if (!env->term_out) + goto skip; + /* format the output */ + va_start(arg, fmt); + vsprintf(env->term_buf, fmt, arg); + /* (do not use xassert) */ + assert(strlen(env->term_buf) < TBUF_SIZE); + va_end(arg); + /* write the formatted output on the terminal */ + glp_puts(env->term_buf); +skip: return; +} + +/*********************************************************************** +* NAME +* +* glp_vprintf - write formatted output on terminal +* +* SYNOPSIS +* +* void glp_vprintf(const char *fmt, va_list arg); +* +* DESCRIPTION +* +* The routine glp_vprintf uses the format control string fmt to format +* its parameters specified by the list arg and writes the formatted +* output on the terminal. */ + +void glp_vprintf(const char *fmt, va_list arg) +{ ENV *env = get_env_ptr(); + /* if terminal output is disabled, do nothing */ + if (!env->term_out) + goto skip; + /* format the output */ + vsprintf(env->term_buf, fmt, arg); + /* (do not use xassert) */ + assert(strlen(env->term_buf) < TBUF_SIZE); + /* write the formatted output on the terminal */ + glp_puts(env->term_buf); +skip: return; +} + +/*********************************************************************** +* NAME +* +* glp_term_out - enable/disable terminal output +* +* SYNOPSIS +* +* int glp_term_out(int flag); +* +* DESCRIPTION +* +* Depending on the parameter flag the routine glp_term_out enables or +* disables terminal output performed by glpk routines: +* +* GLP_ON - enable terminal output; +* GLP_OFF - disable terminal output. +* +* RETURNS +* +* The routine glp_term_out returns the previous value of the terminal +* output flag. */ + +int glp_term_out(int flag) +{ ENV *env = get_env_ptr(); + int old = env->term_out; + if (!(flag == GLP_ON || flag == GLP_OFF)) + xerror("glp_term_out: flag = %d; invalid parameter\n", flag); + env->term_out = flag; + return old; +} + +/*********************************************************************** +* NAME +* +* glp_term_hook - install hook to intercept terminal output +* +* SYNOPSIS +* +* void glp_term_hook(int (*func)(void *info, const char *s), +* void *info); +* +* DESCRIPTION +* +* The routine glp_term_hook installs a user-defined hook routine to +* intercept all terminal output performed by glpk routines. +* +* This feature can be used to redirect the terminal output to other +* destination, for example to a file or a text window. +* +* The parameter func specifies the user-defined hook routine. It is +* called from an internal printing routine, which passes to it two +* parameters: info and s. The parameter info is a transit pointer, +* specified in the corresponding call to the routine glp_term_hook; +* it may be used to pass some information to the hook routine. The +* parameter s is a pointer to the null terminated character string, +* which is intended to be written to the terminal. If the hook routine +* returns zero, the printing routine writes the string s to the +* terminal in a usual way; otherwise, if the hook routine returns +* non-zero, no terminal output is performed. +* +* To uninstall the hook routine the parameters func and info should be +* specified as NULL. */ + +void glp_term_hook(int (*func)(void *info, const char *s), void *info) +{ ENV *env = get_env_ptr(); + if (func == NULL) + { env->term_hook = NULL; + env->term_info = NULL; + } + else + { env->term_hook = func; + env->term_info = info; + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_open_tee - start copying terminal output to text file +* +* SYNOPSIS +* +* int glp_open_tee(const char *name); +* +* DESCRIPTION +* +* The routine glp_open_tee starts copying all the terminal output to +* an output text file, whose name is specified by the character string +* name. +* +* RETURNS +* +* 0 - operation successful +* 1 - copying terminal output is already active +* 2 - unable to create output file */ + +int glp_open_tee(const char *name) +{ ENV *env = get_env_ptr(); + if (env->tee_file != NULL) + { /* copying terminal output is already active */ + return 1; + } + env->tee_file = fopen(name, "w"); + if (env->tee_file == NULL) + { /* unable to create output file */ + return 2; + } + return 0; +} + +/*********************************************************************** +* NAME +* +* glp_close_tee - stop copying terminal output to text file +* +* SYNOPSIS +* +* int glp_close_tee(void); +* +* DESCRIPTION +* +* The routine glp_close_tee stops copying the terminal output to the +* output text file previously open by the routine glp_open_tee closing +* that file. +* +* RETURNS +* +* 0 - operation successful +* 1 - copying terminal output was not started */ + +int glp_close_tee(void) +{ ENV *env = get_env_ptr(); + if (env->tee_file == NULL) + { /* copying terminal output was not started */ + return 1; + } + fclose(env->tee_file); + env->tee_file = NULL; + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/env/stream.c b/resources/3rdparty/glpk-4.53/src/env/stream.c new file mode 100644 index 000000000..d290c116e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/env/stream.c @@ -0,0 +1,475 @@ +/* stream.c (stream input/output) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "zlib.h" + +struct glp_file +{ /* sequential stream descriptor */ + char *base; + /* pointer to buffer */ + int size; + /* size of buffer, in bytes */ + char *ptr; + /* pointer to next byte in buffer */ + int cnt; + /* count of bytes in buffer */ + int flag; + /* stream flags: */ +#define IONULL 0x01 /* null file */ +#define IOSTD 0x02 /* standard stream */ +#define IOGZIP 0x04 /* gzipped file */ +#define IOWRT 0x08 /* output stream */ +#define IOEOF 0x10 /* end of file */ +#define IOERR 0x20 /* input/output error */ + void *file; + /* pointer to underlying control object */ +}; + +/*********************************************************************** +* NAME +* +* glp_open - open stream +* +* SYNOPSIS +* +* glp_file *glp_open(const char *name, const char *mode); +* +* DESCRIPTION +* +* The routine glp_open opens a file whose name is a string pointed to +* by name and associates a stream with it. +* +* The following special filenames are recognized by the routine (this +* feature is platform independent): +* +* "/dev/null" empty (null) file; +* "/dev/stdin" standard input stream; +* "/dev/stdout" standard output stream; +* "/dev/stderr" standard error stream. +* +* If the specified filename is ended with ".gz", it is assumed that +* the file is in gzipped format. In this case the file is compressed +* or decompressed by the I/O routines "on the fly". +* +* The parameter mode points to a string, which indicates the open mode +* and should be one of the following: +* +* "r" open text file for reading; +* "w" truncate to zero length or create text file for writing; +* "rb" open binary file for reading; +* "wb" truncate to zero length or create binary file for writing. +* +* RETURNS +* +* The routine glp_open returns a pointer to the object controlling the +* stream. If the operation fails, the routine returns NULL. */ + +glp_file *glp_open(const char *name, const char *mode) +{ glp_file *f; + int flag; + void *file; + if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0) + flag = 0; + else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0) + flag = IOWRT; + else + xerror("glp_open: invalid mode string\n"); + if (strcmp(name, "/dev/null") == 0) + { flag |= IONULL; + file = NULL; + } + else if (strcmp(name, "/dev/stdin") == 0) + { flag |= IOSTD; + file = stdin; + } + else if (strcmp(name, "/dev/stdout") == 0) + { flag |= IOSTD; + file = stdout; + } + else if (strcmp(name, "/dev/stderr") == 0) + { flag |= IOSTD; + file = stderr; + } + else + { char *ext = strrchr(name, '.'); + if (ext == NULL || strcmp(ext, ".gz") != 0) + { file = fopen(name, mode); + if (file == NULL) + { put_err_msg(strerror(errno)); + return NULL; + } + } + else + { flag |= IOGZIP; + if (strcmp(mode, "r") == 0) + mode = "rb"; + else if (strcmp(mode, "w") == 0) + mode = "wb"; + file = gzopen(name, mode); + if (file == NULL) + { put_err_msg(strerror(errno)); + return NULL; + } + } + } + f = talloc(1, glp_file); + f->base = talloc(BUFSIZ, char); + f->size = BUFSIZ; + f->ptr = f->base; + f->cnt = 0; + f->flag = flag; + f->file = file; + return f; +} + +/*********************************************************************** +* NAME +* +* glp_eof - test end-of-file indicator +* +* SYNOPSIS +* +* int glp_eof(glp_file *f); +* +* DESCRIPTION +* +* The routine glp_eof tests the end-of-file indicator for the stream +* pointed to by f. +* +* RETURNS +* +* The routine glp_eof returns non-zero if and only if the end-of-file +* indicator is set for the specified stream. */ + +int glp_eof(glp_file *f) +{ return + f->flag & IOEOF; +} + +/*********************************************************************** +* NAME +* +* glp_ioerr - test I/O error indicator +* +* SYNOPSIS +* +* int glp_ioerr(glp_file *f); +* +* DESCRIPTION +* +* The routine glp_ioerr tests the I/O error indicator for the stream +* pointed to by f. +* +* RETURNS +* +* The routine glp_ioerr returns non-zero if and only if the I/O error +* indicator is set for the specified stream. */ + +int glp_ioerr(glp_file *f) +{ return + f->flag & IOERR; +} + +/*********************************************************************** +* NAME +* +* glp_read - read data from stream +* +* SYNOPSIS +* +* int glp_read(glp_file *f, void *buf, int nnn); +* +* DESCRIPTION +* +* The routine glp_read reads, into the buffer pointed to by buf, up to +* nnn bytes, from the stream pointed to by f. +* +* RETURNS +* +* The routine glp_read returns the number of bytes successfully read +* (which may be less than nnn). If an end-of-file is encountered, the +* end-of-file indicator for the stream is set and glp_read returns +* zero. If a read error occurs, the error indicator for the stream is +* set and glp_read returns a negative value. */ + +int glp_read(glp_file *f, void *buf, int nnn) +{ int nrd, cnt; + if (f->flag & IOWRT) + xerror("glp_read: attempt to read from output stream\n"); + if (nnn < 1) + xerror("glp_read: nnn = %d; invalid parameter\n", nnn); + for (nrd = 0; nrd < nnn; nrd += cnt) + { if (f->cnt == 0) + { /* buffer is empty; fill it */ + if (f->flag & IONULL) + cnt = 0; + else if (!(f->flag & IOGZIP)) + { cnt = fread(f->base, 1, f->size, (FILE *)(f->file)); + if (ferror((FILE *)(f->file))) + { f->flag |= IOERR; + put_err_msg(strerror(errno)); + return EOF; + } + } + else + { int errnum; + const char *msg; + cnt = gzread((gzFile)(f->file), f->base, f->size); + if (cnt < 0) + { f->flag |= IOERR; + msg = gzerror((gzFile)(f->file), &errnum); + if (errnum == Z_ERRNO) + put_err_msg(strerror(errno)); + else + put_err_msg(msg); + return EOF; + } + } + if (cnt == 0) + { if (nrd == 0) + f->flag |= IOEOF; + break; + } + f->ptr = f->base; + f->cnt = cnt; + } + cnt = nnn - nrd; + if (cnt > f->cnt) + cnt = f->cnt; + memcpy((char *)buf + nrd, f->ptr, cnt); + f->ptr += cnt; + f->cnt -= cnt; + } + return nrd; +} + +/*********************************************************************** +* NAME +* +* glp_getc - read character from stream +* +* SYNOPSIS +* +* int glp_getc(glp_file *f); +* +* DESCRIPTION +* +* The routine glp_getc obtains a next character as an unsigned char +* converted to an int from the input stream pointed to by f. +* +* RETURNS +* +* The routine glp_getc returns the next character obtained. However, +* if an end-of-file is encountered or a read error occurs, the routine +* returns EOF. (An end-of-file and a read error can be distinguished +* by use of the routines glp_eof and glp_ioerr.) */ + +int glp_getc(glp_file *f) +{ unsigned char buf[1]; + if (f->flag & IOWRT) + xerror("glp_getc: attempt to read from output stream\n"); + if (glp_read(f, buf, 1) != 1) + return EOF; + return buf[0]; +} + +/*********************************************************************** +* do_flush - flush output stream +* +* This routine causes buffered data for the specified output stream to +* be written to the associated file. +* +* If the operation was successful, the routine returns zero, otherwise +* non-zero. */ + +static int do_flush(glp_file *f) +{ xassert(f->flag & IOWRT); + if (f->cnt > 0) + { if (f->flag & IONULL) + ; + else if (!(f->flag & IOGZIP)) + { if ((int)fwrite(f->base, 1, f->cnt, (FILE *)(f->file)) + != f->cnt) + { f->flag |= IOERR; + put_err_msg(strerror(errno)); + return EOF; + } + } + else + { int errnum; + const char *msg; + if (gzwrite((gzFile)(f->file), f->base, f->cnt) != f->cnt) + { f->flag |= IOERR; + msg = gzerror((gzFile)(f->file), &errnum); + if (errnum == Z_ERRNO) + put_err_msg(strerror(errno)); + else + put_err_msg(msg); + return EOF; + } + } + } + f->ptr = f->base; + f->cnt = 0; + return 0; +} + +/*********************************************************************** +* NAME +* +* glp_write - write data to stream +* +* SYNOPSIS +* +* int glp_write(glp_file *f, const void *buf, int nnn); +* +* DESCRIPTION +* +* The routine glp_write writes, from the buffer pointed to by buf, up +* to nnn bytes, to the stream pointed to by f. +* +* RETURNS +* +* The routine glp_write returns the number of bytes successfully +* written (which is equal to nnn). If a write error occurs, the error +* indicator for the stream is set and glp_write returns a negative +* value. */ + +int glp_write(glp_file *f, const void *buf, int nnn) +{ int nwr, cnt; + if (!(f->flag & IOWRT)) + xerror("glp_write: attempt to write to input stream\n"); + if (nnn < 1) + xerror("glp_write: nnn = %d; invalid parameter\n", nnn); + for (nwr = 0; nwr < nnn; nwr += cnt) + { cnt = nnn - nwr; + if (cnt > f->size - f->cnt) + cnt = f->size - f->cnt; + memcpy(f->ptr, (const char *)buf + nwr, cnt); + f->ptr += cnt; + f->cnt += cnt; + if (f->cnt == f->size) + { /* buffer is full; flush it */ + if (do_flush(f) != 0) + return EOF; + } + } + return nwr; +} + +/*********************************************************************** +* NAME +* +* glp_format - write formatted data to stream +* +* SYNOPSIS +* +* int glp_format(glp_file *f, const char *fmt, ...); +* +* DESCRIPTION +* +* The routine glp_format writes formatted data to the stream pointed +* to by f. The format control string pointed to by fmt specifies how +* subsequent arguments are converted for output. +* +* RETURNS +* +* The routine glp_format returns the number of characters written, or +* a negative value if an output error occurs. */ + +int glp_format(glp_file *f, const char *fmt, ...) +{ ENV *env = get_env_ptr(); + va_list arg; + int nnn; + if (!(f->flag & IOWRT)) + xerror("glp_format: attempt to write to input stream\n"); + va_start(arg, fmt); + nnn = vsprintf(env->term_buf, fmt, arg); + xassert(0 <= nnn && nnn < TBUF_SIZE); + va_end(arg); + return nnn == 0 ? 0 : glp_write(f, env->term_buf, nnn); +} + +/*********************************************************************** +* NAME +* +* glp_close - close stream +* +* SYNOPSIS +* +* int glp_close(glp_file *f); +* +* DESCRIPTION +* +* The routine glp_close closes the stream pointed to by f. +* +* RETURNS +* +* If the operation was successful, the routine returns zero, otherwise +* non-zero. */ + +int glp_close(glp_file *f) +{ int ret = 0; + if (f->flag & IOWRT) + { if (do_flush(f) != 0) + ret = EOF; + } + if (f->flag & (IONULL | IOSTD)) + ; + else if (!(f->flag & IOGZIP)) + { if (fclose((FILE *)(f->file)) != 0) + { if (ret == 0) + { put_err_msg(strerror(errno)); + ret = EOF; + } + } + } + else + { int errnum; + errnum = gzclose((gzFile)(f->file)); + if (errnum == Z_OK) + ; + else if (errnum == Z_ERRNO) + { if (ret == 0) + { put_err_msg(strerror(errno)); + ret = EOF; + } + } +#if 1 /* FIXME */ + else + { if (ret == 0) + { ENV *env = get_env_ptr(); + sprintf(env->term_buf, "gzclose returned %d", errnum); + put_err_msg(env->term_buf); + ret = EOF; + } + } +#endif + } + tfree(f->base); + tfree(f); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/env/time.c b/resources/3rdparty/glpk-4.53/src/env/time.c new file mode 100644 index 000000000..01956ce7f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/env/time.c @@ -0,0 +1,159 @@ +/* time.c (standard time) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "env.h" +#include "jd.h" + +/*********************************************************************** +* NAME +* +* glp_time - determine current universal time +* +* SYNOPSIS +* +* double glp_time(void); +* +* RETURNS +* +* The routine glp_time returns the current universal time (UTC), in +* milliseconds, elapsed since 00:00:00 GMT January 1, 1970. */ + +#define EPOCH 2440588 /* jday(1, 1, 1970) */ + +/* POSIX version ******************************************************/ + +#if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY) + +#include <sys/time.h> +#include <time.h> + +double glp_time(void) +{ struct timeval tv; + struct tm *tm; + int j; + double t; + gettimeofday(&tv, NULL); + tm = gmtime(&tv.tv_sec); + j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year); + xassert(j >= 0); + t = ((((double)(j - EPOCH) * 24.0 + (double)tm->tm_hour) * 60.0 + + (double)tm->tm_min) * 60.0 + (double)tm->tm_sec) * 1000.0 + + (double)(tv.tv_usec / 1000); + return t; +} + +/* MS Windows version *************************************************/ + +#elif defined(__WOE__) + +#include <windows.h> + +double glp_time(void) +{ SYSTEMTIME st; + int j; + double t; + GetSystemTime(&st); + j = jday(st.wDay, st.wMonth, st.wYear); + xassert(j >= 0); + t = ((((double)(j - EPOCH) * 24.0 + (double)st.wHour) * 60.0 + + (double)st.wMinute) * 60.0 + (double)st.wSecond) * 1000.0 + + (double)st.wMilliseconds; + return t; +} + +/* portable ANSI C version ********************************************/ + +#else + +#include <time.h> + +double glp_time(void) +{ time_t timer; + struct tm *tm; + int j; + double t; + timer = time(NULL); + tm = gmtime(&timer); + j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year); + xassert(j >= 0); + t = ((((double)(j - EPOCH) * 24.0 + (double)tm->tm_hour) * 60.0 + + (double)tm->tm_min) * 60.0 + (double)tm->tm_sec) * 1000.0; + return t; +} + +#endif + +/*********************************************************************** +* NAME +* +* glp_difftime - compute difference between two time values +* +* SYNOPSIS +* +* double glp_difftime(double t1, double t0); +* +* RETURNS +* +* The routine glp_difftime returns the difference between two time +* values t1 and t0, expressed in seconds. */ + +double glp_difftime(double t1, double t0) +{ return + (t1 - t0) / 1000.0; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +#include <assert.h> + +int main(void) +{ int ttt, ss, mm, hh, day, month, year; + double t; + t = glp_time(); + xprintf("t = %.f\n", t); + assert(floor(t) == t); + ttt = (int)fmod(t, 1000.0); + t = (t - (double)ttt) / 1000.0; + assert(floor(t) == t); + ss = (int)fmod(t, 60.0); + t = (t - (double)ss) / 60.0; + assert(floor(t) == t); + mm = (int)fmod(t, 60.0); + t = (t - (double)mm) / 60.0; + assert(floor(t) == t); + hh = (int)fmod(t, 24.0); + t = (t - (double)hh) / 24.0; + assert(floor(t) == t); + assert(jdate((int)t + EPOCH, &day, &month, &year) == 0); + printf("%04d-%02d-%02d %02d:%02d:%02d.%03d\n", + year, month, day, hh, mm, ss, ttt); + return 0; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/env/tls.c b/resources/3rdparty/glpk-4.53/src/env/tls.c new file mode 100644 index 000000000..b414e3b32 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/env/tls.c @@ -0,0 +1,72 @@ +/* tls.c (thread local storage) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2001, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" + +static void *tls = NULL; +/* NOTE: in a re-entrant version of the package this variable should be + * placed in the Thread Local Storage (TLS) */ + +/*********************************************************************** +* NAME +* +* tls_set_ptr - store global pointer in TLS +* +* SYNOPSIS +* +* #include "env.h" +* void tls_set_ptr(void *ptr); +* +* DESCRIPTION +* +* The routine tls_set_ptr stores a pointer specified by the parameter +* ptr in the Thread Local Storage (TLS). */ + +void tls_set_ptr(void *ptr) +{ tls = ptr; + return; +} + +/*********************************************************************** +* NAME +* +* tls_get_ptr - retrieve global pointer from TLS +* +* SYNOPSIS +* +* #include "env.h" +* void *tls_get_ptr(void); +* +* RETURNS +* +* The routine tls_get_ptr returns a pointer previously stored by the +* routine tls_set_ptr. If the latter has not been called yet, NULL is +* returned. */ + +void *tls_get_ptr(void) +{ void *ptr; + ptr = tls; + return ptr; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi01.c b/resources/3rdparty/glpk-4.53/src/glpapi01.c new file mode 100644 index 000000000..a7010b4e3 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi01.c @@ -0,0 +1,1571 @@ +/* glpapi01.c (problem creating and modifying routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" + +/* CAUTION: DO NOT CHANGE THE LIMITS BELOW */ + +#define M_MAX 100000000 /* = 100*10^6 */ +/* maximal number of rows in the problem object */ + +#define N_MAX 100000000 /* = 100*10^6 */ +/* maximal number of columns in the problem object */ + +#define NNZ_MAX 500000000 /* = 500*10^6 */ +/* maximal number of constraint coefficients in the problem object */ + +/*********************************************************************** +* NAME +* +* glp_create_prob - create problem object +* +* SYNOPSIS +* +* glp_prob *glp_create_prob(void); +* +* DESCRIPTION +* +* The routine glp_create_prob creates a new problem object, which is +* initially "empty", i.e. has no rows and columns. +* +* RETURNS +* +* The routine returns a pointer to the object created, which should be +* used in any subsequent operations on this object. */ + +static void create_prob(glp_prob *lp) +{ lp->magic = GLP_PROB_MAGIC; + lp->pool = dmp_create_pool(); +#if 0 /* 17/XI-2009 */ + lp->cps = xmalloc(sizeof(struct LPXCPS)); + lpx_reset_parms(lp); +#else + lp->parms = NULL; +#endif + lp->tree = NULL; +#if 0 + lp->lwa = 0; + lp->cwa = NULL; +#endif + /* LP/MIP data */ + lp->name = NULL; + lp->obj = NULL; + lp->dir = GLP_MIN; + lp->c0 = 0.0; + lp->m_max = 100; + lp->n_max = 200; + lp->m = lp->n = 0; + lp->nnz = 0; + lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *)); + lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *)); + lp->r_tree = lp->c_tree = NULL; + /* basis factorization */ + lp->valid = 0; + lp->head = xcalloc(1+lp->m_max, sizeof(int)); + lp->bfcp = NULL; + lp->bfd = NULL; + /* basic solution (LP) */ + lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; + lp->obj_val = 0.0; + lp->it_cnt = 0; + lp->some = 0; + /* interior-point solution (LP) */ + lp->ipt_stat = GLP_UNDEF; + lp->ipt_obj = 0.0; + /* integer solution (MIP) */ + lp->mip_stat = GLP_UNDEF; + lp->mip_obj = 0.0; + return; +} + +glp_prob *glp_create_prob(void) +{ glp_prob *lp; + lp = xmalloc(sizeof(glp_prob)); + create_prob(lp); + return lp; +} + +/*********************************************************************** +* NAME +* +* glp_set_prob_name - assign (change) problem name +* +* SYNOPSIS +* +* void glp_set_prob_name(glp_prob *lp, const char *name); +* +* DESCRIPTION +* +* The routine glp_set_prob_name assigns a given symbolic name (1 up to +* 255 characters) to the specified problem object. +* +* If the parameter name is NULL or empty string, the routine erases an +* existing symbolic name of the problem object. */ + +void glp_set_prob_name(glp_prob *lp, const char *name) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_prob_name: operation not allowed\n"); + if (lp->name != NULL) + { dmp_free_atom(lp->pool, lp->name, strlen(lp->name)+1); + lp->name = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int k; + for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_set_prob_name: problem name too long\n"); + if (iscntrl((unsigned char)name[k])) + xerror("glp_set_prob_name: problem name contains invalid" + " character(s)\n"); + } + lp->name = dmp_get_atom(lp->pool, strlen(name)+1); + strcpy(lp->name, name); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_obj_name - assign (change) objective function name +* +* SYNOPSIS +* +* void glp_set_obj_name(glp_prob *lp, const char *name); +* +* DESCRIPTION +* +* The routine glp_set_obj_name assigns a given symbolic name (1 up to +* 255 characters) to the objective function of the specified problem +* object. +* +* If the parameter name is NULL or empty string, the routine erases an +* existing name of the objective function. */ + +void glp_set_obj_name(glp_prob *lp, const char *name) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_obj_name: operation not allowed\n"); + if (lp->obj != NULL) + { dmp_free_atom(lp->pool, lp->obj, strlen(lp->obj)+1); + lp->obj = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int k; + for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_set_obj_name: objective name too long\n"); + if (iscntrl((unsigned char)name[k])) + xerror("glp_set_obj_name: objective name contains invali" + "d character(s)\n"); + } + lp->obj = dmp_get_atom(lp->pool, strlen(name)+1); + strcpy(lp->obj, name); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_obj_dir - set (change) optimization direction flag +* +* SYNOPSIS +* +* void glp_set_obj_dir(glp_prob *lp, int dir); +* +* DESCRIPTION +* +* The routine glp_set_obj_dir sets (changes) optimization direction +* flag (i.e. "sense" of the objective function) as specified by the +* parameter dir: +* +* GLP_MIN - minimization; +* GLP_MAX - maximization. */ + +void glp_set_obj_dir(glp_prob *lp, int dir) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_obj_dir: operation not allowed\n"); + if (!(dir == GLP_MIN || dir == GLP_MAX)) + xerror("glp_set_obj_dir: dir = %d; invalid direction flag\n", + dir); + lp->dir = dir; + return; +} + +/*********************************************************************** +* NAME +* +* glp_add_rows - add new rows to problem object +* +* SYNOPSIS +* +* int glp_add_rows(glp_prob *lp, int nrs); +* +* DESCRIPTION +* +* The routine glp_add_rows adds nrs rows (constraints) to the specified +* problem object. New rows are always added to the end of the row list, +* so the ordinal numbers of existing rows remain unchanged. +* +* Being added each new row is initially free (unbounded) and has empty +* list of the constraint coefficients. +* +* RETURNS +* +* The routine glp_add_rows returns the ordinal number of the first new +* row added to the problem object. */ + +int glp_add_rows(glp_prob *lp, int nrs) +{ glp_tree *tree = lp->tree; + GLPROW *row; + int m_new, i; + /* determine new number of rows */ + if (nrs < 1) + xerror("glp_add_rows: nrs = %d; invalid number of rows\n", + nrs); + if (nrs > M_MAX - lp->m) + xerror("glp_add_rows: nrs = %d; too many rows\n", nrs); + m_new = lp->m + nrs; + /* increase the room, if necessary */ + if (lp->m_max < m_new) + { GLPROW **save = lp->row; + while (lp->m_max < m_new) + { lp->m_max += lp->m_max; + xassert(lp->m_max > 0); + } + lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *)); + memcpy(&lp->row[1], &save[1], lp->m * sizeof(GLPROW *)); + xfree(save); + /* do not forget about the basis header */ + xfree(lp->head); + lp->head = xcalloc(1+lp->m_max, sizeof(int)); + } + /* add new rows to the end of the row list */ + for (i = lp->m+1; i <= m_new; i++) + { /* create row descriptor */ + lp->row[i] = row = dmp_get_atom(lp->pool, sizeof(GLPROW)); + row->i = i; + row->name = NULL; + row->node = NULL; +#if 1 /* 20/IX-2008 */ + row->level = 0; + row->origin = 0; + row->klass = 0; + if (tree != NULL) + { switch (tree->reason) + { case 0: + break; + case GLP_IROWGEN: + xassert(tree->curr != NULL); + row->level = tree->curr->level; + row->origin = GLP_RF_LAZY; + break; + case GLP_ICUTGEN: + xassert(tree->curr != NULL); + row->level = tree->curr->level; + row->origin = GLP_RF_CUT; + break; + default: + xassert(tree != tree); + } + } +#endif + row->type = GLP_FR; + row->lb = row->ub = 0.0; + row->ptr = NULL; + row->rii = 1.0; + row->stat = GLP_BS; +#if 0 + row->bind = -1; +#else + row->bind = 0; +#endif + row->prim = row->dual = 0.0; + row->pval = row->dval = 0.0; + row->mipx = 0.0; + } + /* set new number of rows */ + lp->m = m_new; + /* invalidate the basis factorization */ + lp->valid = 0; +#if 1 + if (tree != NULL && tree->reason != 0) tree->reopt = 1; +#endif + /* return the ordinal number of the first row added */ + return m_new - nrs + 1; +} + +/*********************************************************************** +* NAME +* +* glp_add_cols - add new columns to problem object +* +* SYNOPSIS +* +* int glp_add_cols(glp_prob *lp, int ncs); +* +* DESCRIPTION +* +* The routine glp_add_cols adds ncs columns (structural variables) to +* the specified problem object. New columns are always added to the end +* of the column list, so the ordinal numbers of existing columns remain +* unchanged. +* +* Being added each new column is initially fixed at zero and has empty +* list of the constraint coefficients. +* +* RETURNS +* +* The routine glp_add_cols returns the ordinal number of the first new +* column added to the problem object. */ + +int glp_add_cols(glp_prob *lp, int ncs) +{ glp_tree *tree = lp->tree; + GLPCOL *col; + int n_new, j; + if (tree != NULL && tree->reason != 0) + xerror("glp_add_cols: operation not allowed\n"); + /* determine new number of columns */ + if (ncs < 1) + xerror("glp_add_cols: ncs = %d; invalid number of columns\n", + ncs); + if (ncs > N_MAX - lp->n) + xerror("glp_add_cols: ncs = %d; too many columns\n", ncs); + n_new = lp->n + ncs; + /* increase the room, if necessary */ + if (lp->n_max < n_new) + { GLPCOL **save = lp->col; + while (lp->n_max < n_new) + { lp->n_max += lp->n_max; + xassert(lp->n_max > 0); + } + lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *)); + memcpy(&lp->col[1], &save[1], lp->n * sizeof(GLPCOL *)); + xfree(save); + } + /* add new columns to the end of the column list */ + for (j = lp->n+1; j <= n_new; j++) + { /* create column descriptor */ + lp->col[j] = col = dmp_get_atom(lp->pool, sizeof(GLPCOL)); + col->j = j; + col->name = NULL; + col->node = NULL; + col->kind = GLP_CV; + col->type = GLP_FX; + col->lb = col->ub = 0.0; + col->coef = 0.0; + col->ptr = NULL; + col->sjj = 1.0; + col->stat = GLP_NS; +#if 0 + col->bind = -1; +#else + col->bind = 0; /* the basis may remain valid */ +#endif + col->prim = col->dual = 0.0; + col->pval = col->dval = 0.0; + col->mipx = 0.0; + } + /* set new number of columns */ + lp->n = n_new; + /* return the ordinal number of the first column added */ + return n_new - ncs + 1; +} + +/*********************************************************************** +* NAME +* +* glp_set_row_name - assign (change) row name +* +* SYNOPSIS +* +* void glp_set_row_name(glp_prob *lp, int i, const char *name); +* +* DESCRIPTION +* +* The routine glp_set_row_name assigns a given symbolic name (1 up to +* 255 characters) to i-th row (auxiliary variable) of the specified +* problem object. +* +* If the parameter name is NULL or empty string, the routine erases an +* existing name of i-th row. */ + +void glp_set_row_name(glp_prob *lp, int i, const char *name) +{ glp_tree *tree = lp->tree; + GLPROW *row; + if (!(1 <= i && i <= lp->m)) + xerror("glp_set_row_name: i = %d; row number out of range\n", + i); + row = lp->row[i]; + if (tree != NULL && tree->reason != 0) + { xassert(tree->curr != NULL); + xassert(row->level == tree->curr->level); + } + if (row->name != NULL) + { if (row->node != NULL) + { xassert(lp->r_tree != NULL); + avl_delete_node(lp->r_tree, row->node); + row->node = NULL; + } + dmp_free_atom(lp->pool, row->name, strlen(row->name)+1); + row->name = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int k; + for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_set_row_name: i = %d; row name too long\n", + i); + if (iscntrl((unsigned char)name[k])) + xerror("glp_set_row_name: i = %d: row name contains inva" + "lid character(s)\n", i); + } + row->name = dmp_get_atom(lp->pool, strlen(name)+1); + strcpy(row->name, name); + if (lp->r_tree != NULL) + { xassert(row->node == NULL); + row->node = avl_insert_node(lp->r_tree, row->name); + avl_set_node_link(row->node, row); + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_col_name - assign (change) column name +* +* SYNOPSIS +* +* void glp_set_col_name(glp_prob *lp, int j, const char *name); +* +* DESCRIPTION +* +* The routine glp_set_col_name assigns a given symbolic name (1 up to +* 255 characters) to j-th column (structural variable) of the specified +* problem object. +* +* If the parameter name is NULL or empty string, the routine erases an +* existing name of j-th column. */ + +void glp_set_col_name(glp_prob *lp, int j, const char *name) +{ glp_tree *tree = lp->tree; + GLPCOL *col; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_col_name: operation not allowed\n"); + if (!(1 <= j && j <= lp->n)) + xerror("glp_set_col_name: j = %d; column number out of range\n" + , j); + col = lp->col[j]; + if (col->name != NULL) + { if (col->node != NULL) + { xassert(lp->c_tree != NULL); + avl_delete_node(lp->c_tree, col->node); + col->node = NULL; + } + dmp_free_atom(lp->pool, col->name, strlen(col->name)+1); + col->name = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int k; + for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_set_col_name: j = %d; column name too long\n" + , j); + if (iscntrl((unsigned char)name[k])) + xerror("glp_set_col_name: j = %d: column name contains i" + "nvalid character(s)\n", j); + } + col->name = dmp_get_atom(lp->pool, strlen(name)+1); + strcpy(col->name, name); + if (lp->c_tree != NULL && col->name != NULL) + { xassert(col->node == NULL); + col->node = avl_insert_node(lp->c_tree, col->name); + avl_set_node_link(col->node, col); + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_row_bnds - set (change) row bounds +* +* SYNOPSIS +* +* void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb, +* double ub); +* +* DESCRIPTION +* +* The routine glp_set_row_bnds sets (changes) the type and bounds of +* i-th row (auxiliary variable) of the specified problem object. +* +* Parameters type, lb, and ub specify the type, lower bound, and upper +* bound, respectively, as follows: +* +* Type Bounds Comments +* ------------------------------------------------------ +* GLP_FR -inf < x < +inf Free variable +* GLP_LO lb <= x < +inf Variable with lower bound +* GLP_UP -inf < x <= ub Variable with upper bound +* GLP_DB lb <= x <= ub Double-bounded variable +* GLP_FX x = lb Fixed variable +* +* where x is the auxiliary variable associated with i-th row. +* +* If the row has no lower bound, the parameter lb is ignored. If the +* row has no upper bound, the parameter ub is ignored. If the row is +* an equality constraint (i.e. the corresponding auxiliary variable is +* of fixed type), only the parameter lb is used while the parameter ub +* is ignored. */ + +void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb, + double ub) +{ GLPROW *row; + if (!(1 <= i && i <= lp->m)) + xerror("glp_set_row_bnds: i = %d; row number out of range\n", + i); + row = lp->row[i]; + row->type = type; + switch (type) + { case GLP_FR: + row->lb = row->ub = 0.0; + if (row->stat != GLP_BS) row->stat = GLP_NF; + break; + case GLP_LO: + row->lb = lb, row->ub = 0.0; + if (row->stat != GLP_BS) row->stat = GLP_NL; + break; + case GLP_UP: + row->lb = 0.0, row->ub = ub; + if (row->stat != GLP_BS) row->stat = GLP_NU; + break; + case GLP_DB: + row->lb = lb, row->ub = ub; + if (!(row->stat == GLP_BS || + row->stat == GLP_NL || row->stat == GLP_NU)) + row->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU); + break; + case GLP_FX: + row->lb = row->ub = lb; + if (row->stat != GLP_BS) row->stat = GLP_NS; + break; + default: + xerror("glp_set_row_bnds: i = %d; type = %d; invalid row ty" + "pe\n", i, type); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_col_bnds - set (change) column bounds +* +* SYNOPSIS +* +* void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb, +* double ub); +* +* DESCRIPTION +* +* The routine glp_set_col_bnds sets (changes) the type and bounds of +* j-th column (structural variable) of the specified problem object. +* +* Parameters type, lb, and ub specify the type, lower bound, and upper +* bound, respectively, as follows: +* +* Type Bounds Comments +* ------------------------------------------------------ +* GLP_FR -inf < x < +inf Free variable +* GLP_LO lb <= x < +inf Variable with lower bound +* GLP_UP -inf < x <= ub Variable with upper bound +* GLP_DB lb <= x <= ub Double-bounded variable +* GLP_FX x = lb Fixed variable +* +* where x is the structural variable associated with j-th column. +* +* If the column has no lower bound, the parameter lb is ignored. If the +* column has no upper bound, the parameter ub is ignored. If the column +* is of fixed type, only the parameter lb is used while the parameter +* ub is ignored. */ + +void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb, + double ub) +{ GLPCOL *col; + if (!(1 <= j && j <= lp->n)) + xerror("glp_set_col_bnds: j = %d; column number out of range\n" + , j); + col = lp->col[j]; + col->type = type; + switch (type) + { case GLP_FR: + col->lb = col->ub = 0.0; + if (col->stat != GLP_BS) col->stat = GLP_NF; + break; + case GLP_LO: + col->lb = lb, col->ub = 0.0; + if (col->stat != GLP_BS) col->stat = GLP_NL; + break; + case GLP_UP: + col->lb = 0.0, col->ub = ub; + if (col->stat != GLP_BS) col->stat = GLP_NU; + break; + case GLP_DB: + col->lb = lb, col->ub = ub; + if (!(col->stat == GLP_BS || + col->stat == GLP_NL || col->stat == GLP_NU)) + col->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU); + break; + case GLP_FX: + col->lb = col->ub = lb; + if (col->stat != GLP_BS) col->stat = GLP_NS; + break; + default: + xerror("glp_set_col_bnds: j = %d; type = %d; invalid column" + " type\n", j, type); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_obj_coef - set (change) obj. coefficient or constant term +* +* SYNOPSIS +* +* void glp_set_obj_coef(glp_prob *lp, int j, double coef); +* +* DESCRIPTION +* +* The routine glp_set_obj_coef sets (changes) objective coefficient at +* j-th column (structural variable) of the specified problem object. +* +* If the parameter j is 0, the routine sets (changes) the constant term +* ("shift") of the objective function. */ + +void glp_set_obj_coef(glp_prob *lp, int j, double coef) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_obj_coef: operation not allowed\n"); + if (!(0 <= j && j <= lp->n)) + xerror("glp_set_obj_coef: j = %d; column number out of range\n" + , j); + if (j == 0) + lp->c0 = coef; + else + lp->col[j]->coef = coef; + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_mat_row - set (replace) row of the constraint matrix +* +* SYNOPSIS +* +* void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[], +* const double val[]); +* +* DESCRIPTION +* +* The routine glp_set_mat_row stores (replaces) the contents of i-th +* row of the constraint matrix of the specified problem object. +* +* Column indices and numeric values of new row elements must be placed +* in locations ind[1], ..., ind[len] and val[1], ..., val[len], where +* 0 <= len <= n is the new length of i-th row, n is the current number +* of columns in the problem object. Elements with identical column +* indices are not allowed. Zero elements are allowed, but they are not +* stored in the constraint matrix. +* +* If the parameter len is zero, the parameters ind and/or val can be +* specified as NULL. */ + +void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[], + const double val[]) +{ glp_tree *tree = lp->tree; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij, *next; + int j, k; + /* obtain pointer to i-th row */ + if (!(1 <= i && i <= lp->m)) + xerror("glp_set_mat_row: i = %d; row number out of range\n", + i); + row = lp->row[i]; + if (tree != NULL && tree->reason != 0) + { xassert(tree->curr != NULL); + xassert(row->level == tree->curr->level); + } + /* remove all existing elements from i-th row */ + while (row->ptr != NULL) + { /* take next element in the row */ + aij = row->ptr; + /* remove the element from the row list */ + row->ptr = aij->r_next; + /* obtain pointer to corresponding column */ + col = aij->col; + /* remove the element from the column list */ + if (aij->c_prev == NULL) + col->ptr = aij->c_next; + else + aij->c_prev->c_next = aij->c_next; + if (aij->c_next == NULL) + ; + else + aij->c_next->c_prev = aij->c_prev; + /* return the element to the memory pool */ + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + /* if the corresponding column is basic, invalidate the basis + factorization */ + if (col->stat == GLP_BS) lp->valid = 0; + } + /* store new contents of i-th row */ + if (!(0 <= len && len <= lp->n)) + xerror("glp_set_mat_row: i = %d; len = %d; invalid row length " + "\n", i, len); + if (len > NNZ_MAX - lp->nnz) + xerror("glp_set_mat_row: i = %d; len = %d; too many constraint" + " coefficients\n", i, len); + for (k = 1; k <= len; k++) + { /* take number j of corresponding column */ + j = ind[k]; + /* obtain pointer to j-th column */ + if (!(1 <= j && j <= lp->n)) + xerror("glp_set_mat_row: i = %d; ind[%d] = %d; column index" + " out of range\n", i, k, j); + col = lp->col[j]; + /* if there is element with the same column index, it can only + be found in the beginning of j-th column list */ + if (col->ptr != NULL && col->ptr->row->i == i) + xerror("glp_set_mat_row: i = %d; ind[%d] = %d; duplicate co" + "lumn indices not allowed\n", i, k, j); + /* create new element */ + aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++; + aij->row = row; + aij->col = col; + aij->val = val[k]; + /* add the new element to the beginning of i-th row and j-th + column lists */ + aij->r_prev = NULL; + aij->r_next = row->ptr; + aij->c_prev = NULL; + aij->c_next = col->ptr; + if (aij->r_next != NULL) aij->r_next->r_prev = aij; + if (aij->c_next != NULL) aij->c_next->c_prev = aij; + row->ptr = col->ptr = aij; + /* if the corresponding column is basic, invalidate the basis + factorization */ + if (col->stat == GLP_BS && aij->val != 0.0) lp->valid = 0; + } + /* remove zero elements from i-th row */ + for (aij = row->ptr; aij != NULL; aij = next) + { next = aij->r_next; + if (aij->val == 0.0) + { /* remove the element from the row list */ + if (aij->r_prev == NULL) + row->ptr = next; + else + aij->r_prev->r_next = next; + if (next == NULL) + ; + else + next->r_prev = aij->r_prev; + /* remove the element from the column list */ + xassert(aij->c_prev == NULL); + aij->col->ptr = aij->c_next; + if (aij->c_next != NULL) aij->c_next->c_prev = NULL; + /* return the element to the memory pool */ + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_mat_col - set (replace) column of the constraint matrix +* +* SYNOPSIS +* +* void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[], +* const double val[]); +* +* DESCRIPTION +* +* The routine glp_set_mat_col stores (replaces) the contents of j-th +* column of the constraint matrix of the specified problem object. +* +* Row indices and numeric values of new column elements must be placed +* in locations ind[1], ..., ind[len] and val[1], ..., val[len], where +* 0 <= len <= m is the new length of j-th column, m is the current +* number of rows in the problem object. Elements with identical column +* indices are not allowed. Zero elements are allowed, but they are not +* stored in the constraint matrix. +* +* If the parameter len is zero, the parameters ind and/or val can be +* specified as NULL. */ + +void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[], + const double val[]) +{ glp_tree *tree = lp->tree; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij, *next; + int i, k; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_mat_col: operation not allowed\n"); + /* obtain pointer to j-th column */ + if (!(1 <= j && j <= lp->n)) + xerror("glp_set_mat_col: j = %d; column number out of range\n", + j); + col = lp->col[j]; + /* remove all existing elements from j-th column */ + while (col->ptr != NULL) + { /* take next element in the column */ + aij = col->ptr; + /* remove the element from the column list */ + col->ptr = aij->c_next; + /* obtain pointer to corresponding row */ + row = aij->row; + /* remove the element from the row list */ + if (aij->r_prev == NULL) + row->ptr = aij->r_next; + else + aij->r_prev->r_next = aij->r_next; + if (aij->r_next == NULL) + ; + else + aij->r_next->r_prev = aij->r_prev; + /* return the element to the memory pool */ + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + } + /* store new contents of j-th column */ + if (!(0 <= len && len <= lp->m)) + xerror("glp_set_mat_col: j = %d; len = %d; invalid column leng" + "th\n", j, len); + if (len > NNZ_MAX - lp->nnz) + xerror("glp_set_mat_col: j = %d; len = %d; too many constraint" + " coefficients\n", j, len); + for (k = 1; k <= len; k++) + { /* take number i of corresponding row */ + i = ind[k]; + /* obtain pointer to i-th row */ + if (!(1 <= i && i <= lp->m)) + xerror("glp_set_mat_col: j = %d; ind[%d] = %d; row index ou" + "t of range\n", j, k, i); + row = lp->row[i]; + /* if there is element with the same row index, it can only be + found in the beginning of i-th row list */ + if (row->ptr != NULL && row->ptr->col->j == j) + xerror("glp_set_mat_col: j = %d; ind[%d] = %d; duplicate ro" + "w indices not allowed\n", j, k, i); + /* create new element */ + aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++; + aij->row = row; + aij->col = col; + aij->val = val[k]; + /* add the new element to the beginning of i-th row and j-th + column lists */ + aij->r_prev = NULL; + aij->r_next = row->ptr; + aij->c_prev = NULL; + aij->c_next = col->ptr; + if (aij->r_next != NULL) aij->r_next->r_prev = aij; + if (aij->c_next != NULL) aij->c_next->c_prev = aij; + row->ptr = col->ptr = aij; + } + /* remove zero elements from j-th column */ + for (aij = col->ptr; aij != NULL; aij = next) + { next = aij->c_next; + if (aij->val == 0.0) + { /* remove the element from the row list */ + xassert(aij->r_prev == NULL); + aij->row->ptr = aij->r_next; + if (aij->r_next != NULL) aij->r_next->r_prev = NULL; + /* remove the element from the column list */ + if (aij->c_prev == NULL) + col->ptr = next; + else + aij->c_prev->c_next = next; + if (next == NULL) + ; + else + next->c_prev = aij->c_prev; + /* return the element to the memory pool */ + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + } + } + /* if j-th column is basic, invalidate the basis factorization */ + if (col->stat == GLP_BS) lp->valid = 0; + return; +} + +/*********************************************************************** +* NAME +* +* glp_load_matrix - load (replace) the whole constraint matrix +* +* SYNOPSIS +* +* void glp_load_matrix(glp_prob *lp, int ne, const int ia[], +* const int ja[], const double ar[]); +* +* DESCRIPTION +* +* The routine glp_load_matrix loads the constraint matrix passed in +* the arrays ia, ja, and ar into the specified problem object. Before +* loading the current contents of the constraint matrix is destroyed. +* +* Constraint coefficients (elements of the constraint matrix) must be +* specified as triplets (ia[k], ja[k], ar[k]) for k = 1, ..., ne, +* where ia[k] is the row index, ja[k] is the column index, ar[k] is a +* numeric value of corresponding constraint coefficient. The parameter +* ne specifies the total number of (non-zero) elements in the matrix +* to be loaded. Coefficients with identical indices are not allowed. +* Zero coefficients are allowed, however, they are not stored in the +* constraint matrix. +* +* If the parameter ne is zero, the parameters ia, ja, and ar can be +* specified as NULL. */ + +void glp_load_matrix(glp_prob *lp, int ne, const int ia[], + const int ja[], const double ar[]) +{ glp_tree *tree = lp->tree; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij, *next; + int i, j, k; + if (tree != NULL && tree->reason != 0) + xerror("glp_load_matrix: operation not allowed\n"); + /* clear the constraint matrix */ + for (i = 1; i <= lp->m; i++) + { row = lp->row[i]; + while (row->ptr != NULL) + { aij = row->ptr; + row->ptr = aij->r_next; + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + } + } + xassert(lp->nnz == 0); + for (j = 1; j <= lp->n; j++) lp->col[j]->ptr = NULL; + /* load the new contents of the constraint matrix and build its + row lists */ + if (ne < 0) + xerror("glp_load_matrix: ne = %d; invalid number of constraint" + " coefficients\n", ne); + if (ne > NNZ_MAX) + xerror("glp_load_matrix: ne = %d; too many constraint coeffici" + "ents\n", ne); + for (k = 1; k <= ne; k++) + { /* take indices of new element */ + i = ia[k], j = ja[k]; + /* obtain pointer to i-th row */ + if (!(1 <= i && i <= lp->m)) + xerror("glp_load_matrix: ia[%d] = %d; row index out of rang" + "e\n", k, i); + row = lp->row[i]; + /* obtain pointer to j-th column */ + if (!(1 <= j && j <= lp->n)) + xerror("glp_load_matrix: ja[%d] = %d; column index out of r" + "ange\n", k, j); + col = lp->col[j]; + /* create new element */ + aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++; + aij->row = row; + aij->col = col; + aij->val = ar[k]; + /* add the new element to the beginning of i-th row list */ + aij->r_prev = NULL; + aij->r_next = row->ptr; + if (aij->r_next != NULL) aij->r_next->r_prev = aij; + row->ptr = aij; + } + xassert(lp->nnz == ne); + /* build column lists of the constraint matrix and check elements + with identical indices */ + for (i = 1; i <= lp->m; i++) + { for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { /* obtain pointer to corresponding column */ + col = aij->col; + /* if there is element with identical indices, it can only + be found in the beginning of j-th column list */ + if (col->ptr != NULL && col->ptr->row->i == i) + { for (k = 1; k <= ne; k++) + if (ia[k] == i && ja[k] == col->j) break; + xerror("glp_load_mat: ia[%d] = %d; ja[%d] = %d; duplicat" + "e indices not allowed\n", k, i, k, col->j); + } + /* add the element to the beginning of j-th column list */ + aij->c_prev = NULL; + aij->c_next = col->ptr; + if (aij->c_next != NULL) aij->c_next->c_prev = aij; + col->ptr = aij; + } + } + /* remove zero elements from the constraint matrix */ + for (i = 1; i <= lp->m; i++) + { row = lp->row[i]; + for (aij = row->ptr; aij != NULL; aij = next) + { next = aij->r_next; + if (aij->val == 0.0) + { /* remove the element from the row list */ + if (aij->r_prev == NULL) + row->ptr = next; + else + aij->r_prev->r_next = next; + if (next == NULL) + ; + else + next->r_prev = aij->r_prev; + /* remove the element from the column list */ + if (aij->c_prev == NULL) + aij->col->ptr = aij->c_next; + else + aij->c_prev->c_next = aij->c_next; + if (aij->c_next == NULL) + ; + else + aij->c_next->c_prev = aij->c_prev; + /* return the element to the memory pool */ + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + } + } + } + /* invalidate the basis factorization */ + lp->valid = 0; + return; +} + +/*********************************************************************** +* NAME +* +* glp_check_dup - check for duplicate elements in sparse matrix +* +* SYNOPSIS +* +* int glp_check_dup(int m, int n, int ne, const int ia[], +* const int ja[]); +* +* DESCRIPTION +* +* The routine glp_check_dup checks for duplicate elements (that is, +* elements with identical indices) in a sparse matrix specified in the +* coordinate format. +* +* The parameters m and n specifies, respectively, the number of rows +* and columns in the matrix, m >= 0, n >= 0. +* +* The parameter ne specifies the number of (structurally) non-zero +* elements in the matrix, ne >= 0. +* +* Elements of the matrix are specified as doublets (ia[k],ja[k]) for +* k = 1,...,ne, where ia[k] is a row index, ja[k] is a column index. +* +* The routine glp_check_dup can be used prior to a call to the routine +* glp_load_matrix to check that the constraint matrix to be loaded has +* no duplicate elements. +* +* RETURNS +* +* The routine glp_check_dup returns one of the following values: +* +* 0 - the matrix has no duplicate elements; +* +* -k - indices ia[k] or/and ja[k] are out of range; +* +* +k - element (ia[k],ja[k]) is duplicate. */ + +int glp_check_dup(int m, int n, int ne, const int ia[], const int ja[]) +{ int i, j, k, *ptr, *next, ret; + char *flag; + if (m < 0) + xerror("glp_check_dup: m = %d; invalid parameter\n"); + if (n < 0) + xerror("glp_check_dup: n = %d; invalid parameter\n"); + if (ne < 0) + xerror("glp_check_dup: ne = %d; invalid parameter\n"); + if (ne > 0 && ia == NULL) + xerror("glp_check_dup: ia = %p; invalid parameter\n", ia); + if (ne > 0 && ja == NULL) + xerror("glp_check_dup: ja = %p; invalid parameter\n", ja); + for (k = 1; k <= ne; k++) + { i = ia[k], j = ja[k]; + if (!(1 <= i && i <= m && 1 <= j && j <= n)) + { ret = -k; + goto done; + } + } + if (m == 0 || n == 0) + { ret = 0; + goto done; + } + /* allocate working arrays */ + ptr = xcalloc(1+m, sizeof(int)); + next = xcalloc(1+ne, sizeof(int)); + flag = xcalloc(1+n, sizeof(char)); + /* build row lists */ + for (i = 1; i <= m; i++) + ptr[i] = 0; + for (k = 1; k <= ne; k++) + { i = ia[k]; + next[k] = ptr[i]; + ptr[i] = k; + } + /* clear column flags */ + for (j = 1; j <= n; j++) + flag[j] = 0; + /* check for duplicate elements */ + for (i = 1; i <= m; i++) + { for (k = ptr[i]; k != 0; k = next[k]) + { j = ja[k]; + if (flag[j]) + { /* find first element (i,j) */ + for (k = 1; k <= ne; k++) + if (ia[k] == i && ja[k] == j) break; + xassert(k <= ne); + /* find next (duplicate) element (i,j) */ + for (k++; k <= ne; k++) + if (ia[k] == i && ja[k] == j) break; + xassert(k <= ne); + ret = +k; + goto skip; + } + flag[j] = 1; + } + /* clear column flags */ + for (k = ptr[i]; k != 0; k = next[k]) + flag[ja[k]] = 0; + } + /* no duplicate element found */ + ret = 0; +skip: /* free working arrays */ + xfree(ptr); + xfree(next); + xfree(flag); +done: return ret; +} + +/*********************************************************************** +* NAME +* +* glp_sort_matrix - sort elements of the constraint matrix +* +* SYNOPSIS +* +* void glp_sort_matrix(glp_prob *P); +* +* DESCRIPTION +* +* The routine glp_sort_matrix sorts elements of the constraint matrix +* rebuilding its row and column linked lists. On exit from the routine +* the constraint matrix is not changed, however, elements in the row +* linked lists become ordered by ascending column indices, and the +* elements in the column linked lists become ordered by ascending row +* indices. */ + +void glp_sort_matrix(glp_prob *P) +{ GLPAIJ *aij; + int i, j; + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_sort_matrix: P = %p; invalid problem object\n", + P); + /* rebuild row linked lists */ + for (i = P->m; i >= 1; i--) + P->row[i]->ptr = NULL; + for (j = P->n; j >= 1; j--) + { for (aij = P->col[j]->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row->i; + aij->r_prev = NULL; + aij->r_next = P->row[i]->ptr; + if (aij->r_next != NULL) aij->r_next->r_prev = aij; + P->row[i]->ptr = aij; + } + } + /* rebuild column linked lists */ + for (j = P->n; j >= 1; j--) + P->col[j]->ptr = NULL; + for (i = P->m; i >= 1; i--) + { for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) + { j = aij->col->j; + aij->c_prev = NULL; + aij->c_next = P->col[j]->ptr; + if (aij->c_next != NULL) aij->c_next->c_prev = aij; + P->col[j]->ptr = aij; + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_del_rows - delete rows from problem object +* +* SYNOPSIS +* +* void glp_del_rows(glp_prob *lp, int nrs, const int num[]); +* +* DESCRIPTION +* +* The routine glp_del_rows deletes rows from the specified problem +* object. Ordinal numbers of rows to be deleted should be placed in +* locations num[1], ..., num[nrs], where nrs > 0. +* +* Note that deleting rows involves changing ordinal numbers of other +* rows remaining in the problem object. New ordinal numbers of the +* remaining rows are assigned under the assumption that the original +* order of rows is not changed. */ + +void glp_del_rows(glp_prob *lp, int nrs, const int num[]) +{ glp_tree *tree = lp->tree; + GLPROW *row; + int i, k, m_new; + /* mark rows to be deleted */ + if (!(1 <= nrs && nrs <= lp->m)) + xerror("glp_del_rows: nrs = %d; invalid number of rows\n", + nrs); + for (k = 1; k <= nrs; k++) + { /* take the number of row to be deleted */ + i = num[k]; + /* obtain pointer to i-th row */ + if (!(1 <= i && i <= lp->m)) + xerror("glp_del_rows: num[%d] = %d; row number out of range" + "\n", k, i); + row = lp->row[i]; + if (tree != NULL && tree->reason != 0) + { if (!(tree->reason == GLP_IROWGEN || + tree->reason == GLP_ICUTGEN)) + xerror("glp_del_rows: operation not allowed\n"); + xassert(tree->curr != NULL); + if (row->level != tree->curr->level) + xerror("glp_del_rows: num[%d] = %d; invalid attempt to d" + "elete row created not in current subproblem\n", k,i); + if (row->stat != GLP_BS) + xerror("glp_del_rows: num[%d] = %d; invalid attempt to d" + "elete active row (constraint)\n", k, i); + tree->reinv = 1; + } + /* check that the row is not marked yet */ + if (row->i == 0) + xerror("glp_del_rows: num[%d] = %d; duplicate row numbers n" + "ot allowed\n", k, i); + /* erase symbolic name assigned to the row */ + glp_set_row_name(lp, i, NULL); + xassert(row->node == NULL); + /* erase corresponding row of the constraint matrix */ + glp_set_mat_row(lp, i, 0, NULL, NULL); + xassert(row->ptr == NULL); + /* mark the row to be deleted */ + row->i = 0; + } + /* delete all marked rows from the row list */ + m_new = 0; + for (i = 1; i <= lp->m; i++) + { /* obtain pointer to i-th row */ + row = lp->row[i]; + /* check if the row is marked */ + if (row->i == 0) + { /* it is marked, delete it */ + dmp_free_atom(lp->pool, row, sizeof(GLPROW)); + } + else + { /* it is not marked; keep it */ + row->i = ++m_new; + lp->row[row->i] = row; + } + } + /* set new number of rows */ + lp->m = m_new; + /* invalidate the basis factorization */ + lp->valid = 0; + return; +} + +/*********************************************************************** +* NAME +* +* glp_del_cols - delete columns from problem object +* +* SYNOPSIS +* +* void glp_del_cols(glp_prob *lp, int ncs, const int num[]); +* +* DESCRIPTION +* +* The routine glp_del_cols deletes columns from the specified problem +* object. Ordinal numbers of columns to be deleted should be placed in +* locations num[1], ..., num[ncs], where ncs > 0. +* +* Note that deleting columns involves changing ordinal numbers of +* other columns remaining in the problem object. New ordinal numbers +* of the remaining columns are assigned under the assumption that the +* original order of columns is not changed. */ + +void glp_del_cols(glp_prob *lp, int ncs, const int num[]) +{ glp_tree *tree = lp->tree; + GLPCOL *col; + int j, k, n_new; + if (tree != NULL && tree->reason != 0) + xerror("glp_del_cols: operation not allowed\n"); + /* mark columns to be deleted */ + if (!(1 <= ncs && ncs <= lp->n)) + xerror("glp_del_cols: ncs = %d; invalid number of columns\n", + ncs); + for (k = 1; k <= ncs; k++) + { /* take the number of column to be deleted */ + j = num[k]; + /* obtain pointer to j-th column */ + if (!(1 <= j && j <= lp->n)) + xerror("glp_del_cols: num[%d] = %d; column number out of ra" + "nge", k, j); + col = lp->col[j]; + /* check that the column is not marked yet */ + if (col->j == 0) + xerror("glp_del_cols: num[%d] = %d; duplicate column number" + "s not allowed\n", k, j); + /* erase symbolic name assigned to the column */ + glp_set_col_name(lp, j, NULL); + xassert(col->node == NULL); + /* erase corresponding column of the constraint matrix */ + glp_set_mat_col(lp, j, 0, NULL, NULL); + xassert(col->ptr == NULL); + /* mark the column to be deleted */ + col->j = 0; + /* if it is basic, invalidate the basis factorization */ + if (col->stat == GLP_BS) lp->valid = 0; + } + /* delete all marked columns from the column list */ + n_new = 0; + for (j = 1; j <= lp->n; j++) + { /* obtain pointer to j-th column */ + col = lp->col[j]; + /* check if the column is marked */ + if (col->j == 0) + { /* it is marked; delete it */ + dmp_free_atom(lp->pool, col, sizeof(GLPCOL)); + } + else + { /* it is not marked; keep it */ + col->j = ++n_new; + lp->col[col->j] = col; + } + } + /* set new number of columns */ + lp->n = n_new; + /* if the basis header is still valid, adjust it */ + if (lp->valid) + { int m = lp->m; + int *head = lp->head; + for (j = 1; j <= n_new; j++) + { k = lp->col[j]->bind; + if (k != 0) + { xassert(1 <= k && k <= m); + head[k] = m + j; + } + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_copy_prob - copy problem object content +* +* SYNOPSIS +* +* void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names); +* +* DESCRIPTION +* +* The routine glp_copy_prob copies the content of the problem object +* prob to the problem object dest. +* +* The parameter names is a flag. If it is non-zero, the routine also +* copies all symbolic names; otherwise, if it is zero, symbolic names +* are not copied. */ + +void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names) +{ glp_tree *tree = dest->tree; + glp_bfcp bfcp; + int i, j, len, *ind; + double *val; + if (tree != NULL && tree->reason != 0) + xerror("glp_copy_prob: operation not allowed\n"); + if (dest == prob) + xerror("glp_copy_prob: copying problem object to itself not al" + "lowed\n"); + if (!(names == GLP_ON || names == GLP_OFF)) + xerror("glp_copy_prob: names = %d; invalid parameter\n", + names); + glp_erase_prob(dest); + if (names && prob->name != NULL) + glp_set_prob_name(dest, prob->name); + if (names && prob->obj != NULL) + glp_set_obj_name(dest, prob->obj); + dest->dir = prob->dir; + dest->c0 = prob->c0; + if (prob->m > 0) + glp_add_rows(dest, prob->m); + if (prob->n > 0) + glp_add_cols(dest, prob->n); + glp_get_bfcp(prob, &bfcp); + glp_set_bfcp(dest, &bfcp); + dest->pbs_stat = prob->pbs_stat; + dest->dbs_stat = prob->dbs_stat; + dest->obj_val = prob->obj_val; + dest->some = prob->some; + dest->ipt_stat = prob->ipt_stat; + dest->ipt_obj = prob->ipt_obj; + dest->mip_stat = prob->mip_stat; + dest->mip_obj = prob->mip_obj; + for (i = 1; i <= prob->m; i++) + { GLPROW *to = dest->row[i]; + GLPROW *from = prob->row[i]; + if (names && from->name != NULL) + glp_set_row_name(dest, i, from->name); + to->type = from->type; + to->lb = from->lb; + to->ub = from->ub; + to->rii = from->rii; + to->stat = from->stat; + to->prim = from->prim; + to->dual = from->dual; + to->pval = from->pval; + to->dval = from->dval; + to->mipx = from->mipx; + } + ind = xcalloc(1+prob->m, sizeof(int)); + val = xcalloc(1+prob->m, sizeof(double)); + for (j = 1; j <= prob->n; j++) + { GLPCOL *to = dest->col[j]; + GLPCOL *from = prob->col[j]; + if (names && from->name != NULL) + glp_set_col_name(dest, j, from->name); + to->kind = from->kind; + to->type = from->type; + to->lb = from->lb; + to->ub = from->ub; + to->coef = from->coef; + len = glp_get_mat_col(prob, j, ind, val); + glp_set_mat_col(dest, j, len, ind, val); + to->sjj = from->sjj; + to->stat = from->stat; + to->prim = from->prim; + to->dual = from->dual; + to->pval = from->pval; + to->dval = from->dval; + to->mipx = from->mipx; + } + xfree(ind); + xfree(val); + return; +} + +/*********************************************************************** +* NAME +* +* glp_erase_prob - erase problem object content +* +* SYNOPSIS +* +* void glp_erase_prob(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_erase_prob erases the content of the specified +* problem object. The effect of this operation is the same as if the +* problem object would be deleted with the routine glp_delete_prob and +* then created anew with the routine glp_create_prob, with exception +* that the handle (pointer) to the problem object remains valid. */ + +static void delete_prob(glp_prob *lp); + +void glp_erase_prob(glp_prob *lp) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_erase_prob: operation not allowed\n"); + delete_prob(lp); + create_prob(lp); + return; +} + +/*********************************************************************** +* NAME +* +* glp_delete_prob - delete problem object +* +* SYNOPSIS +* +* void glp_delete_prob(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_delete_prob deletes the specified problem object and +* frees all the memory allocated to it. */ + +static void delete_prob(glp_prob *lp) +{ lp->magic = 0x3F3F3F3F; + dmp_delete_pool(lp->pool); +#if 0 /* 17/XI-2009 */ + xfree(lp->cps); +#else + if (lp->parms != NULL) xfree(lp->parms); +#endif + xassert(lp->tree == NULL); +#if 0 + if (lp->cwa != NULL) xfree(lp->cwa); +#endif + xfree(lp->row); + xfree(lp->col); + if (lp->r_tree != NULL) avl_delete_tree(lp->r_tree); + if (lp->c_tree != NULL) avl_delete_tree(lp->c_tree); + xfree(lp->head); + if (lp->bfcp != NULL) xfree(lp->bfcp); + if (lp->bfd != NULL) bfd_delete_it(lp->bfd); + return; +} + +void glp_delete_prob(glp_prob *lp) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_delete_prob: operation not allowed\n"); + delete_prob(lp); + xfree(lp); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi02.c b/resources/3rdparty/glpk-4.53/src/glpapi02.c new file mode 100644 index 000000000..5b74aab95 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi02.c @@ -0,0 +1,492 @@ +/* glpapi02.c (problem retrieving routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_get_prob_name - retrieve problem name +* +* SYNOPSIS +* +* const char *glp_get_prob_name(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_prob_name returns a pointer to an internal +* buffer, which contains symbolic name of the problem. However, if the +* problem has no assigned name, the routine returns NULL. */ + +const char *glp_get_prob_name(glp_prob *lp) +{ char *name; + name = lp->name; + return name; +} + +/*********************************************************************** +* NAME +* +* glp_get_obj_name - retrieve objective function name +* +* SYNOPSIS +* +* const char *glp_get_obj_name(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_obj_name returns a pointer to an internal +* buffer, which contains a symbolic name of the objective function. +* However, if the objective function has no assigned name, the routine +* returns NULL. */ + +const char *glp_get_obj_name(glp_prob *lp) +{ char *name; + name = lp->obj; + return name; +} + +/*********************************************************************** +* NAME +* +* glp_get_obj_dir - retrieve optimization direction flag +* +* SYNOPSIS +* +* int glp_get_obj_dir(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_obj_dir returns the optimization direction flag +* (i.e. "sense" of the objective function): +* +* GLP_MIN - minimization; +* GLP_MAX - maximization. */ + +int glp_get_obj_dir(glp_prob *lp) +{ int dir = lp->dir; + return dir; +} + +/*********************************************************************** +* NAME +* +* glp_get_num_rows - retrieve number of rows +* +* SYNOPSIS +* +* int glp_get_num_rows(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_num_rows returns the current number of rows in +* the specified problem object. */ + +int glp_get_num_rows(glp_prob *lp) +{ int m = lp->m; + return m; +} + +/*********************************************************************** +* NAME +* +* glp_get_num_cols - retrieve number of columns +* +* SYNOPSIS +* +* int glp_get_num_cols(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_num_cols returns the current number of columns +* in the specified problem object. */ + +int glp_get_num_cols(glp_prob *lp) +{ int n = lp->n; + return n; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_name - retrieve row name +* +* SYNOPSIS +* +* const char *glp_get_row_name(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_name returns a pointer to an internal +* buffer, which contains symbolic name of i-th row. However, if i-th +* row has no assigned name, the routine returns NULL. */ + +const char *glp_get_row_name(glp_prob *lp, int i) +{ char *name; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_name: i = %d; row number out of range\n", + i); + name = lp->row[i]->name; + return name; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_name - retrieve column name +* +* SYNOPSIS +* +* const char *glp_get_col_name(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_name returns a pointer to an internal +* buffer, which contains symbolic name of j-th column. However, if j-th +* column has no assigned name, the routine returns NULL. */ + +const char *glp_get_col_name(glp_prob *lp, int j) +{ char *name; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_name: j = %d; column number out of range\n" + , j); + name = lp->col[j]->name; + return name; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_type - retrieve row type +* +* SYNOPSIS +* +* int glp_get_row_type(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_type returns the type of i-th row, i.e. the +* type of corresponding auxiliary variable, as follows: +* +* GLP_FR - free (unbounded) variable; +* GLP_LO - variable with lower bound; +* GLP_UP - variable with upper bound; +* GLP_DB - double-bounded variable; +* GLP_FX - fixed variable. */ + +int glp_get_row_type(glp_prob *lp, int i) +{ if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_type: i = %d; row number out of range\n", + i); + return lp->row[i]->type; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_lb - retrieve row lower bound +* +* SYNOPSIS +* +* double glp_get_row_lb(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_lb returns the lower bound of i-th row, i.e. +* the lower bound of corresponding auxiliary variable. However, if the +* row has no lower bound, the routine returns -DBL_MAX. */ + +double glp_get_row_lb(glp_prob *lp, int i) +{ double lb; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_lb: i = %d; row number out of range\n", i); + switch (lp->row[i]->type) + { case GLP_FR: + case GLP_UP: + lb = -DBL_MAX; break; + case GLP_LO: + case GLP_DB: + case GLP_FX: + lb = lp->row[i]->lb; break; + default: + xassert(lp != lp); + } + return lb; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_ub - retrieve row upper bound +* +* SYNOPSIS +* +* double glp_get_row_ub(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_ub returns the upper bound of i-th row, i.e. +* the upper bound of corresponding auxiliary variable. However, if the +* row has no upper bound, the routine returns +DBL_MAX. */ + +double glp_get_row_ub(glp_prob *lp, int i) +{ double ub; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_ub: i = %d; row number out of range\n", i); + switch (lp->row[i]->type) + { case GLP_FR: + case GLP_LO: + ub = +DBL_MAX; break; + case GLP_UP: + case GLP_DB: + case GLP_FX: + ub = lp->row[i]->ub; break; + default: + xassert(lp != lp); + } + return ub; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_type - retrieve column type +* +* SYNOPSIS +* +* int glp_get_col_type(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_type returns the type of j-th column, i.e. +* the type of corresponding structural variable, as follows: +* +* GLP_FR - free (unbounded) variable; +* GLP_LO - variable with lower bound; +* GLP_UP - variable with upper bound; +* GLP_DB - double-bounded variable; +* GLP_FX - fixed variable. */ + +int glp_get_col_type(glp_prob *lp, int j) +{ if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_type: j = %d; column number out of range\n" + , j); + return lp->col[j]->type; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_lb - retrieve column lower bound +* +* SYNOPSIS +* +* double glp_get_col_lb(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_lb returns the lower bound of j-th column, +* i.e. the lower bound of corresponding structural variable. However, +* if the column has no lower bound, the routine returns -DBL_MAX. */ + +double glp_get_col_lb(glp_prob *lp, int j) +{ double lb; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_lb: j = %d; column number out of range\n", + j); + switch (lp->col[j]->type) + { case GLP_FR: + case GLP_UP: + lb = -DBL_MAX; break; + case GLP_LO: + case GLP_DB: + case GLP_FX: + lb = lp->col[j]->lb; break; + default: + xassert(lp != lp); + } + return lb; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_ub - retrieve column upper bound +* +* SYNOPSIS +* +* double glp_get_col_ub(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_ub returns the upper bound of j-th column, +* i.e. the upper bound of corresponding structural variable. However, +* if the column has no upper bound, the routine returns +DBL_MAX. */ + +double glp_get_col_ub(glp_prob *lp, int j) +{ double ub; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_ub: j = %d; column number out of range\n", + j); + switch (lp->col[j]->type) + { case GLP_FR: + case GLP_LO: + ub = +DBL_MAX; break; + case GLP_UP: + case GLP_DB: + case GLP_FX: + ub = lp->col[j]->ub; break; + default: + xassert(lp != lp); + } + return ub; +} + +/*********************************************************************** +* NAME +* +* glp_get_obj_coef - retrieve obj. coefficient or constant term +* +* SYNOPSIS +* +* double glp_get_obj_coef(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_obj_coef returns the objective coefficient at +* j-th structural variable (column) of the specified problem object. +* +* If the parameter j is zero, the routine returns the constant term +* ("shift") of the objective function. */ + +double glp_get_obj_coef(glp_prob *lp, int j) +{ if (!(0 <= j && j <= lp->n)) + xerror("glp_get_obj_coef: j = %d; column number out of range\n" + , j); + return j == 0 ? lp->c0 : lp->col[j]->coef; +} + +/*********************************************************************** +* NAME +* +* glp_get_num_nz - retrieve number of constraint coefficients +* +* SYNOPSIS +* +* int glp_get_num_nz(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_num_nz returns the number of (non-zero) elements +* in the constraint matrix of the specified problem object. */ + +int glp_get_num_nz(glp_prob *lp) +{ int nnz = lp->nnz; + return nnz; +} + +/*********************************************************************** +* NAME +* +* glp_get_mat_row - retrieve row of the constraint matrix +* +* SYNOPSIS +* +* int glp_get_mat_row(glp_prob *lp, int i, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_get_mat_row scans (non-zero) elements of i-th row +* of the constraint matrix of the specified problem object and stores +* their column indices and numeric values to locations ind[1], ..., +* ind[len] and val[1], ..., val[len], respectively, where 0 <= len <= n +* is the number of elements in i-th row, n is the number of columns. +* +* The parameter ind and/or val can be specified as NULL, in which case +* corresponding information is not stored. +* +* RETURNS +* +* The routine glp_get_mat_row returns the length len, i.e. the number +* of (non-zero) elements in i-th row. */ + +int glp_get_mat_row(glp_prob *lp, int i, int ind[], double val[]) +{ GLPAIJ *aij; + int len; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_mat_row: i = %d; row number out of range\n", + i); + len = 0; + for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { len++; + if (ind != NULL) ind[len] = aij->col->j; + if (val != NULL) val[len] = aij->val; + } + xassert(len <= lp->n); + return len; +} + +/*********************************************************************** +* NAME +* +* glp_get_mat_col - retrieve column of the constraint matrix +* +* SYNOPSIS +* +* int glp_get_mat_col(glp_prob *lp, int j, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_get_mat_col scans (non-zero) elements of j-th column +* of the constraint matrix of the specified problem object and stores +* their row indices and numeric values to locations ind[1], ..., +* ind[len] and val[1], ..., val[len], respectively, where 0 <= len <= m +* is the number of elements in j-th column, m is the number of rows. +* +* The parameter ind or/and val can be specified as NULL, in which case +* corresponding information is not stored. +* +* RETURNS +* +* The routine glp_get_mat_col returns the length len, i.e. the number +* of (non-zero) elements in j-th column. */ + +int glp_get_mat_col(glp_prob *lp, int j, int ind[], double val[]) +{ GLPAIJ *aij; + int len; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_mat_col: j = %d; column number out of range\n", + j); + len = 0; + for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) + { len++; + if (ind != NULL) ind[len] = aij->row->i; + if (val != NULL) val[len] = aij->val; + } + xassert(len <= lp->m); + return len; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi03.c b/resources/3rdparty/glpk-4.53/src/glpapi03.c new file mode 100644 index 000000000..daf9174af --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi03.c @@ -0,0 +1,167 @@ +/* glpapi03.c (row and column searching routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_create_index - create the name index +* +* SYNOPSIS +* +* void glp_create_index(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_create_index creates the name index for the +* specified problem object. The name index is an auxiliary data +* structure, which is intended to quickly (i.e. for logarithmic time) +* find rows and columns by their names. +* +* This routine can be called at any time. If the name index already +* exists, the routine does nothing. */ + +void glp_create_index(glp_prob *lp) +{ GLPROW *row; + GLPCOL *col; + int i, j; + /* create row name index */ + if (lp->r_tree == NULL) + { lp->r_tree = avl_create_tree(avl_strcmp, NULL); + for (i = 1; i <= lp->m; i++) + { row = lp->row[i]; + xassert(row->node == NULL); + if (row->name != NULL) + { row->node = avl_insert_node(lp->r_tree, row->name); + avl_set_node_link(row->node, row); + } + } + } + /* create column name index */ + if (lp->c_tree == NULL) + { lp->c_tree = avl_create_tree(avl_strcmp, NULL); + for (j = 1; j <= lp->n; j++) + { col = lp->col[j]; + xassert(col->node == NULL); + if (col->name != NULL) + { col->node = avl_insert_node(lp->c_tree, col->name); + avl_set_node_link(col->node, col); + } + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_find_row - find row by its name +* +* SYNOPSIS +* +* int glp_find_row(glp_prob *lp, const char *name); +* +* RETURNS +* +* The routine glp_find_row returns the ordinal number of a row, +* which is assigned (by the routine glp_set_row_name) the specified +* symbolic name. If no such row exists, the routine returns 0. */ + +int glp_find_row(glp_prob *lp, const char *name) +{ AVLNODE *node; + int i = 0; + if (lp->r_tree == NULL) + xerror("glp_find_row: row name index does not exist\n"); + if (!(name == NULL || name[0] == '\0' || strlen(name) > 255)) + { node = avl_find_node(lp->r_tree, name); + if (node != NULL) + i = ((GLPROW *)avl_get_node_link(node))->i; + } + return i; +} + +/*********************************************************************** +* NAME +* +* glp_find_col - find column by its name +* +* SYNOPSIS +* +* int glp_find_col(glp_prob *lp, const char *name); +* +* RETURNS +* +* The routine glp_find_col returns the ordinal number of a column, +* which is assigned (by the routine glp_set_col_name) the specified +* symbolic name. If no such column exists, the routine returns 0. */ + +int glp_find_col(glp_prob *lp, const char *name) +{ AVLNODE *node; + int j = 0; + if (lp->c_tree == NULL) + xerror("glp_find_col: column name index does not exist\n"); + if (!(name == NULL || name[0] == '\0' || strlen(name) > 255)) + { node = avl_find_node(lp->c_tree, name); + if (node != NULL) + j = ((GLPCOL *)avl_get_node_link(node))->j; + } + return j; +} + +/*********************************************************************** +* NAME +* +* glp_delete_index - delete the name index +* +* SYNOPSIS +* +* void glp_delete_index(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_delete_index deletes the name index previously +* created by the routine glp_create_index and frees the memory +* allocated to this auxiliary data structure. +* +* This routine can be called at any time. If the name index does not +* exist, the routine does nothing. */ + +void glp_delete_index(glp_prob *lp) +{ int i, j; + /* delete row name index */ + if (lp->r_tree != NULL) + { for (i = 1; i <= lp->m; i++) lp->row[i]->node = NULL; + avl_delete_tree(lp->r_tree), lp->r_tree = NULL; + } + /* delete column name index */ + if (lp->c_tree != NULL) + { for (j = 1; j <= lp->n; j++) lp->col[j]->node = NULL; + avl_delete_tree(lp->c_tree), lp->c_tree = NULL; + } + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi04.c b/resources/3rdparty/glpk-4.53/src/glpapi04.c new file mode 100644 index 000000000..adabb02c1 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi04.c @@ -0,0 +1,157 @@ +/* glpapi04.c (problem scaling routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_set_rii - set (change) row scale factor +* +* SYNOPSIS +* +* void glp_set_rii(glp_prob *lp, int i, double rii); +* +* DESCRIPTION +* +* The routine glp_set_rii sets (changes) the scale factor r[i,i] for +* i-th row of the specified problem object. */ + +void glp_set_rii(glp_prob *lp, int i, double rii) +{ if (!(1 <= i && i <= lp->m)) + xerror("glp_set_rii: i = %d; row number out of range\n", i); + if (rii <= 0.0) + xerror("glp_set_rii: i = %d; rii = %g; invalid scale factor\n", + i, rii); + if (lp->valid && lp->row[i]->rii != rii) + { GLPAIJ *aij; + for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { if (aij->col->stat == GLP_BS) + { /* invalidate the basis factorization */ + lp->valid = 0; + break; + } + } + } + lp->row[i]->rii = rii; + return; +} + +/*********************************************************************** +* NAME +* +* glp_set sjj - set (change) column scale factor +* +* SYNOPSIS +* +* void glp_set_sjj(glp_prob *lp, int j, double sjj); +* +* DESCRIPTION +* +* The routine glp_set_sjj sets (changes) the scale factor s[j,j] for +* j-th column of the specified problem object. */ + +void glp_set_sjj(glp_prob *lp, int j, double sjj) +{ if (!(1 <= j && j <= lp->n)) + xerror("glp_set_sjj: j = %d; column number out of range\n", j); + if (sjj <= 0.0) + xerror("glp_set_sjj: j = %d; sjj = %g; invalid scale factor\n", + j, sjj); + if (lp->valid && lp->col[j]->sjj != sjj && lp->col[j]->stat == + GLP_BS) + { /* invalidate the basis factorization */ + lp->valid = 0; + } + lp->col[j]->sjj = sjj; + return; +} + +/*********************************************************************** +* NAME +* +* glp_get_rii - retrieve row scale factor +* +* SYNOPSIS +* +* double glp_get_rii(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_rii returns current scale factor r[i,i] for i-th +* row of the specified problem object. */ + +double glp_get_rii(glp_prob *lp, int i) +{ if (!(1 <= i && i <= lp->m)) + xerror("glp_get_rii: i = %d; row number out of range\n", i); + return lp->row[i]->rii; +} + +/*********************************************************************** +* NAME +* +* glp_get_sjj - retrieve column scale factor +* +* SYNOPSIS +* +* double glp_get_sjj(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_sjj returns current scale factor s[j,j] for j-th +* column of the specified problem object. */ + +double glp_get_sjj(glp_prob *lp, int j) +{ if (!(1 <= j && j <= lp->n)) + xerror("glp_get_sjj: j = %d; column number out of range\n", j); + return lp->col[j]->sjj; +} + +/*********************************************************************** +* NAME +* +* glp_unscale_prob - unscale problem data +* +* SYNOPSIS +* +* void glp_unscale_prob(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_unscale_prob performs unscaling of problem data for +* the specified problem object. +* +* "Unscaling" means replacing the current scaling matrices R and S by +* unity matrices that cancels the scaling effect. */ + +void glp_unscale_prob(glp_prob *lp) +{ int m = glp_get_num_rows(lp); + int n = glp_get_num_cols(lp); + int i, j; + for (i = 1; i <= m; i++) glp_set_rii(lp, i, 1.0); + for (j = 1; j <= n; j++) glp_set_sjj(lp, j, 1.0); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi05.c b/resources/3rdparty/glpk-4.53/src/glpapi05.c new file mode 100644 index 000000000..b18845522 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi05.c @@ -0,0 +1,169 @@ +/* glpapi05.c (LP basis constructing routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_set_row_stat - set (change) row status +* +* SYNOPSIS +* +* void glp_set_row_stat(glp_prob *lp, int i, int stat); +* +* DESCRIPTION +* +* The routine glp_set_row_stat sets (changes) status of the auxiliary +* variable associated with i-th row. +* +* The new status of the auxiliary variable should be specified by the +* parameter stat as follows: +* +* GLP_BS - basic variable; +* GLP_NL - non-basic variable; +* GLP_NU - non-basic variable on its upper bound; if the variable is +* not double-bounded, this means the same as GLP_NL (only in +* case of this routine); +* GLP_NF - the same as GLP_NL (only in case of this routine); +* GLP_NS - the same as GLP_NL (only in case of this routine). */ + +void glp_set_row_stat(glp_prob *lp, int i, int stat) +{ GLPROW *row; + if (!(1 <= i && i <= lp->m)) + xerror("glp_set_row_stat: i = %d; row number out of range\n", + i); + if (!(stat == GLP_BS || stat == GLP_NL || stat == GLP_NU || + stat == GLP_NF || stat == GLP_NS)) + xerror("glp_set_row_stat: i = %d; stat = %d; invalid status\n", + i, stat); + row = lp->row[i]; + if (stat != GLP_BS) + { switch (row->type) + { case GLP_FR: stat = GLP_NF; break; + case GLP_LO: stat = GLP_NL; break; + case GLP_UP: stat = GLP_NU; break; + case GLP_DB: if (stat != GLP_NU) stat = GLP_NL; break; + case GLP_FX: stat = GLP_NS; break; + default: xassert(row != row); + } + } + if (row->stat == GLP_BS && stat != GLP_BS || + row->stat != GLP_BS && stat == GLP_BS) + { /* invalidate the basis factorization */ + lp->valid = 0; + } + row->stat = stat; + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_col_stat - set (change) column status +* +* SYNOPSIS +* +* void glp_set_col_stat(glp_prob *lp, int j, int stat); +* +* DESCRIPTION +* +* The routine glp_set_col_stat sets (changes) status of the structural +* variable associated with j-th column. +* +* The new status of the structural variable should be specified by the +* parameter stat as follows: +* +* GLP_BS - basic variable; +* GLP_NL - non-basic variable; +* GLP_NU - non-basic variable on its upper bound; if the variable is +* not double-bounded, this means the same as GLP_NL (only in +* case of this routine); +* GLP_NF - the same as GLP_NL (only in case of this routine); +* GLP_NS - the same as GLP_NL (only in case of this routine). */ + +void glp_set_col_stat(glp_prob *lp, int j, int stat) +{ GLPCOL *col; + if (!(1 <= j && j <= lp->n)) + xerror("glp_set_col_stat: j = %d; column number out of range\n" + , j); + if (!(stat == GLP_BS || stat == GLP_NL || stat == GLP_NU || + stat == GLP_NF || stat == GLP_NS)) + xerror("glp_set_col_stat: j = %d; stat = %d; invalid status\n", + j, stat); + col = lp->col[j]; + if (stat != GLP_BS) + { switch (col->type) + { case GLP_FR: stat = GLP_NF; break; + case GLP_LO: stat = GLP_NL; break; + case GLP_UP: stat = GLP_NU; break; + case GLP_DB: if (stat != GLP_NU) stat = GLP_NL; break; + case GLP_FX: stat = GLP_NS; break; + default: xassert(col != col); + } + } + if (col->stat == GLP_BS && stat != GLP_BS || + col->stat != GLP_BS && stat == GLP_BS) + { /* invalidate the basis factorization */ + lp->valid = 0; + } + col->stat = stat; + return; +} + +/*********************************************************************** +* NAME +* +* glp_std_basis - construct standard initial LP basis +* +* SYNOPSIS +* +* void glp_std_basis(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_std_basis builds the "standard" (trivial) initial +* basis for the specified problem object. +* +* In the "standard" basis all auxiliary variables are basic, and all +* structural variables are non-basic. */ + +void glp_std_basis(glp_prob *lp) +{ int i, j; + /* make all auxiliary variables basic */ + for (i = 1; i <= lp->m; i++) + glp_set_row_stat(lp, i, GLP_BS); + /* make all structural variables non-basic */ + for (j = 1; j <= lp->n; j++) + { GLPCOL *col = lp->col[j]; + if (col->type == GLP_DB && fabs(col->lb) > fabs(col->ub)) + glp_set_col_stat(lp, j, GLP_NU); + else + glp_set_col_stat(lp, j, GLP_NL); + } + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi06.c b/resources/3rdparty/glpk-4.53/src/glpapi06.c new file mode 100644 index 000000000..53a2f9340 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi06.c @@ -0,0 +1,822 @@ +/* glpapi06.c (simplex method routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" +#include "glpnpp.h" +#include "glpspx.h" + +/*********************************************************************** +* NAME +* +* glp_simplex - solve LP problem with the simplex method +* +* SYNOPSIS +* +* int glp_simplex(glp_prob *P, const glp_smcp *parm); +* +* DESCRIPTION +* +* The routine glp_simplex is a driver to the LP solver based on the +* simplex method. This routine retrieves problem data from the +* specified problem object, calls the solver to solve the problem +* instance, and stores results of computations back into the problem +* object. +* +* The simplex solver has a set of control parameters. Values of the +* control parameters can be passed in a structure glp_smcp, which the +* parameter parm points to. +* +* The parameter parm can be specified as NULL, in which case the LP +* solver uses default settings. +* +* RETURNS +* +* 0 The LP problem instance has been successfully solved. This code +* does not necessarily mean that the solver has found optimal +* solution. It only means that the solution process was successful. +* +* GLP_EBADB +* Unable to start the search, because the initial basis specified +* in the problem object is invalid--the number of basic (auxiliary +* and structural) variables is not the same as the number of rows in +* the problem object. +* +* GLP_ESING +* Unable to start the search, because the basis matrix correspodning +* to the initial basis is singular within the working precision. +* +* GLP_ECOND +* Unable to start the search, because the basis matrix correspodning +* to the initial basis is ill-conditioned, i.e. its condition number +* is too large. +* +* GLP_EBOUND +* Unable to start the search, because some double-bounded variables +* have incorrect bounds. +* +* GLP_EFAIL +* The search was prematurely terminated due to the solver failure. +* +* GLP_EOBJLL +* The search was prematurely terminated, because the objective +* function being maximized has reached its lower limit and continues +* decreasing (dual simplex only). +* +* GLP_EOBJUL +* The search was prematurely terminated, because the objective +* function being minimized has reached its upper limit and continues +* increasing (dual simplex only). +* +* GLP_EITLIM +* The search was prematurely terminated, because the simplex +* iteration limit has been exceeded. +* +* GLP_ETMLIM +* The search was prematurely terminated, because the time limit has +* been exceeded. +* +* GLP_ENOPFS +* The LP problem instance has no primal feasible solution (only if +* the LP presolver is used). +* +* GLP_ENODFS +* The LP problem instance has no dual feasible solution (only if the +* LP presolver is used). */ + +static void trivial_lp(glp_prob *P, const glp_smcp *parm) +{ /* solve trivial LP which has empty constraint matrix */ + GLPROW *row; + GLPCOL *col; + int i, j; + double p_infeas, d_infeas, zeta; + P->valid = 0; + P->pbs_stat = P->dbs_stat = GLP_FEAS; + P->obj_val = P->c0; + P->some = 0; + p_infeas = d_infeas = 0.0; + /* make all auxiliary variables basic */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + row->stat = GLP_BS; + row->prim = row->dual = 0.0; + /* check primal feasibility */ + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + { /* row has lower bound */ + if (row->lb > + parm->tol_bnd) + { P->pbs_stat = GLP_NOFEAS; + if (P->some == 0 && parm->meth != GLP_PRIMAL) + P->some = i; + } + if (p_infeas < + row->lb) + p_infeas = + row->lb; + } + if (row->type == GLP_UP || row->type == GLP_DB || + row->type == GLP_FX) + { /* row has upper bound */ + if (row->ub < - parm->tol_bnd) + { P->pbs_stat = GLP_NOFEAS; + if (P->some == 0 && parm->meth != GLP_PRIMAL) + P->some = i; + } + if (p_infeas < - row->ub) + p_infeas = - row->ub; + } + } + /* determine scale factor for the objective row */ + zeta = 1.0; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (zeta < fabs(col->coef)) zeta = fabs(col->coef); + } + zeta = (P->dir == GLP_MIN ? +1.0 : -1.0) / zeta; + /* make all structural variables non-basic */ + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->type == GLP_FR) + col->stat = GLP_NF, col->prim = 0.0; + else if (col->type == GLP_LO) +lo: col->stat = GLP_NL, col->prim = col->lb; + else if (col->type == GLP_UP) +up: col->stat = GLP_NU, col->prim = col->ub; + else if (col->type == GLP_DB) + { if (zeta * col->coef > 0.0) + goto lo; + else if (zeta * col->coef < 0.0) + goto up; + else if (fabs(col->lb) <= fabs(col->ub)) + goto lo; + else + goto up; + } + else if (col->type == GLP_FX) + col->stat = GLP_NS, col->prim = col->lb; + col->dual = col->coef; + P->obj_val += col->coef * col->prim; + /* check dual feasibility */ + if (col->type == GLP_FR || col->type == GLP_LO) + { /* column has no upper bound */ + if (zeta * col->dual < - parm->tol_dj) + { P->dbs_stat = GLP_NOFEAS; + if (P->some == 0 && parm->meth == GLP_PRIMAL) + P->some = P->m + j; + } + if (d_infeas < - zeta * col->dual) + d_infeas = - zeta * col->dual; + } + if (col->type == GLP_FR || col->type == GLP_UP) + { /* column has no lower bound */ + if (zeta * col->dual > + parm->tol_dj) + { P->dbs_stat = GLP_NOFEAS; + if (P->some == 0 && parm->meth == GLP_PRIMAL) + P->some = P->m + j; + } + if (d_infeas < + zeta * col->dual) + d_infeas = + zeta * col->dual; + } + } + /* simulate the simplex solver output */ + if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0) + { xprintf("~%6d: obj = %17.9e infeas = %10.3e\n", P->it_cnt, + P->obj_val, parm->meth == GLP_PRIMAL ? p_infeas : d_infeas); + } + if (parm->msg_lev >= GLP_MSG_ALL && parm->out_dly == 0) + { if (P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS) + xprintf("OPTIMAL SOLUTION FOUND\n"); + else if (P->pbs_stat == GLP_NOFEAS) + xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); + else if (parm->meth == GLP_PRIMAL) + xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n"); + else + xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n"); + } + return; +} + +static int solve_lp(glp_prob *P, const glp_smcp *parm) +{ /* solve LP directly without using the preprocessor */ + int ret; + if (!glp_bf_exists(P)) + { ret = glp_factorize(P); + if (ret == 0) + ; + else if (ret == GLP_EBADB) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_simplex: initial basis is invalid\n"); + } + else if (ret == GLP_ESING) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_simplex: initial basis is singular\n"); + } + else if (ret == GLP_ECOND) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf( + "glp_simplex: initial basis is ill-conditioned\n"); + } + else + xassert(ret != ret); + if (ret != 0) goto done; + } + if (parm->meth == GLP_PRIMAL) + ret = spx_primal(P, parm); + else if (parm->meth == GLP_DUALP) + { ret = spx_dual(P, parm); + if (ret == GLP_EFAIL && P->valid) + ret = spx_primal(P, parm); + } + else if (parm->meth == GLP_DUAL) + ret = spx_dual(P, parm); + else + xassert(parm != parm); +done: return ret; +} + +static int preprocess_and_solve_lp(glp_prob *P, const glp_smcp *parm) +{ /* solve LP using the preprocessor */ + NPP *npp; + glp_prob *lp = NULL; + glp_bfcp bfcp; + int ret; + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Preprocessing...\n"); + /* create preprocessor workspace */ + npp = npp_create_wksp(); + /* load original problem into the preprocessor workspace */ + npp_load_prob(npp, P, GLP_OFF, GLP_SOL, GLP_OFF); + /* process LP prior to applying primal/dual simplex method */ + ret = npp_simplex(npp, parm); + if (ret == 0) + ; + else if (ret == GLP_ENOPFS) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n"); + } + else if (ret == GLP_ENODFS) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n"); + } + else + xassert(ret != ret); + if (ret != 0) goto done; + /* build transformed LP */ + lp = glp_create_prob(); + npp_build_prob(npp, lp); + /* if the transformed LP is empty, it has empty solution, which + is optimal */ + if (lp->m == 0 && lp->n == 0) + { lp->pbs_stat = lp->dbs_stat = GLP_FEAS; + lp->obj_val = lp->c0; + if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0) + { xprintf("~%6d: obj = %17.9e infeas = %10.3e\n", P->it_cnt, + lp->obj_val, 0.0); + } + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("OPTIMAL SOLUTION FOUND BY LP PREPROCESSOR\n"); + goto post; + } + if (parm->msg_lev >= GLP_MSG_ALL) + { xprintf("%d row%s, %d column%s, %d non-zero%s\n", + lp->m, lp->m == 1 ? "" : "s", lp->n, lp->n == 1 ? "" : "s", + lp->nnz, lp->nnz == 1 ? "" : "s"); + } + /* inherit basis factorization control parameters */ + glp_get_bfcp(P, &bfcp); + glp_set_bfcp(lp, &bfcp); + /* scale the transformed problem */ + { ENV *env = get_env_ptr(); + int term_out = env->term_out; + if (!term_out || parm->msg_lev < GLP_MSG_ALL) + env->term_out = GLP_OFF; + else + env->term_out = GLP_ON; + glp_scale_prob(lp, GLP_SF_AUTO); + env->term_out = term_out; + } + /* build advanced initial basis */ + { ENV *env = get_env_ptr(); + int term_out = env->term_out; + if (!term_out || parm->msg_lev < GLP_MSG_ALL) + env->term_out = GLP_OFF; + else + env->term_out = GLP_ON; + glp_adv_basis(lp, 0); + env->term_out = term_out; + } + /* solve the transformed LP */ + lp->it_cnt = P->it_cnt; + ret = solve_lp(lp, parm); + P->it_cnt = lp->it_cnt; + /* only optimal solution can be postprocessed */ + if (!(ret == 0 && lp->pbs_stat == GLP_FEAS && lp->dbs_stat == + GLP_FEAS)) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_simplex: unable to recover undefined or non-op" + "timal solution\n"); + if (ret == 0) + { if (lp->pbs_stat == GLP_NOFEAS) + ret = GLP_ENOPFS; + else if (lp->dbs_stat == GLP_NOFEAS) + ret = GLP_ENODFS; + else + xassert(lp != lp); + } + goto done; + } +post: /* postprocess solution from the transformed LP */ + npp_postprocess(npp, lp); + /* the transformed LP is no longer needed */ + glp_delete_prob(lp), lp = NULL; + /* store solution to the original problem */ + npp_unload_sol(npp, P); + /* the original LP has been successfully solved */ + ret = 0; +done: /* delete the transformed LP, if it exists */ + if (lp != NULL) glp_delete_prob(lp); + /* delete preprocessor workspace */ + npp_delete_wksp(npp); + return ret; +} + +int glp_simplex(glp_prob *P, const glp_smcp *parm) +{ /* solve LP problem with the simplex method */ + glp_smcp _parm; + int i, j, ret; + /* check problem object */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_simplex: P = %p; invalid problem object\n", P); + if (P->tree != NULL && P->tree->reason != 0) + xerror("glp_simplex: operation not allowed\n"); + /* check control parameters */ + if (parm == NULL) + parm = &_parm, glp_init_smcp((glp_smcp *)parm); + if (!(parm->msg_lev == GLP_MSG_OFF || + parm->msg_lev == GLP_MSG_ERR || + parm->msg_lev == GLP_MSG_ON || + parm->msg_lev == GLP_MSG_ALL || + parm->msg_lev == GLP_MSG_DBG)) + xerror("glp_simplex: msg_lev = %d; invalid parameter\n", + parm->msg_lev); + if (!(parm->meth == GLP_PRIMAL || + parm->meth == GLP_DUALP || + parm->meth == GLP_DUAL)) + xerror("glp_simplex: meth = %d; invalid parameter\n", + parm->meth); + if (!(parm->pricing == GLP_PT_STD || + parm->pricing == GLP_PT_PSE)) + xerror("glp_simplex: pricing = %d; invalid parameter\n", + parm->pricing); + if (!(parm->r_test == GLP_RT_STD || + parm->r_test == GLP_RT_HAR)) + xerror("glp_simplex: r_test = %d; invalid parameter\n", + parm->r_test); + if (!(0.0 < parm->tol_bnd && parm->tol_bnd < 1.0)) + xerror("glp_simplex: tol_bnd = %g; invalid parameter\n", + parm->tol_bnd); + if (!(0.0 < parm->tol_dj && parm->tol_dj < 1.0)) + xerror("glp_simplex: tol_dj = %g; invalid parameter\n", + parm->tol_dj); + if (!(0.0 < parm->tol_piv && parm->tol_piv < 1.0)) + xerror("glp_simplex: tol_piv = %g; invalid parameter\n", + parm->tol_piv); + if (parm->it_lim < 0) + xerror("glp_simplex: it_lim = %d; invalid parameter\n", + parm->it_lim); + if (parm->tm_lim < 0) + xerror("glp_simplex: tm_lim = %d; invalid parameter\n", + parm->tm_lim); + if (parm->out_frq < 1) + xerror("glp_simplex: out_frq = %d; invalid parameter\n", + parm->out_frq); + if (parm->out_dly < 0) + xerror("glp_simplex: out_dly = %d; invalid parameter\n", + parm->out_dly); + if (!(parm->presolve == GLP_ON || parm->presolve == GLP_OFF)) + xerror("glp_simplex: presolve = %d; invalid parameter\n", + parm->presolve); + /* basic solution is currently undefined */ + P->pbs_stat = P->dbs_stat = GLP_UNDEF; + P->obj_val = 0.0; + P->some = 0; + /* check bounds of double-bounded variables */ + for (i = 1; i <= P->m; i++) + { GLPROW *row = P->row[i]; + if (row->type == GLP_DB && row->lb >= row->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_simplex: row %d: lb = %g, ub = %g; incorrec" + "t bounds\n", i, row->lb, row->ub); + ret = GLP_EBOUND; + goto done; + } + } + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if (col->type == GLP_DB && col->lb >= col->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_simplex: column %d: lb = %g, ub = %g; incor" + "rect bounds\n", j, col->lb, col->ub); + ret = GLP_EBOUND; + goto done; + } + } + /* solve LP problem */ + if (parm->msg_lev >= GLP_MSG_ALL) + { xprintf("GLPK Simplex Optimizer, v%s\n", glp_version()); + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", + P->nnz, P->nnz == 1 ? "" : "s"); + } + if (P->nnz == 0) + trivial_lp(P, parm), ret = 0; + else if (!parm->presolve) + ret = solve_lp(P, parm); + else + ret = preprocess_and_solve_lp(P, parm); +done: /* return to the application program */ + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_init_smcp - initialize simplex method control parameters +* +* SYNOPSIS +* +* void glp_init_smcp(glp_smcp *parm); +* +* DESCRIPTION +* +* The routine glp_init_smcp initializes control parameters, which are +* used by the simplex solver, with default values. +* +* Default values of the control parameters are stored in a glp_smcp +* structure, which the parameter parm points to. */ + +void glp_init_smcp(glp_smcp *parm) +{ parm->msg_lev = GLP_MSG_ALL; + parm->meth = GLP_PRIMAL; + parm->pricing = GLP_PT_PSE; + parm->r_test = GLP_RT_HAR; + parm->tol_bnd = 1e-7; + parm->tol_dj = 1e-7; + parm->tol_piv = 1e-10; + parm->obj_ll = -DBL_MAX; + parm->obj_ul = +DBL_MAX; + parm->it_lim = INT_MAX; + parm->tm_lim = INT_MAX; + parm->out_frq = 500; + parm->out_dly = 0; + parm->presolve = GLP_OFF; + return; +} + +/*********************************************************************** +* NAME +* +* glp_get_status - retrieve generic status of basic solution +* +* SYNOPSIS +* +* int glp_get_status(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_status reports the generic status of the basic +* solution for the specified problem object as follows: +* +* GLP_OPT - solution is optimal; +* GLP_FEAS - solution is feasible; +* GLP_INFEAS - solution is infeasible; +* GLP_NOFEAS - problem has no feasible solution; +* GLP_UNBND - problem has unbounded solution; +* GLP_UNDEF - solution is undefined. */ + +int glp_get_status(glp_prob *lp) +{ int status; + status = glp_get_prim_stat(lp); + switch (status) + { case GLP_FEAS: + switch (glp_get_dual_stat(lp)) + { case GLP_FEAS: + status = GLP_OPT; + break; + case GLP_NOFEAS: + status = GLP_UNBND; + break; + case GLP_UNDEF: + case GLP_INFEAS: + status = status; + break; + default: + xassert(lp != lp); + } + break; + case GLP_UNDEF: + case GLP_INFEAS: + case GLP_NOFEAS: + status = status; + break; + default: + xassert(lp != lp); + } + return status; +} + +/*********************************************************************** +* NAME +* +* glp_get_prim_stat - retrieve status of primal basic solution +* +* SYNOPSIS +* +* int glp_get_prim_stat(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_prim_stat reports the status of the primal basic +* solution for the specified problem object as follows: +* +* GLP_UNDEF - primal solution is undefined; +* GLP_FEAS - primal solution is feasible; +* GLP_INFEAS - primal solution is infeasible; +* GLP_NOFEAS - no primal feasible solution exists. */ + +int glp_get_prim_stat(glp_prob *lp) +{ int pbs_stat = lp->pbs_stat; + return pbs_stat; +} + +/*********************************************************************** +* NAME +* +* glp_get_dual_stat - retrieve status of dual basic solution +* +* SYNOPSIS +* +* int glp_get_dual_stat(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_dual_stat reports the status of the dual basic +* solution for the specified problem object as follows: +* +* GLP_UNDEF - dual solution is undefined; +* GLP_FEAS - dual solution is feasible; +* GLP_INFEAS - dual solution is infeasible; +* GLP_NOFEAS - no dual feasible solution exists. */ + +int glp_get_dual_stat(glp_prob *lp) +{ int dbs_stat = lp->dbs_stat; + return dbs_stat; +} + +/*********************************************************************** +* NAME +* +* glp_get_obj_val - retrieve objective value (basic solution) +* +* SYNOPSIS +* +* double glp_get_obj_val(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_obj_val returns value of the objective function +* for basic solution. */ + +double glp_get_obj_val(glp_prob *lp) +{ /*struct LPXCPS *cps = lp->cps;*/ + double z; + z = lp->obj_val; + /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/ + return z; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_stat - retrieve row status +* +* SYNOPSIS +* +* int glp_get_row_stat(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_stat returns current status assigned to the +* auxiliary variable associated with i-th row as follows: +* +* GLP_BS - basic variable; +* GLP_NL - non-basic variable on its lower bound; +* GLP_NU - non-basic variable on its upper bound; +* GLP_NF - non-basic free (unbounded) variable; +* GLP_NS - non-basic fixed variable. */ + +int glp_get_row_stat(glp_prob *lp, int i) +{ if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_stat: i = %d; row number out of range\n", + i); + return lp->row[i]->stat; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_prim - retrieve row primal value (basic solution) +* +* SYNOPSIS +* +* double glp_get_row_prim(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_prim returns primal value of the auxiliary +* variable associated with i-th row. */ + +double glp_get_row_prim(glp_prob *lp, int i) +{ /*struct LPXCPS *cps = lp->cps;*/ + double prim; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_prim: i = %d; row number out of range\n", + i); + prim = lp->row[i]->prim; + /*if (cps->round && fabs(prim) < 1e-9) prim = 0.0;*/ + return prim; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_dual - retrieve row dual value (basic solution) +* +* SYNOPSIS +* +* double glp_get_row_dual(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_dual returns dual value (i.e. reduced cost) +* of the auxiliary variable associated with i-th row. */ + +double glp_get_row_dual(glp_prob *lp, int i) +{ /*struct LPXCPS *cps = lp->cps;*/ + double dual; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_dual: i = %d; row number out of range\n", + i); + dual = lp->row[i]->dual; + /*if (cps->round && fabs(dual) < 1e-9) dual = 0.0;*/ + return dual; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_stat - retrieve column status +* +* SYNOPSIS +* +* int glp_get_col_stat(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_stat returns current status assigned to the +* structural variable associated with j-th column as follows: +* +* GLP_BS - basic variable; +* GLP_NL - non-basic variable on its lower bound; +* GLP_NU - non-basic variable on its upper bound; +* GLP_NF - non-basic free (unbounded) variable; +* GLP_NS - non-basic fixed variable. */ + +int glp_get_col_stat(glp_prob *lp, int j) +{ if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_stat: j = %d; column number out of range\n" + , j); + return lp->col[j]->stat; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_prim - retrieve column primal value (basic solution) +* +* SYNOPSIS +* +* double glp_get_col_prim(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_prim returns primal value of the structural +* variable associated with j-th column. */ + +double glp_get_col_prim(glp_prob *lp, int j) +{ /*struct LPXCPS *cps = lp->cps;*/ + double prim; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_prim: j = %d; column number out of range\n" + , j); + prim = lp->col[j]->prim; + /*if (cps->round && fabs(prim) < 1e-9) prim = 0.0;*/ + return prim; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_dual - retrieve column dual value (basic solution) +* +* SYNOPSIS +* +* double glp_get_col_dual(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_dual returns dual value (i.e. reduced cost) +* of the structural variable associated with j-th column. */ + +double glp_get_col_dual(glp_prob *lp, int j) +{ /*struct LPXCPS *cps = lp->cps;*/ + double dual; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_dual: j = %d; column number out of range\n" + , j); + dual = lp->col[j]->dual; + /*if (cps->round && fabs(dual) < 1e-9) dual = 0.0;*/ + return dual; +} + +/*********************************************************************** +* NAME +* +* glp_get_unbnd_ray - determine variable causing unboundedness +* +* SYNOPSIS +* +* int glp_get_unbnd_ray(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_unbnd_ray returns the number k of a variable, +* which causes primal or dual unboundedness. If 1 <= k <= m, it is +* k-th auxiliary variable, and if m+1 <= k <= m+n, it is (k-m)-th +* structural variable, where m is the number of rows, n is the number +* of columns in the problem object. If such variable is not defined, +* the routine returns 0. +* +* COMMENTS +* +* If it is not exactly known which version of the simplex solver +* detected unboundedness, i.e. whether the unboundedness is primal or +* dual, it is sufficient to check the status of the variable reported +* with the routine glp_get_row_stat or glp_get_col_stat. If the +* variable is non-basic, the unboundedness is primal, otherwise, if +* the variable is basic, the unboundedness is dual (the latter case +* means that the problem has no primal feasible dolution). */ + +int glp_get_unbnd_ray(glp_prob *lp) +{ int k; + k = lp->some; + xassert(k >= 0); + if (k > lp->m + lp->n) k = 0; + return k; +} + +#if 1 /* 08/VIII-2013 */ +int glp_get_it_cnt(glp_prob *P) +{ /* get simplex solver iteration count */ + return P->it_cnt; +} +#endif + +#if 1 /* 08/VIII-2013 */ +int glp_set_it_cnt(glp_prob *P, int it_cnt) +{ /* set simplex solver iteration count */ + P->it_cnt = it_cnt; + return; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi07.c b/resources/3rdparty/glpk-4.53/src/glpapi07.c new file mode 100644 index 000000000..5258a4dec --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi07.c @@ -0,0 +1,456 @@ +/* glpapi07.c (exact simplex solver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "draft.h" +#include "glpssx.h" +#include "misc.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_exact - solve LP problem in exact arithmetic +* +* SYNOPSIS +* +* int glp_exact(glp_prob *lp, const glp_smcp *parm); +* +* DESCRIPTION +* +* The routine glp_exact is a tentative implementation of the primal +* two-phase simplex method based on exact (rational) arithmetic. It is +* similar to the routine glp_simplex, however, for all internal +* computations it uses arithmetic of rational numbers, which is exact +* in mathematical sense, i.e. free of round-off errors unlike floating +* point arithmetic. +* +* Note that the routine glp_exact uses inly two control parameters +* passed in the structure glp_smcp, namely, it_lim and tm_lim. +* +* RETURNS +* +* 0 The LP problem instance has been successfully solved. This code +* does not necessarily mean that the solver has found optimal +* solution. It only means that the solution process was successful. +* +* GLP_EBADB +* Unable to start the search, because the initial basis specified +* in the problem object is invalid--the number of basic (auxiliary +* and structural) variables is not the same as the number of rows in +* the problem object. +* +* GLP_ESING +* Unable to start the search, because the basis matrix correspodning +* to the initial basis is exactly singular. +* +* GLP_EBOUND +* Unable to start the search, because some double-bounded variables +* have incorrect bounds. +* +* GLP_EFAIL +* The problem has no rows/columns. +* +* GLP_EITLIM +* The search was prematurely terminated, because the simplex +* iteration limit has been exceeded. +* +* GLP_ETMLIM +* The search was prematurely terminated, because the time limit has +* been exceeded. */ + +static void set_d_eps(mpq_t x, double val) +{ /* convert double val to rational x obtaining a more adequate + fraction than provided by mpq_set_d due to allowing a small + approximation error specified by a given relative tolerance; + for example, mpq_set_d would give the following + 1/3 ~= 0.333333333333333314829616256247391... -> + -> 6004799503160661/18014398509481984 + while this routine gives exactly 1/3 */ + int s, n, j; + double f, p, q, eps = 1e-9; + mpq_t temp; + xassert(-DBL_MAX <= val && val <= +DBL_MAX); +#if 1 /* 30/VII-2008 */ + if (val == floor(val)) + { /* if val is integral, do not approximate */ + mpq_set_d(x, val); + goto done; + } +#endif + if (val > 0.0) + s = +1; + else if (val < 0.0) + s = -1; + else + { mpq_set_si(x, 0, 1); + goto done; + } + f = frexp(fabs(val), &n); + /* |val| = f * 2^n, where 0.5 <= f < 1.0 */ + fp2rat(f, 0.1 * eps, &p, &q); + /* f ~= p / q, where p and q are integers */ + mpq_init(temp); + mpq_set_d(x, p); + mpq_set_d(temp, q); + mpq_div(x, x, temp); + mpq_set_si(temp, 1, 1); + for (j = 1; j <= abs(n); j++) + mpq_add(temp, temp, temp); + if (n > 0) + mpq_mul(x, x, temp); + else if (n < 0) + mpq_div(x, x, temp); + mpq_clear(temp); + if (s < 0) mpq_neg(x, x); + /* check that the desired tolerance has been attained */ + xassert(fabs(val - mpq_get_d(x)) <= eps * (1.0 + fabs(val))); +done: return; +} + +static void load_data(SSX *ssx, glp_prob *lp) +{ /* load LP problem data into simplex solver workspace */ + int m = ssx->m; + int n = ssx->n; + int nnz = ssx->A_ptr[n+1]-1; + int j, k, type, loc, len, *ind; + double lb, ub, coef, *val; + xassert(lp->m == m); + xassert(lp->n == n); + xassert(lp->nnz == nnz); + /* types and bounds of rows and columns */ + for (k = 1; k <= m+n; k++) + { if (k <= m) + { type = lp->row[k]->type; + lb = lp->row[k]->lb; + ub = lp->row[k]->ub; + } + else + { type = lp->col[k-m]->type; + lb = lp->col[k-m]->lb; + ub = lp->col[k-m]->ub; + } + switch (type) + { case GLP_FR: type = SSX_FR; break; + case GLP_LO: type = SSX_LO; break; + case GLP_UP: type = SSX_UP; break; + case GLP_DB: type = SSX_DB; break; + case GLP_FX: type = SSX_FX; break; + default: xassert(type != type); + } + ssx->type[k] = type; + set_d_eps(ssx->lb[k], lb); + set_d_eps(ssx->ub[k], ub); + } + /* optimization direction */ + switch (lp->dir) + { case GLP_MIN: ssx->dir = SSX_MIN; break; + case GLP_MAX: ssx->dir = SSX_MAX; break; + default: xassert(lp != lp); + } + /* objective coefficients */ + for (k = 0; k <= m+n; k++) + { if (k == 0) + coef = lp->c0; + else if (k <= m) + coef = 0.0; + else + coef = lp->col[k-m]->coef; + set_d_eps(ssx->coef[k], coef); + } + /* constraint coefficients */ + ind = xcalloc(1+m, sizeof(int)); + val = xcalloc(1+m, sizeof(double)); + loc = 0; + for (j = 1; j <= n; j++) + { ssx->A_ptr[j] = loc+1; + len = glp_get_mat_col(lp, j, ind, val); + for (k = 1; k <= len; k++) + { loc++; + ssx->A_ind[loc] = ind[k]; + set_d_eps(ssx->A_val[loc], val[k]); + } + } + xassert(loc == nnz); + xfree(ind); + xfree(val); + return; +} + +static int load_basis(SSX *ssx, glp_prob *lp) +{ /* load current LP basis into simplex solver workspace */ + int m = ssx->m; + int n = ssx->n; + int *type = ssx->type; + int *stat = ssx->stat; + int *Q_row = ssx->Q_row; + int *Q_col = ssx->Q_col; + int i, j, k; + xassert(lp->m == m); + xassert(lp->n == n); + /* statuses of rows and columns */ + for (k = 1; k <= m+n; k++) + { if (k <= m) + stat[k] = lp->row[k]->stat; + else + stat[k] = lp->col[k-m]->stat; + switch (stat[k]) + { case GLP_BS: + stat[k] = SSX_BS; + break; + case GLP_NL: + stat[k] = SSX_NL; + xassert(type[k] == SSX_LO || type[k] == SSX_DB); + break; + case GLP_NU: + stat[k] = SSX_NU; + xassert(type[k] == SSX_UP || type[k] == SSX_DB); + break; + case GLP_NF: + stat[k] = SSX_NF; + xassert(type[k] == SSX_FR); + break; + case GLP_NS: + stat[k] = SSX_NS; + xassert(type[k] == SSX_FX); + break; + default: + xassert(stat != stat); + } + } + /* build permutation matix Q */ + i = j = 0; + for (k = 1; k <= m+n; k++) + { if (stat[k] == SSX_BS) + { i++; + if (i > m) return 1; + Q_row[k] = i, Q_col[i] = k; + } + else + { j++; + if (j > n) return 1; + Q_row[k] = m+j, Q_col[m+j] = k; + } + } + xassert(i == m && j == n); + return 0; +} + +int glp_exact(glp_prob *lp, const glp_smcp *parm) +{ glp_smcp _parm; + SSX *ssx; + int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int i, j, k, type, pst, dst, ret, stat; + double lb, ub, prim, dual, sum; + if (parm == NULL) + parm = &_parm, glp_init_smcp((glp_smcp *)parm); + /* check control parameters */ + if (parm->it_lim < 0) + xerror("glp_exact: it_lim = %d; invalid parameter\n", + parm->it_lim); + if (parm->tm_lim < 0) + xerror("glp_exact: tm_lim = %d; invalid parameter\n", + parm->tm_lim); + /* the problem must have at least one row and one column */ + if (!(m > 0 && n > 0)) + { xprintf("glp_exact: problem has no rows/columns\n"); + return GLP_EFAIL; + } +#if 1 + /* basic solution is currently undefined */ + lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; + lp->obj_val = 0.0; + lp->some = 0; +#endif + /* check that all double-bounded variables have correct bounds */ + for (k = 1; k <= m+n; k++) + { if (k <= m) + { type = lp->row[k]->type; + lb = lp->row[k]->lb; + ub = lp->row[k]->ub; + } + else + { type = lp->col[k-m]->type; + lb = lp->col[k-m]->lb; + ub = lp->col[k-m]->ub; + } + if (type == GLP_DB && lb >= ub) + { xprintf("glp_exact: %s %d has invalid bounds\n", + k <= m ? "row" : "column", k <= m ? k : k-m); + return GLP_EBOUND; + } + } + /* create the simplex solver workspace */ + xprintf("glp_exact: %d rows, %d columns, %d non-zeros\n", + m, n, nnz); +#ifdef HAVE_GMP + xprintf("GNU MP bignum library is being used\n"); +#else + xprintf("GLPK bignum module is being used\n"); + xprintf("(Consider installing GNU MP to attain a much better perf" + "ormance.)\n"); +#endif + ssx = ssx_create(m, n, nnz); + /* load LP problem data into the workspace */ + load_data(ssx, lp); + /* load current LP basis into the workspace */ + if (load_basis(ssx, lp)) + { xprintf("glp_exact: initial LP basis is invalid\n"); + ret = GLP_EBADB; + goto done; + } + /* inherit some control parameters from the LP object */ +#if 0 + ssx->it_lim = lpx_get_int_parm(lp, LPX_K_ITLIM); + ssx->it_cnt = lpx_get_int_parm(lp, LPX_K_ITCNT); + ssx->tm_lim = lpx_get_real_parm(lp, LPX_K_TMLIM); +#else + ssx->it_lim = parm->it_lim; + ssx->it_cnt = lp->it_cnt; + ssx->tm_lim = (double)parm->tm_lim / 1000.0; +#endif + ssx->out_frq = 5.0; + ssx->tm_beg = xtime(); +#if 0 /* 10/VI-2013 */ + ssx->tm_lag = xlset(0); +#else + ssx->tm_lag = 0.0; +#endif + /* solve LP */ + ret = ssx_driver(ssx); + /* copy back some statistics to the LP object */ +#if 0 + lpx_set_int_parm(lp, LPX_K_ITLIM, ssx->it_lim); + lpx_set_int_parm(lp, LPX_K_ITCNT, ssx->it_cnt); + lpx_set_real_parm(lp, LPX_K_TMLIM, ssx->tm_lim); +#else + lp->it_cnt = ssx->it_cnt; +#endif + /* analyze the return code */ + switch (ret) + { case 0: + /* optimal solution found */ + ret = 0; + pst = dst = GLP_FEAS; + break; + case 1: + /* problem has no feasible solution */ + ret = 0; + pst = GLP_NOFEAS, dst = GLP_INFEAS; + break; + case 2: + /* problem has unbounded solution */ + ret = 0; + pst = GLP_FEAS, dst = GLP_NOFEAS; +#if 1 + xassert(1 <= ssx->q && ssx->q <= n); + lp->some = ssx->Q_col[m + ssx->q]; + xassert(1 <= lp->some && lp->some <= m+n); +#endif + break; + case 3: + /* iteration limit exceeded (phase I) */ + ret = GLP_EITLIM; + pst = dst = GLP_INFEAS; + break; + case 4: + /* iteration limit exceeded (phase II) */ + ret = GLP_EITLIM; + pst = GLP_FEAS, dst = GLP_INFEAS; + break; + case 5: + /* time limit exceeded (phase I) */ + ret = GLP_ETMLIM; + pst = dst = GLP_INFEAS; + break; + case 6: + /* time limit exceeded (phase II) */ + ret = GLP_ETMLIM; + pst = GLP_FEAS, dst = GLP_INFEAS; + break; + case 7: + /* initial basis matrix is singular */ + ret = GLP_ESING; + goto done; + default: + xassert(ret != ret); + } + /* store final basic solution components into LP object */ + lp->pbs_stat = pst; + lp->dbs_stat = dst; + sum = lp->c0; + for (k = 1; k <= m+n; k++) + { if (ssx->stat[k] == SSX_BS) + { i = ssx->Q_row[k]; /* x[k] = xB[i] */ + xassert(1 <= i && i <= m); + stat = GLP_BS; + prim = mpq_get_d(ssx->bbar[i]); + dual = 0.0; + } + else + { j = ssx->Q_row[k] - m; /* x[k] = xN[j] */ + xassert(1 <= j && j <= n); + switch (ssx->stat[k]) + { case SSX_NF: + stat = GLP_NF; + prim = 0.0; + break; + case SSX_NL: + stat = GLP_NL; + prim = mpq_get_d(ssx->lb[k]); + break; + case SSX_NU: + stat = GLP_NU; + prim = mpq_get_d(ssx->ub[k]); + break; + case SSX_NS: + stat = GLP_NS; + prim = mpq_get_d(ssx->lb[k]); + break; + default: + xassert(ssx != ssx); + } + dual = mpq_get_d(ssx->cbar[j]); + } + if (k <= m) + { glp_set_row_stat(lp, k, stat); + lp->row[k]->prim = prim; + lp->row[k]->dual = dual; + } + else + { glp_set_col_stat(lp, k-m, stat); + lp->col[k-m]->prim = prim; + lp->col[k-m]->dual = dual; + sum += lp->col[k-m]->coef * prim; + } + } + lp->obj_val = sum; +done: /* delete the simplex solver workspace */ + ssx_delete(ssx); + /* return to the application program */ + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi08.c b/resources/3rdparty/glpk-4.53/src/glpapi08.c new file mode 100644 index 000000000..e7fc62e8f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi08.c @@ -0,0 +1,388 @@ +/* glpapi08.c (interior-point method routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpipm.h" +#include "glpnpp.h" + +/*********************************************************************** +* NAME +* +* glp_interior - solve LP problem with the interior-point method +* +* SYNOPSIS +* +* int glp_interior(glp_prob *P, const glp_iptcp *parm); +* +* The routine glp_interior is a driver to the LP solver based on the +* interior-point method. +* +* The interior-point solver has a set of control parameters. Values of +* the control parameters can be passed in a structure glp_iptcp, which +* the parameter parm points to. +* +* Currently this routine implements an easy variant of the primal-dual +* interior-point method based on Mehrotra's technique. +* +* This routine transforms the original LP problem to an equivalent LP +* problem in the standard formulation (all constraints are equalities, +* all variables are non-negative), calls the routine ipm_main to solve +* the transformed problem, and then transforms an obtained solution to +* the solution of the original problem. +* +* RETURNS +* +* 0 The LP problem instance has been successfully solved. This code +* does not necessarily mean that the solver has found optimal +* solution. It only means that the solution process was successful. +* +* GLP_EFAIL +* The problem has no rows/columns. +* +* GLP_ENOCVG +* Very slow convergence or divergence. +* +* GLP_EITLIM +* Iteration limit exceeded. +* +* GLP_EINSTAB +* Numerical instability on solving Newtonian system. */ + +static void transform(NPP *npp) +{ /* transform LP to the standard formulation */ + NPPROW *row, *prev_row; + NPPCOL *col, *prev_col; + for (row = npp->r_tail; row != NULL; row = prev_row) + { prev_row = row->prev; + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + npp_free_row(npp, row); + else if (row->lb == -DBL_MAX) + npp_leq_row(npp, row); + else if (row->ub == +DBL_MAX) + npp_geq_row(npp, row); + else if (row->lb != row->ub) + { if (fabs(row->lb) < fabs(row->ub)) + npp_geq_row(npp, row); + else + npp_leq_row(npp, row); + } + } + for (col = npp->c_tail; col != NULL; col = prev_col) + { prev_col = col->prev; + if (col->lb == -DBL_MAX && col->ub == +DBL_MAX) + npp_free_col(npp, col); + else if (col->lb == -DBL_MAX) + npp_ubnd_col(npp, col); + else if (col->ub == +DBL_MAX) + { if (col->lb != 0.0) + npp_lbnd_col(npp, col); + } + else if (col->lb != col->ub) + { if (fabs(col->lb) < fabs(col->ub)) + { if (col->lb != 0.0) + npp_lbnd_col(npp, col); + } + else + npp_ubnd_col(npp, col); + npp_dbnd_col(npp, col); + } + else + npp_fixed_col(npp, col); + } + for (row = npp->r_head; row != NULL; row = row->next) + xassert(row->lb == row->ub); + for (col = npp->c_head; col != NULL; col = col->next) + xassert(col->lb == 0.0 && col->ub == +DBL_MAX); + return; +} + +int glp_interior(glp_prob *P, const glp_iptcp *parm) +{ glp_iptcp _parm; + GLPROW *row; + GLPCOL *col; + NPP *npp = NULL; + glp_prob *prob = NULL; + int i, j, ret; + /* check control parameters */ + if (parm == NULL) + glp_init_iptcp(&_parm), parm = &_parm; + if (!(parm->msg_lev == GLP_MSG_OFF || + parm->msg_lev == GLP_MSG_ERR || + parm->msg_lev == GLP_MSG_ON || + parm->msg_lev == GLP_MSG_ALL)) + xerror("glp_interior: msg_lev = %d; invalid parameter\n", + parm->msg_lev); + if (!(parm->ord_alg == GLP_ORD_NONE || + parm->ord_alg == GLP_ORD_QMD || + parm->ord_alg == GLP_ORD_AMD || + parm->ord_alg == GLP_ORD_SYMAMD)) + xerror("glp_interior: ord_alg = %d; invalid parameter\n", + parm->ord_alg); + /* interior-point solution is currently undefined */ + P->ipt_stat = GLP_UNDEF; + P->ipt_obj = 0.0; + /* check bounds of double-bounded variables */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->type == GLP_DB && row->lb >= row->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_interior: row %d: lb = %g, ub = %g; incorre" + "ct bounds\n", i, row->lb, row->ub); + ret = GLP_EBOUND; + goto done; + } + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->type == GLP_DB && col->lb >= col->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_interior: column %d: lb = %g, ub = %g; inco" + "rrect bounds\n", j, col->lb, col->ub); + ret = GLP_EBOUND; + goto done; + } + } + /* transform LP to the standard formulation */ + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Original LP has %d row(s), %d column(s), and %d non-z" + "ero(s)\n", P->m, P->n, P->nnz); + npp = npp_create_wksp(); + npp_load_prob(npp, P, GLP_OFF, GLP_IPT, GLP_ON); + transform(npp); + prob = glp_create_prob(); + npp_build_prob(npp, prob); + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Working LP has %d row(s), %d column(s), and %d non-ze" + "ro(s)\n", prob->m, prob->n, prob->nnz); +#if 1 + /* currently empty problem cannot be solved */ + if (!(prob->m > 0 && prob->n > 0)) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_interior: unable to solve empty problem\n"); + ret = GLP_EFAIL; + goto done; + } +#endif + /* scale the resultant LP */ + { ENV *env = get_env_ptr(); + int term_out = env->term_out; + env->term_out = GLP_OFF; + glp_scale_prob(prob, GLP_SF_EQ); + env->term_out = term_out; + } + /* warn about dense columns */ + if (parm->msg_lev >= GLP_MSG_ON && prob->m >= 200) + { int len, cnt = 0; + for (j = 1; j <= prob->n; j++) + { len = glp_get_mat_col(prob, j, NULL, NULL); + if ((double)len >= 0.20 * (double)prob->m) cnt++; + } + if (cnt == 1) + xprintf("WARNING: PROBLEM HAS ONE DENSE COLUMN\n"); + else if (cnt > 0) + xprintf("WARNING: PROBLEM HAS %d DENSE COLUMNS\n", cnt); + } + /* solve the transformed LP */ + ret = ipm_solve(prob, parm); + /* postprocess solution from the transformed LP */ + npp_postprocess(npp, prob); + /* and store solution to the original LP */ + npp_unload_sol(npp, P); +done: /* free working program objects */ + if (npp != NULL) npp_delete_wksp(npp); + if (prob != NULL) glp_delete_prob(prob); + /* return to the application program */ + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_init_iptcp - initialize interior-point solver control parameters +* +* SYNOPSIS +* +* void glp_init_iptcp(glp_iptcp *parm); +* +* DESCRIPTION +* +* The routine glp_init_iptcp initializes control parameters, which are +* used by the interior-point solver, with default values. +* +* Default values of the control parameters are stored in the glp_iptcp +* structure, which the parameter parm points to. */ + +void glp_init_iptcp(glp_iptcp *parm) +{ parm->msg_lev = GLP_MSG_ALL; + parm->ord_alg = GLP_ORD_AMD; + return; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_status - retrieve status of interior-point solution +* +* SYNOPSIS +* +* int glp_ipt_status(glp_prob *lp); +* +* RETURNS +* +* The routine glp_ipt_status reports the status of solution found by +* the interior-point solver as follows: +* +* GLP_UNDEF - interior-point solution is undefined; +* GLP_OPT - interior-point solution is optimal; +* GLP_INFEAS - interior-point solution is infeasible; +* GLP_NOFEAS - no feasible solution exists. */ + +int glp_ipt_status(glp_prob *lp) +{ int ipt_stat = lp->ipt_stat; + return ipt_stat; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_obj_val - retrieve objective value (interior point) +* +* SYNOPSIS +* +* double glp_ipt_obj_val(glp_prob *lp); +* +* RETURNS +* +* The routine glp_ipt_obj_val returns value of the objective function +* for interior-point solution. */ + +double glp_ipt_obj_val(glp_prob *lp) +{ /*struct LPXCPS *cps = lp->cps;*/ + double z; + z = lp->ipt_obj; + /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/ + return z; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_row_prim - retrieve row primal value (interior point) +* +* SYNOPSIS +* +* double glp_ipt_row_prim(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_ipt_row_prim returns primal value of the auxiliary +* variable associated with i-th row. */ + +double glp_ipt_row_prim(glp_prob *lp, int i) +{ /*struct LPXCPS *cps = lp->cps;*/ + double pval; + if (!(1 <= i && i <= lp->m)) + xerror("glp_ipt_row_prim: i = %d; row number out of range\n", + i); + pval = lp->row[i]->pval; + /*if (cps->round && fabs(pval) < 1e-9) pval = 0.0;*/ + return pval; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_row_dual - retrieve row dual value (interior point) +* +* SYNOPSIS +* +* double glp_ipt_row_dual(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_ipt_row_dual returns dual value (i.e. reduced cost) +* of the auxiliary variable associated with i-th row. */ + +double glp_ipt_row_dual(glp_prob *lp, int i) +{ /*struct LPXCPS *cps = lp->cps;*/ + double dval; + if (!(1 <= i && i <= lp->m)) + xerror("glp_ipt_row_dual: i = %d; row number out of range\n", + i); + dval = lp->row[i]->dval; + /*if (cps->round && fabs(dval) < 1e-9) dval = 0.0;*/ + return dval; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_col_prim - retrieve column primal value (interior point) +* +* SYNOPSIS +* +* double glp_ipt_col_prim(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_ipt_col_prim returns primal value of the structural +* variable associated with j-th column. */ + +double glp_ipt_col_prim(glp_prob *lp, int j) +{ /*struct LPXCPS *cps = lp->cps;*/ + double pval; + if (!(1 <= j && j <= lp->n)) + xerror("glp_ipt_col_prim: j = %d; column number out of range\n" + , j); + pval = lp->col[j]->pval; + /*if (cps->round && fabs(pval) < 1e-9) pval = 0.0;*/ + return pval; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_col_dual - retrieve column dual value (interior point) +* +* SYNOPSIS +* +* double glp_ipt_col_dual(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_ipt_col_dual returns dual value (i.e. reduced cost) +* of the structural variable associated with j-th column. */ + +double glp_ipt_col_dual(glp_prob *lp, int j) +{ /*struct LPXCPS *cps = lp->cps;*/ + double dval; + if (!(1 <= j && j <= lp->n)) + xerror("glp_ipt_col_dual: j = %d; column number out of range\n" + , j); + dval = lp->col[j]->dval; + /*if (cps->round && fabs(dval) < 1e-9) dval = 0.0;*/ + return dval; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi09.c b/resources/3rdparty/glpk-4.53/src/glpapi09.c new file mode 100644 index 000000000..a24f3fdb6 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi09.c @@ -0,0 +1,786 @@ +/* glpapi09.c (mixed integer programming routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "draft.h" +#include "env.h" +#include "glpios.h" +#include "glpnpp.h" + +/*********************************************************************** +* NAME +* +* glp_set_col_kind - set (change) column kind +* +* SYNOPSIS +* +* void glp_set_col_kind(glp_prob *mip, int j, int kind); +* +* DESCRIPTION +* +* The routine glp_set_col_kind sets (changes) the kind of j-th column +* (structural variable) as specified by the parameter kind: +* +* GLP_CV - continuous variable; +* GLP_IV - integer variable; +* GLP_BV - binary variable. */ + +void glp_set_col_kind(glp_prob *mip, int j, int kind) +{ GLPCOL *col; + if (!(1 <= j && j <= mip->n)) + xerror("glp_set_col_kind: j = %d; column number out of range\n" + , j); + col = mip->col[j]; + switch (kind) + { case GLP_CV: + col->kind = GLP_CV; + break; + case GLP_IV: + col->kind = GLP_IV; + break; + case GLP_BV: + col->kind = GLP_IV; + if (!(col->type == GLP_DB && col->lb == 0.0 && col->ub == + 1.0)) glp_set_col_bnds(mip, j, GLP_DB, 0.0, 1.0); + break; + default: + xerror("glp_set_col_kind: j = %d; kind = %d; invalid column" + " kind\n", j, kind); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_kind - retrieve column kind +* +* SYNOPSIS +* +* int glp_get_col_kind(glp_prob *mip, int j); +* +* RETURNS +* +* The routine glp_get_col_kind returns the kind of j-th column, i.e. +* the kind of corresponding structural variable, as follows: +* +* GLP_CV - continuous variable; +* GLP_IV - integer variable; +* GLP_BV - binary variable */ + +int glp_get_col_kind(glp_prob *mip, int j) +{ GLPCOL *col; + int kind; + if (!(1 <= j && j <= mip->n)) + xerror("glp_get_col_kind: j = %d; column number out of range\n" + , j); + col = mip->col[j]; + kind = col->kind; + switch (kind) + { case GLP_CV: + break; + case GLP_IV: + if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0) + kind = GLP_BV; + break; + default: + xassert(kind != kind); + } + return kind; +} + +/*********************************************************************** +* NAME +* +* glp_get_num_int - retrieve number of integer columns +* +* SYNOPSIS +* +* int glp_get_num_int(glp_prob *mip); +* +* RETURNS +* +* The routine glp_get_num_int returns the current number of columns, +* which are marked as integer. */ + +int glp_get_num_int(glp_prob *mip) +{ GLPCOL *col; + int j, count = 0; + for (j = 1; j <= mip->n; j++) + { col = mip->col[j]; + if (col->kind == GLP_IV) count++; + } + return count; +} + +/*********************************************************************** +* NAME +* +* glp_get_num_bin - retrieve number of binary columns +* +* SYNOPSIS +* +* int glp_get_num_bin(glp_prob *mip); +* +* RETURNS +* +* The routine glp_get_num_bin returns the current number of columns, +* which are marked as binary. */ + +int glp_get_num_bin(glp_prob *mip) +{ GLPCOL *col; + int j, count = 0; + for (j = 1; j <= mip->n; j++) + { col = mip->col[j]; + if (col->kind == GLP_IV && col->type == GLP_DB && col->lb == + 0.0 && col->ub == 1.0) count++; + } + return count; +} + +/*********************************************************************** +* NAME +* +* glp_intopt - solve MIP problem with the branch-and-bound method +* +* SYNOPSIS +* +* int glp_intopt(glp_prob *P, const glp_iocp *parm); +* +* DESCRIPTION +* +* The routine glp_intopt is a driver to the MIP solver based on the +* branch-and-bound method. +* +* On entry the problem object should contain optimal solution to LP +* relaxation (which can be obtained with the routine glp_simplex). +* +* The MIP solver has a set of control parameters. Values of the control +* parameters can be passed in a structure glp_iocp, which the parameter +* parm points to. +* +* The parameter parm can be specified as NULL, in which case the MIP +* solver uses default settings. +* +* RETURNS +* +* 0 The MIP problem instance has been successfully solved. This code +* does not necessarily mean that the solver has found optimal +* solution. It only means that the solution process was successful. +* +* GLP_EBOUND +* Unable to start the search, because some double-bounded variables +* have incorrect bounds or some integer variables have non-integer +* (fractional) bounds. +* +* GLP_EROOT +* Unable to start the search, because optimal basis for initial LP +* relaxation is not provided. +* +* GLP_EFAIL +* The search was prematurely terminated due to the solver failure. +* +* GLP_EMIPGAP +* The search was prematurely terminated, because the relative mip +* gap tolerance has been reached. +* +* GLP_ETMLIM +* The search was prematurely terminated, because the time limit has +* been exceeded. +* +* GLP_ENOPFS +* The MIP problem instance has no primal feasible solution (only if +* the MIP presolver is used). +* +* GLP_ENODFS +* LP relaxation of the MIP problem instance has no dual feasible +* solution (only if the MIP presolver is used). +* +* GLP_ESTOP +* The search was prematurely terminated by application. */ + +#if 0 /* 11/VII-2013 */ +static int solve_mip(glp_prob *P, const glp_iocp *parm) +#else +static int solve_mip(glp_prob *P, const glp_iocp *parm, + glp_prob *P0 /* problem passed to glp_intopt */, + NPP *npp /* preprocessor workspace or NULL */) +#endif +{ /* solve MIP directly without using the preprocessor */ + glp_tree *T; + int ret; + /* optimal basis to LP relaxation must be provided */ + if (glp_get_status(P) != GLP_OPT) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: optimal basis to initial LP relaxation" + " not provided\n"); + ret = GLP_EROOT; + goto done; + } + /* it seems all is ok */ + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Integer optimization begins...\n"); + /* create the branch-and-bound tree */ + T = ios_create_tree(P, parm); +#if 1 /* 11/VII-2013 */ + T->P = P0; + T->npp = npp; +#endif + /* solve the problem instance */ + ret = ios_driver(T); + /* delete the branch-and-bound tree */ + ios_delete_tree(T); + /* analyze exit code reported by the mip driver */ + if (ret == 0) + { if (P->mip_stat == GLP_FEAS) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("INTEGER OPTIMAL SOLUTION FOUND\n"); + P->mip_stat = GLP_OPT; + } + else + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION\n"); + P->mip_stat = GLP_NOFEAS; + } + } + else if (ret == GLP_EMIPGAP) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("RELATIVE MIP GAP TOLERANCE REACHED; SEARCH TERMINA" + "TED\n"); + } + else if (ret == GLP_ETMLIM) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + } + else if (ret == GLP_EFAIL) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: cannot solve current LP relaxation\n"); + } + else if (ret == GLP_ESTOP) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("SEARCH TERMINATED BY APPLICATION\n"); + } + else + xassert(ret != ret); +done: return ret; +} + +static int preprocess_and_solve_mip(glp_prob *P, const glp_iocp *parm) +{ /* solve MIP using the preprocessor */ + ENV *env = get_env_ptr(); + int term_out = env->term_out; + NPP *npp; + glp_prob *mip = NULL; + glp_bfcp bfcp; + glp_smcp smcp; + int ret; + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Preprocessing...\n"); + /* create preprocessor workspace */ + npp = npp_create_wksp(); + /* load original problem into the preprocessor workspace */ + npp_load_prob(npp, P, GLP_OFF, GLP_MIP, GLP_OFF); + /* process MIP prior to applying the branch-and-bound method */ + if (!term_out || parm->msg_lev < GLP_MSG_ALL) + env->term_out = GLP_OFF; + else + env->term_out = GLP_ON; + ret = npp_integer(npp, parm); + env->term_out = term_out; + if (ret == 0) + ; + else if (ret == GLP_ENOPFS) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n"); + } + else if (ret == GLP_ENODFS) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("LP RELAXATION HAS NO DUAL FEASIBLE SOLUTION\n"); + } + else + xassert(ret != ret); + if (ret != 0) goto done; + /* build transformed MIP */ + mip = glp_create_prob(); + npp_build_prob(npp, mip); + /* if the transformed MIP is empty, it has empty solution, which + is optimal */ + if (mip->m == 0 && mip->n == 0) + { mip->mip_stat = GLP_OPT; + mip->mip_obj = mip->c0; + if (parm->msg_lev >= GLP_MSG_ALL) + { xprintf("Objective value = %17.9e\n", mip->mip_obj); + xprintf("INTEGER OPTIMAL SOLUTION FOUND BY MIP PREPROCESSOR" + "\n"); + } + goto post; + } + /* display some statistics */ + if (parm->msg_lev >= GLP_MSG_ALL) + { int ni = glp_get_num_int(mip); + int nb = glp_get_num_bin(mip); + char s[50]; + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + mip->m, mip->m == 1 ? "" : "s", mip->n, mip->n == 1 ? "" : + "s", mip->nnz, mip->nnz == 1 ? "" : "s"); + if (nb == 0) + strcpy(s, "none of"); + else if (ni == 1 && nb == 1) + strcpy(s, ""); + else if (nb == 1) + strcpy(s, "one of"); + else if (nb == ni) + strcpy(s, "all of"); + else + sprintf(s, "%d of", nb); + xprintf("%d integer variable%s, %s which %s binary\n", + ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are"); + } + /* inherit basis factorization control parameters */ + glp_get_bfcp(P, &bfcp); + glp_set_bfcp(mip, &bfcp); + /* scale the transformed problem */ + if (!term_out || parm->msg_lev < GLP_MSG_ALL) + env->term_out = GLP_OFF; + else + env->term_out = GLP_ON; + glp_scale_prob(mip, + GLP_SF_GM | GLP_SF_EQ | GLP_SF_2N | GLP_SF_SKIP); + env->term_out = term_out; + /* build advanced initial basis */ + if (!term_out || parm->msg_lev < GLP_MSG_ALL) + env->term_out = GLP_OFF; + else + env->term_out = GLP_ON; + glp_adv_basis(mip, 0); + env->term_out = term_out; + /* solve initial LP relaxation */ + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Solving LP relaxation...\n"); + glp_init_smcp(&smcp); + smcp.msg_lev = parm->msg_lev; + mip->it_cnt = P->it_cnt; + ret = glp_simplex(mip, &smcp); + P->it_cnt = mip->it_cnt; + if (ret != 0) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: cannot solve LP relaxation\n"); + ret = GLP_EFAIL; + goto done; + } + /* check status of the basic solution */ + ret = glp_get_status(mip); + if (ret == GLP_OPT) + ret = 0; + else if (ret == GLP_NOFEAS) + ret = GLP_ENOPFS; + else if (ret == GLP_UNBND) + ret = GLP_ENODFS; + else + xassert(ret != ret); + if (ret != 0) goto done; + /* solve the transformed MIP */ + mip->it_cnt = P->it_cnt; +#if 0 /* 11/VII-2013 */ + ret = solve_mip(mip, parm); +#else + if (parm->use_sol) + { mip->mip_stat = P->mip_stat; + mip->mip_obj = P->mip_obj; + } + ret = solve_mip(mip, parm, P, npp); +#endif + P->it_cnt = mip->it_cnt; + /* only integer feasible solution can be postprocessed */ + if (!(mip->mip_stat == GLP_OPT || mip->mip_stat == GLP_FEAS)) + { P->mip_stat = mip->mip_stat; + goto done; + } + /* postprocess solution from the transformed MIP */ +post: npp_postprocess(npp, mip); + /* the transformed MIP is no longer needed */ + glp_delete_prob(mip), mip = NULL; + /* store solution to the original problem */ + npp_unload_sol(npp, P); +done: /* delete the transformed MIP, if it exists */ + if (mip != NULL) glp_delete_prob(mip); + /* delete preprocessor workspace */ + npp_delete_wksp(npp); + return ret; +} + +#ifndef HAVE_ALIEN_SOLVER /* 28/V-2010 */ +int _glp_intopt1(glp_prob *P, const glp_iocp *parm) +{ xassert(P == P); + xassert(parm == parm); + xprintf("glp_intopt: no alien solver is available\n"); + return GLP_EFAIL; +} +#endif + +int glp_intopt(glp_prob *P, const glp_iocp *parm) +{ /* solve MIP problem with the branch-and-bound method */ + glp_iocp _parm; + int i, j, ret; + /* check problem object */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_intopt: P = %p; invalid problem object\n", P); + if (P->tree != NULL) + xerror("glp_intopt: operation not allowed\n"); + /* check control parameters */ + if (parm == NULL) + parm = &_parm, glp_init_iocp((glp_iocp *)parm); + if (!(parm->msg_lev == GLP_MSG_OFF || + parm->msg_lev == GLP_MSG_ERR || + parm->msg_lev == GLP_MSG_ON || + parm->msg_lev == GLP_MSG_ALL || + parm->msg_lev == GLP_MSG_DBG)) + xerror("glp_intopt: msg_lev = %d; invalid parameter\n", + parm->msg_lev); + if (!(parm->br_tech == GLP_BR_FFV || + parm->br_tech == GLP_BR_LFV || + parm->br_tech == GLP_BR_MFV || + parm->br_tech == GLP_BR_DTH || + parm->br_tech == GLP_BR_PCH)) + xerror("glp_intopt: br_tech = %d; invalid parameter\n", + parm->br_tech); + if (!(parm->bt_tech == GLP_BT_DFS || + parm->bt_tech == GLP_BT_BFS || + parm->bt_tech == GLP_BT_BLB || + parm->bt_tech == GLP_BT_BPH)) + xerror("glp_intopt: bt_tech = %d; invalid parameter\n", + parm->bt_tech); + if (!(0.0 < parm->tol_int && parm->tol_int < 1.0)) + xerror("glp_intopt: tol_int = %g; invalid parameter\n", + parm->tol_int); + if (!(0.0 < parm->tol_obj && parm->tol_obj < 1.0)) + xerror("glp_intopt: tol_obj = %g; invalid parameter\n", + parm->tol_obj); + if (parm->tm_lim < 0) + xerror("glp_intopt: tm_lim = %d; invalid parameter\n", + parm->tm_lim); + if (parm->out_frq < 0) + xerror("glp_intopt: out_frq = %d; invalid parameter\n", + parm->out_frq); + if (parm->out_dly < 0) + xerror("glp_intopt: out_dly = %d; invalid parameter\n", + parm->out_dly); + if (!(0 <= parm->cb_size && parm->cb_size <= 256)) + xerror("glp_intopt: cb_size = %d; invalid parameter\n", + parm->cb_size); + if (!(parm->pp_tech == GLP_PP_NONE || + parm->pp_tech == GLP_PP_ROOT || + parm->pp_tech == GLP_PP_ALL)) + xerror("glp_intopt: pp_tech = %d; invalid parameter\n", + parm->pp_tech); + if (parm->mip_gap < 0.0) + xerror("glp_intopt: mip_gap = %g; invalid parameter\n", + parm->mip_gap); + if (!(parm->mir_cuts == GLP_ON || parm->mir_cuts == GLP_OFF)) + xerror("glp_intopt: mir_cuts = %d; invalid parameter\n", + parm->mir_cuts); + if (!(parm->gmi_cuts == GLP_ON || parm->gmi_cuts == GLP_OFF)) + xerror("glp_intopt: gmi_cuts = %d; invalid parameter\n", + parm->gmi_cuts); + if (!(parm->cov_cuts == GLP_ON || parm->cov_cuts == GLP_OFF)) + xerror("glp_intopt: cov_cuts = %d; invalid parameter\n", + parm->cov_cuts); + if (!(parm->clq_cuts == GLP_ON || parm->clq_cuts == GLP_OFF)) + xerror("glp_intopt: clq_cuts = %d; invalid parameter\n", + parm->clq_cuts); + if (!(parm->presolve == GLP_ON || parm->presolve == GLP_OFF)) + xerror("glp_intopt: presolve = %d; invalid parameter\n", + parm->presolve); + if (!(parm->binarize == GLP_ON || parm->binarize == GLP_OFF)) + xerror("glp_intopt: binarize = %d; invalid parameter\n", + parm->binarize); + if (!(parm->fp_heur == GLP_ON || parm->fp_heur == GLP_OFF)) + xerror("glp_intopt: fp_heur = %d; invalid parameter\n", + parm->fp_heur); +#if 1 /* 28/V-2010 */ + if (!(parm->alien == GLP_ON || parm->alien == GLP_OFF)) + xerror("glp_intopt: alien = %d; invalid parameter\n", + parm->alien); +#endif +#if 0 /* 11/VII-2013 */ + /* integer solution is currently undefined */ + P->mip_stat = GLP_UNDEF; + P->mip_obj = 0.0; +#else + if (!parm->use_sol) + P->mip_stat = GLP_UNDEF; + if (P->mip_stat == GLP_NOFEAS) + P->mip_stat = GLP_UNDEF; + if (P->mip_stat == GLP_UNDEF) + P->mip_obj = 0.0; + else if (P->mip_stat == GLP_OPT) + P->mip_stat = GLP_FEAS; +#endif + /* check bounds of double-bounded variables */ + for (i = 1; i <= P->m; i++) + { GLPROW *row = P->row[i]; + if (row->type == GLP_DB && row->lb >= row->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: row %d: lb = %g, ub = %g; incorrect" + " bounds\n", i, row->lb, row->ub); + ret = GLP_EBOUND; + goto done; + } + } + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if (col->type == GLP_DB && col->lb >= col->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: column %d: lb = %g, ub = %g; incorr" + "ect bounds\n", j, col->lb, col->ub); + ret = GLP_EBOUND; + goto done; + } + } + /* bounds of all integer variables must be integral */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if (col->kind != GLP_IV) continue; + if (col->type == GLP_LO || col->type == GLP_DB) + { if (col->lb != floor(col->lb)) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: integer column %d has non-intege" + "r lower bound %g\n", j, col->lb); + ret = GLP_EBOUND; + goto done; + } + } + if (col->type == GLP_UP || col->type == GLP_DB) + { if (col->ub != floor(col->ub)) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: integer column %d has non-intege" + "r upper bound %g\n", j, col->ub); + ret = GLP_EBOUND; + goto done; + } + } + if (col->type == GLP_FX) + { if (col->lb != floor(col->lb)) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: integer column %d has non-intege" + "r fixed value %g\n", j, col->lb); + ret = GLP_EBOUND; + goto done; + } + } + } + /* solve MIP problem */ + if (parm->msg_lev >= GLP_MSG_ALL) + { int ni = glp_get_num_int(P); + int nb = glp_get_num_bin(P); + char s[50]; + xprintf("GLPK Integer Optimizer, v%s\n", glp_version()); + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", + P->nnz, P->nnz == 1 ? "" : "s"); + if (nb == 0) + strcpy(s, "none of"); + else if (ni == 1 && nb == 1) + strcpy(s, ""); + else if (nb == 1) + strcpy(s, "one of"); + else if (nb == ni) + strcpy(s, "all of"); + else + sprintf(s, "%d of", nb); + xprintf("%d integer variable%s, %s which %s binary\n", + ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are"); + } +#if 1 /* 28/V-2010 */ + if (parm->alien) + { /* use alien integer optimizer */ + ret = _glp_intopt1(P, parm); + goto done; + } +#endif + if (!parm->presolve) +#if 0 /* 11/VII-2013 */ + ret = solve_mip(P, parm); +#else + ret = solve_mip(P, parm, P, NULL); +#endif + else + ret = preprocess_and_solve_mip(P, parm); +done: /* return to the application program */ + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_init_iocp - initialize integer optimizer control parameters +* +* SYNOPSIS +* +* void glp_init_iocp(glp_iocp *parm); +* +* DESCRIPTION +* +* The routine glp_init_iocp initializes control parameters, which are +* used by the integer optimizer, with default values. +* +* Default values of the control parameters are stored in a glp_iocp +* structure, which the parameter parm points to. */ + +void glp_init_iocp(glp_iocp *parm) +{ parm->msg_lev = GLP_MSG_ALL; + parm->br_tech = GLP_BR_DTH; + parm->bt_tech = GLP_BT_BLB; + parm->tol_int = 1e-5; + parm->tol_obj = 1e-7; + parm->tm_lim = INT_MAX; + parm->out_frq = 5000; + parm->out_dly = 10000; + parm->cb_func = NULL; + parm->cb_info = NULL; + parm->cb_size = 0; + parm->pp_tech = GLP_PP_ALL; + parm->mip_gap = 0.0; + parm->mir_cuts = GLP_OFF; + parm->gmi_cuts = GLP_OFF; + parm->cov_cuts = GLP_OFF; + parm->clq_cuts = GLP_OFF; + parm->presolve = GLP_OFF; + parm->binarize = GLP_OFF; + parm->fp_heur = GLP_OFF; +#if 1 /* 25/V-2013 */ + parm->ps_heur = GLP_OFF; +#endif +#if 1 /* 29/VI-2013 */ + parm->ps_tm_lim = 60000; /* 1 minute */ +#endif +#if 1 /* 11/VII-2013 */ + parm->use_sol = GLP_OFF; + parm->save_sol = NULL; +#endif +#if 1 /* 28/V-2010 */ + parm->alien = GLP_OFF; +#endif + return; +} + +/*********************************************************************** +* NAME +* +* glp_mip_status - retrieve status of MIP solution +* +* SYNOPSIS +* +* int glp_mip_status(glp_prob *mip); +* +* RETURNS +* +* The routine lpx_mip_status reports the status of MIP solution found +* by the branch-and-bound solver as follows: +* +* GLP_UNDEF - MIP solution is undefined; +* GLP_OPT - MIP solution is integer optimal; +* GLP_FEAS - MIP solution is integer feasible but its optimality +* (or non-optimality) has not been proven, perhaps due to +* premature termination of the search; +* GLP_NOFEAS - problem has no integer feasible solution (proven by the +* solver). */ + +int glp_mip_status(glp_prob *mip) +{ int mip_stat = mip->mip_stat; + return mip_stat; +} + +/*********************************************************************** +* NAME +* +* glp_mip_obj_val - retrieve objective value (MIP solution) +* +* SYNOPSIS +* +* double glp_mip_obj_val(glp_prob *mip); +* +* RETURNS +* +* The routine glp_mip_obj_val returns value of the objective function +* for MIP solution. */ + +double glp_mip_obj_val(glp_prob *mip) +{ /*struct LPXCPS *cps = mip->cps;*/ + double z; + z = mip->mip_obj; + /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/ + return z; +} + +/*********************************************************************** +* NAME +* +* glp_mip_row_val - retrieve row value (MIP solution) +* +* SYNOPSIS +* +* double glp_mip_row_val(glp_prob *mip, int i); +* +* RETURNS +* +* The routine glp_mip_row_val returns value of the auxiliary variable +* associated with i-th row. */ + +double glp_mip_row_val(glp_prob *mip, int i) +{ /*struct LPXCPS *cps = mip->cps;*/ + double mipx; + if (!(1 <= i && i <= mip->m)) + xerror("glp_mip_row_val: i = %d; row number out of range\n", i) + ; + mipx = mip->row[i]->mipx; + /*if (cps->round && fabs(mipx) < 1e-9) mipx = 0.0;*/ + return mipx; +} + +/*********************************************************************** +* NAME +* +* glp_mip_col_val - retrieve column value (MIP solution) +* +* SYNOPSIS +* +* double glp_mip_col_val(glp_prob *mip, int j); +* +* RETURNS +* +* The routine glp_mip_col_val returns value of the structural variable +* associated with j-th column. */ + +double glp_mip_col_val(glp_prob *mip, int j) +{ /*struct LPXCPS *cps = mip->cps;*/ + double mipx; + if (!(1 <= j && j <= mip->n)) + xerror("glp_mip_col_val: j = %d; column number out of range\n", + j); + mipx = mip->col[j]->mipx; + /*if (cps->round && fabs(mipx) < 1e-9) mipx = 0.0;*/ + return mipx; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi10.c b/resources/3rdparty/glpk-4.53/src/glpapi10.c new file mode 100644 index 000000000..5550aa39f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi10.c @@ -0,0 +1,305 @@ +/* glpapi10.c (solution checking routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +void glp_check_kkt(glp_prob *P, int sol, int cond, double *_ae_max, + int *_ae_ind, double *_re_max, int *_re_ind) +{ /* check feasibility and optimality conditions */ + int m = P->m; + int n = P->n; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, j, ae_ind, re_ind; + double e, sp, sn, t, ae_max, re_max; + if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP)) + xerror("glp_check_kkt: sol = %d; invalid solution indicator\n", + sol); + if (!(cond == GLP_KKT_PE || cond == GLP_KKT_PB || + cond == GLP_KKT_DE || cond == GLP_KKT_DB || + cond == GLP_KKT_CS)) + xerror("glp_check_kkt: cond = %d; invalid condition indicator " + "\n", cond); + ae_max = re_max = 0.0; + ae_ind = re_ind = 0; + if (cond == GLP_KKT_PE) + { /* xR - A * xS = 0 */ + for (i = 1; i <= m; i++) + { row = P->row[i]; + sp = sn = 0.0; + /* t := xR[i] */ + if (sol == GLP_SOL) + t = row->prim; + else if (sol == GLP_IPT) + t = row->pval; + else if (sol == GLP_MIP) + t = row->mipx; + else + xassert(sol != sol); + if (t >= 0.0) sp += t; else sn -= t; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + /* t := - a[i,j] * xS[j] */ + if (sol == GLP_SOL) + t = - aij->val * col->prim; + else if (sol == GLP_IPT) + t = - aij->val * col->pval; + else if (sol == GLP_MIP) + t = - aij->val * col->mipx; + else + xassert(sol != sol); + if (t >= 0.0) sp += t; else sn -= t; + } + /* absolute error */ + e = fabs(sp - sn); + if (ae_max < e) + ae_max = e, ae_ind = i; + /* relative error */ + e /= (1.0 + sp + sn); + if (re_max < e) + re_max = e, re_ind = i; + } + } + else if (cond == GLP_KKT_PB) + { /* lR <= xR <= uR */ + for (i = 1; i <= m; i++) + { row = P->row[i]; + /* t := xR[i] */ + if (sol == GLP_SOL) + t = row->prim; + else if (sol == GLP_IPT) + t = row->pval; + else if (sol == GLP_MIP) + t = row->mipx; + else + xassert(sol != sol); + /* check lower bound */ + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + { if (t < row->lb) + { /* absolute error */ + e = row->lb - t; + if (ae_max < e) + ae_max = e, ae_ind = i; + /* relative error */ + e /= (1.0 + fabs(row->lb)); + if (re_max < e) + re_max = e, re_ind = i; + } + } + /* check upper bound */ + if (row->type == GLP_UP || row->type == GLP_DB || + row->type == GLP_FX) + { if (t > row->ub) + { /* absolute error */ + e = t - row->ub; + if (ae_max < e) + ae_max = e, ae_ind = i; + /* relative error */ + e /= (1.0 + fabs(row->ub)); + if (re_max < e) + re_max = e, re_ind = i; + } + } + } + /* lS <= xS <= uS */ + for (j = 1; j <= n; j++) + { col = P->col[j]; + /* t := xS[j] */ + if (sol == GLP_SOL) + t = col->prim; + else if (sol == GLP_IPT) + t = col->pval; + else if (sol == GLP_MIP) + t = col->mipx; + else + xassert(sol != sol); + /* check lower bound */ + if (col->type == GLP_LO || col->type == GLP_DB || + col->type == GLP_FX) + { if (t < col->lb) + { /* absolute error */ + e = col->lb - t; + if (ae_max < e) + ae_max = e, ae_ind = m+j; + /* relative error */ + e /= (1.0 + fabs(col->lb)); + if (re_max < e) + re_max = e, re_ind = m+j; + } + } + /* check upper bound */ + if (col->type == GLP_UP || col->type == GLP_DB || + col->type == GLP_FX) + { if (t > col->ub) + { /* absolute error */ + e = t - col->ub; + if (ae_max < e) + ae_max = e, ae_ind = m+j; + /* relative error */ + e /= (1.0 + fabs(col->ub)); + if (re_max < e) + re_max = e, re_ind = m+j; + } + } + } + } + else if (cond == GLP_KKT_DE) + { /* A' * (lambdaR - cR) + (lambdaS - cS) = 0 */ + for (j = 1; j <= n; j++) + { col = P->col[j]; + sp = sn = 0.0; + /* t := lambdaS[j] - cS[j] */ + if (sol == GLP_SOL) + t = col->dual - col->coef; + else if (sol == GLP_IPT) + t = col->dval - col->coef; + else + xassert(sol != sol); + if (t >= 0.0) sp += t; else sn -= t; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + { row = aij->row; + /* t := a[i,j] * (lambdaR[i] - cR[i]) */ + if (sol == GLP_SOL) + t = aij->val * row->dual; + else if (sol == GLP_IPT) + t = aij->val * row->dval; + else + xassert(sol != sol); + if (t >= 0.0) sp += t; else sn -= t; + } + /* absolute error */ + e = fabs(sp - sn); + if (ae_max < e) + ae_max = e, ae_ind = m+j; + /* relative error */ + e /= (1.0 + sp + sn); + if (re_max < e) + re_max = e, re_ind = m+j; + } + } + else if (cond == GLP_KKT_DB) + { /* check lambdaR */ + for (i = 1; i <= m; i++) + { row = P->row[i]; + /* t := lambdaR[i] */ + if (sol == GLP_SOL) + t = row->dual; + else if (sol == GLP_IPT) + t = row->dval; + else + xassert(sol != sol); + /* correct sign */ + if (P->dir == GLP_MIN) + t = + t; + else if (P->dir == GLP_MAX) + t = - t; + else + xassert(P != P); + /* check for positivity */ +#if 1 /* 08/III-2013 */ + /* the former check was correct */ + /* the bug reported by David Price is related to violation + of complementarity slackness, not to this condition */ + if (row->type == GLP_FR || row->type == GLP_LO) +#else + if (row->stat == GLP_NF || row->stat == GLP_NL) +#endif + { if (t < 0.0) + { e = - t; + if (ae_max < e) + ae_max = re_max = e, ae_ind = re_ind = i; + } + } + /* check for negativity */ +#if 1 /* 08/III-2013 */ + /* see comment above */ + if (row->type == GLP_FR || row->type == GLP_UP) +#else + if (row->stat == GLP_NF || row->stat == GLP_NU) +#endif + { if (t > 0.0) + { e = + t; + if (ae_max < e) + ae_max = re_max = e, ae_ind = re_ind = i; + } + } + } + /* check lambdaS */ + for (j = 1; j <= n; j++) + { col = P->col[j]; + /* t := lambdaS[j] */ + if (sol == GLP_SOL) + t = col->dual; + else if (sol == GLP_IPT) + t = col->dval; + else + xassert(sol != sol); + /* correct sign */ + if (P->dir == GLP_MIN) + t = + t; + else if (P->dir == GLP_MAX) + t = - t; + else + xassert(P != P); + /* check for positivity */ +#if 1 /* 08/III-2013 */ + /* see comment above */ + if (col->type == GLP_FR || col->type == GLP_LO) +#else + if (col->stat == GLP_NF || col->stat == GLP_NL) +#endif + { if (t < 0.0) + { e = - t; + if (ae_max < e) + ae_max = re_max = e, ae_ind = re_ind = m+j; + } + } + /* check for negativity */ +#if 1 /* 08/III-2013 */ + /* see comment above */ + if (col->type == GLP_FR || col->type == GLP_UP) +#else + if (col->stat == GLP_NF || col->stat == GLP_NU) +#endif + { if (t > 0.0) + { e = + t; + if (ae_max < e) + ae_max = re_max = e, ae_ind = re_ind = m+j; + } + } + } + } + else + xassert(cond != cond); + if (_ae_max != NULL) *_ae_max = ae_max; + if (_ae_ind != NULL) *_ae_ind = ae_ind; + if (_re_max != NULL) *_re_max = re_max; + if (_re_ind != NULL) *_re_ind = re_ind; + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi11.c b/resources/3rdparty/glpk-4.53/src/glpapi11.c new file mode 100644 index 000000000..29876da23 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi11.c @@ -0,0 +1,1235 @@ +/* glpapi11.c (utility routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpsdf.h" +#include "prob.h" + +#define xfprintf glp_format + +int glp_print_sol(glp_prob *P, const char *fname) +{ /* write basic solution in printable format */ + glp_file *fp; + GLPROW *row; + GLPCOL *col; + int i, j, t, ae_ind, re_ind, ret; + double ae_max, re_max; + xprintf("Writing basic solution to `%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "%-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name); + xfprintf(fp, "%-12s%d\n", "Rows:", P->m); + xfprintf(fp, "%-12s%d\n", "Columns:", P->n); + xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); + t = glp_get_status(P); + xfprintf(fp, "%-12s%s\n", "Status:", + t == GLP_OPT ? "OPTIMAL" : + t == GLP_FEAS ? "FEASIBLE" : + t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" : + t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" : + t == GLP_UNBND ? "UNBOUNDED" : + t == GLP_UNDEF ? "UNDEFINED" : "???"); + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->obj_val, + P->dir == GLP_MIN ? "MINimum" : + P->dir == GLP_MAX ? "MAXimum" : "???"); + xfprintf(fp, "\n"); + xfprintf(fp, " No. Row name St Activity Lower bound " + " Upper bound Marginal\n"); + xfprintf(fp, "------ ------------ -- ------------- ------------- " + "------------- -------------\n"); + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + xfprintf(fp, "%6d ", i); + if (row->name == NULL || strlen(row->name) <= 12) + xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); + else + xfprintf(fp, "%s\n%20s", row->name, ""); + xfprintf(fp, "%s ", + row->stat == GLP_BS ? "B " : + row->stat == GLP_NL ? "NL" : + row->stat == GLP_NU ? "NU" : + row->stat == GLP_NF ? "NF" : + row->stat == GLP_NS ? "NS" : "??"); + xfprintf(fp, "%13.6g ", + fabs(row->prim) <= 1e-9 ? 0.0 : row->prim); + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + xfprintf(fp, "%13.6g ", row->lb); + else + xfprintf(fp, "%13s ", ""); + if (row->type == GLP_UP || row->type == GLP_DB) + xfprintf(fp, "%13.6g ", row->ub); + else + xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); + if (row->stat != GLP_BS) + { if (fabs(row->dual) <= 1e-9) + xfprintf(fp, "%13s", "< eps"); + else + xfprintf(fp, "%13.6g ", row->dual); + } + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, " No. Column name St Activity Lower bound " + " Upper bound Marginal\n"); + xfprintf(fp, "------ ------------ -- ------------- ------------- " + "------------- -------------\n"); + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + xfprintf(fp, "%6d ", j); + if (col->name == NULL || strlen(col->name) <= 12) + xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); + else + xfprintf(fp, "%s\n%20s", col->name, ""); + xfprintf(fp, "%s ", + col->stat == GLP_BS ? "B " : + col->stat == GLP_NL ? "NL" : + col->stat == GLP_NU ? "NU" : + col->stat == GLP_NF ? "NF" : + col->stat == GLP_NS ? "NS" : "??"); + xfprintf(fp, "%13.6g ", + fabs(col->prim) <= 1e-9 ? 0.0 : col->prim); + if (col->type == GLP_LO || col->type == GLP_DB || + col->type == GLP_FX) + xfprintf(fp, "%13.6g ", col->lb); + else + xfprintf(fp, "%13s ", ""); + if (col->type == GLP_UP || col->type == GLP_DB) + xfprintf(fp, "%13.6g ", col->ub); + else + xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); + if (col->stat != GLP_BS) + { if (fabs(col->dual) <= 1e-9) + xfprintf(fp, "%13s", "< eps"); + else + xfprintf(fp, "%13.6g ", col->dual); + } + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", + ae_max, ae_ind); + xfprintf(fp, " max.rel.err = %.2e on row %d\n", + re_max, re_ind); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", + ae_max, ae_ind <= P->m ? "row" : "column", + ae_ind <= P->m ? ae_ind : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", + re_max, re_ind <= P->m ? "row" : "column", + re_ind <= P->m ? re_ind : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL" + "E"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n", + ae_max, ae_ind == 0 ? 0 : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on column %d\n", + re_max, re_ind == 0 ? 0 : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n", + ae_max, ae_ind <= P->m ? "row" : "column", + ae_ind <= P->m ? ae_ind : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", + re_max, re_ind <= P->m ? "row" : "column", + re_ind <= P->m ? re_ind : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE") + ; + xfprintf(fp, "\n"); + xfprintf(fp, "End of output\n"); +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_read_sol - read basic solution from text file +* +* SYNOPSIS +* +* int glp_read_sol(glp_prob *lp, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_sol reads basic solution from a text file whose +* name is specified by the parameter fname into the problem object. +* +* For the file format see description of the routine glp_write_sol. +* +* RETURNS +* +* On success the routine returns zero, otherwise non-zero. */ + +int glp_read_sol(glp_prob *lp, const char *fname) +{ glp_data *data; + jmp_buf jump; + int i, j, k, ret = 0; + xprintf("Reading basic solution from `%s'...\n", fname); + data = glp_sdf_open_file(fname); + if (data == NULL) + { ret = 1; + goto done; + } + if (setjmp(jump)) + { ret = 1; + goto done; + } + glp_sdf_set_jump(data, jump); + /* number of rows, number of columns */ + k = glp_sdf_read_int(data); + if (k != lp->m) + glp_sdf_error(data, "wrong number of rows\n"); + k = glp_sdf_read_int(data); + if (k != lp->n) + glp_sdf_error(data, "wrong number of columns\n"); + /* primal status, dual status, objective value */ + k = glp_sdf_read_int(data); + if (!(k == GLP_UNDEF || k == GLP_FEAS || k == GLP_INFEAS || + k == GLP_NOFEAS)) + glp_sdf_error(data, "invalid primal status\n"); + lp->pbs_stat = k; + k = glp_sdf_read_int(data); + if (!(k == GLP_UNDEF || k == GLP_FEAS || k == GLP_INFEAS || + k == GLP_NOFEAS)) + glp_sdf_error(data, "invalid dual status\n"); + lp->dbs_stat = k; + lp->obj_val = glp_sdf_read_num(data); + /* rows (auxiliary variables) */ + for (i = 1; i <= lp->m; i++) + { GLPROW *row = lp->row[i]; + /* status, primal value, dual value */ + k = glp_sdf_read_int(data); + if (!(k == GLP_BS || k == GLP_NL || k == GLP_NU || + k == GLP_NF || k == GLP_NS)) + glp_sdf_error(data, "invalid row status\n"); + glp_set_row_stat(lp, i, k); + row->prim = glp_sdf_read_num(data); + row->dual = glp_sdf_read_num(data); + } + /* columns (structural variables) */ + for (j = 1; j <= lp->n; j++) + { GLPCOL *col = lp->col[j]; + /* status, primal value, dual value */ + k = glp_sdf_read_int(data); + if (!(k == GLP_BS || k == GLP_NL || k == GLP_NU || + k == GLP_NF || k == GLP_NS)) + glp_sdf_error(data, "invalid column status\n"); + glp_set_col_stat(lp, j, k); + col->prim = glp_sdf_read_num(data); + col->dual = glp_sdf_read_num(data); + } + xprintf("%d lines were read\n", glp_sdf_line(data)); +done: if (ret) lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; + if (data != NULL) glp_sdf_close_file(data); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_sol - write basic solution to text file +* +* SYNOPSIS +* +* int glp_write_sol(glp_prob *lp, const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_sol writes the current basic solution to a +* text file whose name is specified by the parameter fname. This file +* can be read back with the routine glp_read_sol. +* +* RETURNS +* +* On success the routine returns zero, otherwise non-zero. +* +* FILE FORMAT +* +* The file created by the routine glp_write_sol is a plain text file, +* which contains the following information: +* +* m n +* p_stat d_stat obj_val +* r_stat[1] r_prim[1] r_dual[1] +* . . . +* r_stat[m] r_prim[m] r_dual[m] +* c_stat[1] c_prim[1] c_dual[1] +* . . . +* c_stat[n] c_prim[n] c_dual[n] +* +* where: +* m is the number of rows (auxiliary variables); +* n is the number of columns (structural variables); +* p_stat is the primal status of the basic solution (GLP_UNDEF = 1, +* GLP_FEAS = 2, GLP_INFEAS = 3, or GLP_NOFEAS = 4); +* d_stat is the dual status of the basic solution (GLP_UNDEF = 1, +* GLP_FEAS = 2, GLP_INFEAS = 3, or GLP_NOFEAS = 4); +* obj_val is the objective value; +* r_stat[i], i = 1,...,m, is the status of i-th row (GLP_BS = 1, +* GLP_NL = 2, GLP_NU = 3, GLP_NF = 4, or GLP_NS = 5); +* r_prim[i], i = 1,...,m, is the primal value of i-th row; +* r_dual[i], i = 1,...,m, is the dual value of i-th row; +* c_stat[j], j = 1,...,n, is the status of j-th column (GLP_BS = 1, +* GLP_NL = 2, GLP_NU = 3, GLP_NF = 4, or GLP_NS = 5); +* c_prim[j], j = 1,...,n, is the primal value of j-th column; +* c_dual[j], j = 1,...,n, is the dual value of j-th column. */ + +int glp_write_sol(glp_prob *lp, const char *fname) +{ glp_file *fp; + int i, j, ret = 0; + xprintf("Writing basic solution to `%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* number of rows, number of columns */ + xfprintf(fp, "%d %d\n", lp->m, lp->n); + /* primal status, dual status, objective value */ + xfprintf(fp, "%d %d %.*g\n", lp->pbs_stat, lp->dbs_stat, DBL_DIG, + lp->obj_val); + /* rows (auxiliary variables) */ + for (i = 1; i <= lp->m; i++) + { GLPROW *row = lp->row[i]; + /* status, primal value, dual value */ + xfprintf(fp, "%d %.*g %.*g\n", row->stat, DBL_DIG, row->prim, + DBL_DIG, row->dual); + } + /* columns (structural variables) */ + for (j = 1; j <= lp->n; j++) + { GLPCOL *col = lp->col[j]; + /* status, primal value, dual value */ + xfprintf(fp, "%d %.*g %.*g\n", col->stat, DBL_DIG, col->prim, + DBL_DIG, col->dual); + } +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", 2 + lp->m + lp->n); +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/**********************************************************************/ + +static char *format(char buf[13+1], double x) +{ /* format floating-point number in MPS/360-like style */ + if (x == -DBL_MAX) + strcpy(buf, " -Inf"); + else if (x == +DBL_MAX) + strcpy(buf, " +Inf"); + else if (fabs(x) <= 999999.99998) + { sprintf(buf, "%13.5f", x); +#if 1 + if (strcmp(buf, " 0.00000") == 0 || + strcmp(buf, " -0.00000") == 0) + strcpy(buf, " . "); + else if (memcmp(buf, " 0.", 8) == 0) + memcpy(buf, " .", 8); + else if (memcmp(buf, " -0.", 8) == 0) + memcpy(buf, " -.", 8); +#endif + } + else + sprintf(buf, "%13.6g", x); + return buf; +} + +int glp_print_ranges(glp_prob *P, int len, const int list[], + int flags, const char *fname) +{ /* print sensitivity analysis report */ + glp_file *fp = NULL; + GLPROW *row; + GLPCOL *col; + int m, n, pass, k, t, numb, type, stat, var1, var2, count, page, + ret; + double lb, ub, slack, coef, prim, dual, value1, value2, coef1, + coef2, obj1, obj2; + const char *name, *limit; + char buf[13+1]; + /* sanity checks */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_print_ranges: P = %p; invalid problem object\n", + P); + m = P->m, n = P->n; + if (len < 0) + xerror("glp_print_ranges: len = %d; invalid list length\n", + len); + if (len > 0) + { if (list == NULL) + xerror("glp_print_ranges: list = %p: invalid parameter\n", + list); + for (t = 1; t <= len; t++) + { k = list[t]; + if (!(1 <= k && k <= m+n)) + xerror("glp_print_ranges: list[%d] = %d; row/column numb" + "er out of range\n", t, k); + } + } + if (flags != 0) + xerror("glp_print_ranges: flags = %d; invalid parameter\n", + flags); + if (fname == NULL) + xerror("glp_print_ranges: fname = %p; invalid parameter\n", + fname); + if (glp_get_status(P) != GLP_OPT) + { xprintf("glp_print_ranges: optimal basic solution required\n"); + ret = 1; + goto done; + } + if (!glp_bf_exists(P)) + { xprintf("glp_print_ranges: basis factorization required\n"); + ret = 2; + goto done; + } + /* start reporting */ + xprintf("Write sensitivity analysis report to `%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 3; + goto done; + } + page = count = 0; + for (pass = 1; pass <= 2; pass++) + for (t = 1; t <= (len == 0 ? m+n : len); t++) + { if (t == 1) count = 0; + k = (len == 0 ? t : list[t]); + if (pass == 1 && k > m || pass == 2 && k <= m) + continue; + if (count == 0) + { xfprintf(fp, "GLPK %-4s - SENSITIVITY ANALYSIS REPORT%73sPa" + "ge%4d\n", glp_version(), "", ++page); + xfprintf(fp, "\n"); + xfprintf(fp, "%-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name); + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->obj_val, + P->dir == GLP_MIN ? "MINimum" : + P->dir == GLP_MAX ? "MAXimum" : "???"); + xfprintf(fp, "\n"); + xfprintf(fp, "%6s %-12s %2s %13s %13s %13s %13s %13s %13s " + "%s\n", "No.", pass == 1 ? "Row name" : "Column name", + "St", "Activity", pass == 1 ? "Slack" : "Obj coef", + "Lower bound", "Activity", "Obj coef", "Obj value at", + "Limiting"); + xfprintf(fp, "%6s %-12s %2s %13s %13s %13s %13s %13s %13s " + "%s\n", "", "", "", "", "Marginal", "Upper bound", + "range", "range", "break point", "variable"); + xfprintf(fp, "------ ------------ -- ------------- --------" + "----- ------------- ------------- ------------- ------" + "------- ------------\n"); + } + if (pass == 1) + { numb = k; + xassert(1 <= numb && numb <= m); + row = P->row[numb]; + name = row->name; + type = row->type; + lb = glp_get_row_lb(P, numb); + ub = glp_get_row_ub(P, numb); + coef = 0.0; + stat = row->stat; + prim = row->prim; + if (type == GLP_FR) + slack = - prim; + else if (type == GLP_LO) + slack = lb - prim; + else if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + slack = ub - prim; + dual = row->dual; + } + else + { numb = k - m; + xassert(1 <= numb && numb <= n); + col = P->col[numb]; + name = col->name; + lb = glp_get_col_lb(P, numb); + ub = glp_get_col_ub(P, numb); + coef = col->coef; + stat = col->stat; + prim = col->prim; + slack = 0.0; + dual = col->dual; + } + if (stat != GLP_BS) + { glp_analyze_bound(P, k, &value1, &var1, &value2, &var2); + if (stat == GLP_NF) + coef1 = coef2 = coef; + else if (stat == GLP_NS) + coef1 = -DBL_MAX, coef2 = +DBL_MAX; + else if (stat == GLP_NL && P->dir == GLP_MIN || + stat == GLP_NU && P->dir == GLP_MAX) + coef1 = coef - dual, coef2 = +DBL_MAX; + else + coef1 = -DBL_MAX, coef2 = coef - dual; + if (value1 == -DBL_MAX) + { if (dual < -1e-9) + obj1 = +DBL_MAX; + else if (dual > +1e-9) + obj1 = -DBL_MAX; + else + obj1 = P->obj_val; + } + else + obj1 = P->obj_val + dual * (value1 - prim); + if (value2 == +DBL_MAX) + { if (dual < -1e-9) + obj2 = -DBL_MAX; + else if (dual > +1e-9) + obj2 = +DBL_MAX; + else + obj2 = P->obj_val; + } + else + obj2 = P->obj_val + dual * (value2 - prim); + } + else + { glp_analyze_coef(P, k, &coef1, &var1, &value1, &coef2, + &var2, &value2); + if (coef1 == -DBL_MAX) + { if (prim < -1e-9) + obj1 = +DBL_MAX; + else if (prim > +1e-9) + obj1 = -DBL_MAX; + else + obj1 = P->obj_val; + } + else + obj1 = P->obj_val + (coef1 - coef) * prim; + if (coef2 == +DBL_MAX) + { if (prim < -1e-9) + obj2 = -DBL_MAX; + else if (prim > +1e-9) + obj2 = +DBL_MAX; + else + obj2 = P->obj_val; + } + else + obj2 = P->obj_val + (coef2 - coef) * prim; + } + /*** first line ***/ + /* row/column number */ + xfprintf(fp, "%6d", numb); + /* row/column name */ + xfprintf(fp, " %-12.12s", name == NULL ? "" : name); + if (name != NULL && strlen(name) > 12) + xfprintf(fp, "%s\n%6s %12s", name+12, "", ""); + /* row/column status */ + xfprintf(fp, " %2s", + stat == GLP_BS ? "BS" : stat == GLP_NL ? "NL" : + stat == GLP_NU ? "NU" : stat == GLP_NF ? "NF" : + stat == GLP_NS ? "NS" : "??"); + /* row/column activity */ + xfprintf(fp, " %s", format(buf, prim)); + /* row slack, column objective coefficient */ + xfprintf(fp, " %s", format(buf, k <= m ? slack : coef)); + /* row/column lower bound */ + xfprintf(fp, " %s", format(buf, lb)); + /* row/column activity range */ + xfprintf(fp, " %s", format(buf, value1)); + /* row/column objective coefficient range */ + xfprintf(fp, " %s", format(buf, coef1)); + /* objective value at break point */ + xfprintf(fp, " %s", format(buf, obj1)); + /* limiting variable name */ + if (var1 != 0) + { if (var1 <= m) + limit = glp_get_row_name(P, var1); + else + limit = glp_get_col_name(P, var1 - m); + if (limit != NULL) + xfprintf(fp, " %s", limit); + } + xfprintf(fp, "\n"); + /*** second line ***/ + xfprintf(fp, "%6s %-12s %2s %13s", "", "", "", ""); + /* row/column reduced cost */ + xfprintf(fp, " %s", format(buf, dual)); + /* row/column upper bound */ + xfprintf(fp, " %s", format(buf, ub)); + /* row/column activity range */ + xfprintf(fp, " %s", format(buf, value2)); + /* row/column objective coefficient range */ + xfprintf(fp, " %s", format(buf, coef2)); + /* objective value at break point */ + xfprintf(fp, " %s", format(buf, obj2)); + /* limiting variable name */ + if (var2 != 0) + { if (var2 <= m) + limit = glp_get_row_name(P, var2); + else + limit = glp_get_col_name(P, var2 - m); + if (limit != NULL) + xfprintf(fp, " %s", limit); + } + xfprintf(fp, "\n"); + xfprintf(fp, "\n"); + /* print 10 items per page */ + count = (count + 1) % 10; + } + xfprintf(fp, "End of report\n"); +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 4; + goto done; + } + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/**********************************************************************/ + +int glp_print_ipt(glp_prob *P, const char *fname) +{ /* write interior-point solution in printable format */ + glp_file *fp; + GLPROW *row; + GLPCOL *col; + int i, j, t, ae_ind, re_ind, ret; + double ae_max, re_max; + xprintf("Writing interior-point solution to `%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "%-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name); + xfprintf(fp, "%-12s%d\n", "Rows:", P->m); + xfprintf(fp, "%-12s%d\n", "Columns:", P->n); + xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); + t = glp_ipt_status(P); + xfprintf(fp, "%-12s%s\n", "Status:", + t == GLP_OPT ? "OPTIMAL" : + t == GLP_UNDEF ? "UNDEFINED" : + t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" : + t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" : "???"); + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->ipt_obj, + P->dir == GLP_MIN ? "MINimum" : + P->dir == GLP_MAX ? "MAXimum" : "???"); + xfprintf(fp, "\n"); + xfprintf(fp, " No. Row name Activity Lower bound " + " Upper bound Marginal\n"); + xfprintf(fp, "------ ------------ ------------- ------------- " + "------------- -------------\n"); + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + xfprintf(fp, "%6d ", i); + if (row->name == NULL || strlen(row->name) <= 12) + xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); + else + xfprintf(fp, "%s\n%20s", row->name, ""); + xfprintf(fp, "%3s", ""); + xfprintf(fp, "%13.6g ", + fabs(row->pval) <= 1e-9 ? 0.0 : row->pval); + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + xfprintf(fp, "%13.6g ", row->lb); + else + xfprintf(fp, "%13s ", ""); + if (row->type == GLP_UP || row->type == GLP_DB) + xfprintf(fp, "%13.6g ", row->ub); + else + xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); + if (fabs(row->dval) <= 1e-9) + xfprintf(fp, "%13s", "< eps"); + else + xfprintf(fp, "%13.6g ", row->dval); + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, " No. Column name Activity Lower bound " + " Upper bound Marginal\n"); + xfprintf(fp, "------ ------------ ------------- ------------- " + "------------- -------------\n"); + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + xfprintf(fp, "%6d ", j); + if (col->name == NULL || strlen(col->name) <= 12) + xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); + else + xfprintf(fp, "%s\n%20s", col->name, ""); + xfprintf(fp, "%3s", ""); + xfprintf(fp, "%13.6g ", + fabs(col->pval) <= 1e-9 ? 0.0 : col->pval); + if (col->type == GLP_LO || col->type == GLP_DB || + col->type == GLP_FX) + xfprintf(fp, "%13.6g ", col->lb); + else + xfprintf(fp, "%13s ", ""); + if (col->type == GLP_UP || col->type == GLP_DB) + xfprintf(fp, "%13.6g ", col->ub); + else + xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); + if (fabs(col->dval) <= 1e-9) + xfprintf(fp, "%13s", "< eps"); + else + xfprintf(fp, "%13.6g ", col->dval); + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_IPT, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", + ae_max, ae_ind); + xfprintf(fp, " max.rel.err = %.2e on row %d\n", + re_max, re_ind); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_IPT, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", + ae_max, ae_ind <= P->m ? "row" : "column", + ae_ind <= P->m ? ae_ind : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", + re_max, re_ind <= P->m ? "row" : "column", + re_ind <= P->m ? re_ind : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL" + "E"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_IPT, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n", + ae_max, ae_ind == 0 ? 0 : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on column %d\n", + re_max, re_ind == 0 ? 0 : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_IPT, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n", + ae_max, ae_ind <= P->m ? "row" : "column", + ae_ind <= P->m ? ae_ind : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", + re_max, re_ind <= P->m ? "row" : "column", + re_ind <= P->m ? re_ind : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE") + ; + xfprintf(fp, "\n"); + xfprintf(fp, "End of output\n"); +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_read_ipt - read interior-point solution from text file +* +* SYNOPSIS +* +* int glp_read_ipt(glp_prob *lp, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_ipt reads interior-point solution from a text +* file whose name is specified by the parameter fname into the problem +* object. +* +* For the file format see description of the routine glp_write_ipt. +* +* RETURNS +* +* On success the routine returns zero, otherwise non-zero. */ + +int glp_read_ipt(glp_prob *lp, const char *fname) +{ glp_data *data; + jmp_buf jump; + int i, j, k, ret = 0; + xprintf("Reading interior-point solution from `%s'...\n", fname); + data = glp_sdf_open_file(fname); + if (data == NULL) + { ret = 1; + goto done; + } + if (setjmp(jump)) + { ret = 1; + goto done; + } + glp_sdf_set_jump(data, jump); + /* number of rows, number of columns */ + k = glp_sdf_read_int(data); + if (k != lp->m) + glp_sdf_error(data, "wrong number of rows\n"); + k = glp_sdf_read_int(data); + if (k != lp->n) + glp_sdf_error(data, "wrong number of columns\n"); + /* solution status, objective value */ + k = glp_sdf_read_int(data); + if (!(k == GLP_UNDEF || k == GLP_OPT)) + glp_sdf_error(data, "invalid solution status\n"); + lp->ipt_stat = k; + lp->ipt_obj = glp_sdf_read_num(data); + /* rows (auxiliary variables) */ + for (i = 1; i <= lp->m; i++) + { GLPROW *row = lp->row[i]; + /* primal value, dual value */ + row->pval = glp_sdf_read_num(data); + row->dval = glp_sdf_read_num(data); + } + /* columns (structural variables) */ + for (j = 1; j <= lp->n; j++) + { GLPCOL *col = lp->col[j]; + /* primal value, dual value */ + col->pval = glp_sdf_read_num(data); + col->dval = glp_sdf_read_num(data); + } + xprintf("%d lines were read\n", glp_sdf_line(data)); +done: if (ret) lp->ipt_stat = GLP_UNDEF; + if (data != NULL) glp_sdf_close_file(data); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_ipt - write interior-point solution to text file +* +* SYNOPSIS +* +* int glp_write_ipt(glp_prob *lp, const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_ipt writes the current interior-point solution +* to a text file whose name is specified by the parameter fname. This +* file can be read back with the routine glp_read_ipt. +* +* RETURNS +* +* On success the routine returns zero, otherwise non-zero. +* +* FILE FORMAT +* +* The file created by the routine glp_write_ipt is a plain text file, +* which contains the following information: +* +* m n +* stat obj_val +* r_prim[1] r_dual[1] +* . . . +* r_prim[m] r_dual[m] +* c_prim[1] c_dual[1] +* . . . +* c_prim[n] c_dual[n] +* +* where: +* m is the number of rows (auxiliary variables); +* n is the number of columns (structural variables); +* stat is the solution status (GLP_UNDEF = 1 or GLP_OPT = 5); +* obj_val is the objective value; +* r_prim[i], i = 1,...,m, is the primal value of i-th row; +* r_dual[i], i = 1,...,m, is the dual value of i-th row; +* c_prim[j], j = 1,...,n, is the primal value of j-th column; +* c_dual[j], j = 1,...,n, is the dual value of j-th column. */ + +int glp_write_ipt(glp_prob *lp, const char *fname) +{ glp_file *fp; + int i, j, ret = 0; + xprintf("Writing interior-point solution to `%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* number of rows, number of columns */ + xfprintf(fp, "%d %d\n", lp->m, lp->n); + /* solution status, objective value */ + xfprintf(fp, "%d %.*g\n", lp->ipt_stat, DBL_DIG, lp->ipt_obj); + /* rows (auxiliary variables) */ + for (i = 1; i <= lp->m; i++) + { GLPROW *row = lp->row[i]; + /* primal value, dual value */ + xfprintf(fp, "%.*g %.*g\n", DBL_DIG, row->pval, DBL_DIG, + row->dval); + } + /* columns (structural variables) */ + for (j = 1; j <= lp->n; j++) + { GLPCOL *col = lp->col[j]; + /* primal value, dual value */ + xfprintf(fp, "%.*g %.*g\n", DBL_DIG, col->pval, DBL_DIG, + col->dval); + } +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", 2 + lp->m + lp->n); +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/**********************************************************************/ + +int glp_print_mip(glp_prob *P, const char *fname) +{ /* write MIP solution in printable format */ + glp_file *fp; + GLPROW *row; + GLPCOL *col; + int i, j, t, ae_ind, re_ind, ret; + double ae_max, re_max; + xprintf("Writing MIP solution to `%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "%-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name); + xfprintf(fp, "%-12s%d\n", "Rows:", P->m); + xfprintf(fp, "%-12s%d (%d integer, %d binary)\n", "Columns:", + P->n, glp_get_num_int(P), glp_get_num_bin(P)); + xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); + t = glp_mip_status(P); + xfprintf(fp, "%-12s%s\n", "Status:", + t == GLP_OPT ? "INTEGER OPTIMAL" : + t == GLP_FEAS ? "INTEGER NON-OPTIMAL" : + t == GLP_NOFEAS ? "INTEGER EMPTY" : + t == GLP_UNDEF ? "INTEGER UNDEFINED" : "???"); + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->mip_obj, + P->dir == GLP_MIN ? "MINimum" : + P->dir == GLP_MAX ? "MAXimum" : "???"); + xfprintf(fp, "\n"); + xfprintf(fp, " No. Row name Activity Lower bound " + " Upper bound\n"); + xfprintf(fp, "------ ------------ ------------- ------------- " + "-------------\n"); + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + xfprintf(fp, "%6d ", i); + if (row->name == NULL || strlen(row->name) <= 12) + xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); + else + xfprintf(fp, "%s\n%20s", row->name, ""); + xfprintf(fp, "%3s", ""); + xfprintf(fp, "%13.6g ", + fabs(row->mipx) <= 1e-9 ? 0.0 : row->mipx); + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + xfprintf(fp, "%13.6g ", row->lb); + else + xfprintf(fp, "%13s ", ""); + if (row->type == GLP_UP || row->type == GLP_DB) + xfprintf(fp, "%13.6g ", row->ub); + else + xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, " No. Column name Activity Lower bound " + " Upper bound\n"); + xfprintf(fp, "------ ------------ ------------- ------------- " + "-------------\n"); + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + xfprintf(fp, "%6d ", j); + if (col->name == NULL || strlen(col->name) <= 12) + xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); + else + xfprintf(fp, "%s\n%20s", col->name, ""); + xfprintf(fp, "%s ", + col->kind == GLP_CV ? " " : + col->kind == GLP_IV ? "*" : "?"); + xfprintf(fp, "%13.6g ", + fabs(col->mipx) <= 1e-9 ? 0.0 : col->mipx); + if (col->type == GLP_LO || col->type == GLP_DB || + col->type == GLP_FX) + xfprintf(fp, "%13.6g ", col->lb); + else + xfprintf(fp, "%13s ", ""); + if (col->type == GLP_UP || col->type == GLP_DB) + xfprintf(fp, "%13.6g ", col->ub); + else + xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, "Integer feasibility conditions:\n"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", + ae_max, ae_ind); + xfprintf(fp, " max.rel.err = %.2e on row %d\n", + re_max, re_ind); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "SOLUTION IS WRONG"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", + ae_max, ae_ind <= P->m ? "row" : "column", + ae_ind <= P->m ? ae_ind : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", + re_max, re_ind <= P->m ? "row" : "column", + re_ind <= P->m ? re_ind : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "SOLUTION IS INFEASIBLE"); + xfprintf(fp, "\n"); + xfprintf(fp, "End of output\n"); +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_read_mip - read MIP solution from text file +* +* SYNOPSIS +* +* int glp_read_mip(glp_prob *mip, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_mip reads MIP solution from a text file whose +* name is specified by the parameter fname into the problem object. +* +* For the file format see description of the routine glp_write_mip. +* +* RETURNS +* +* On success the routine returns zero, otherwise non-zero. */ + +int glp_read_mip(glp_prob *mip, const char *fname) +{ glp_data *data; + jmp_buf jump; + int i, j, k, ret = 0; + xprintf("Reading MIP solution from `%s'...\n", fname); + data = glp_sdf_open_file(fname); + if (data == NULL) + { ret = 1; + goto done; + } + if (setjmp(jump)) + { ret = 1; + goto done; + } + glp_sdf_set_jump(data, jump); + /* number of rows, number of columns */ + k = glp_sdf_read_int(data); + if (k != mip->m) + glp_sdf_error(data, "wrong number of rows\n"); + k = glp_sdf_read_int(data); + if (k != mip->n) + glp_sdf_error(data, "wrong number of columns\n"); + /* solution status, objective value */ + k = glp_sdf_read_int(data); + if (!(k == GLP_UNDEF || k == GLP_OPT || k == GLP_FEAS || + k == GLP_NOFEAS)) + glp_sdf_error(data, "invalid solution status\n"); + mip->mip_stat = k; + mip->mip_obj = glp_sdf_read_num(data); + /* rows (auxiliary variables) */ + for (i = 1; i <= mip->m; i++) + { GLPROW *row = mip->row[i]; + row->mipx = glp_sdf_read_num(data); + } + /* columns (structural variables) */ + for (j = 1; j <= mip->n; j++) + { GLPCOL *col = mip->col[j]; + col->mipx = glp_sdf_read_num(data); + if (col->kind == GLP_IV && col->mipx != floor(col->mipx)) + glp_sdf_error(data, "non-integer column value"); + } + xprintf("%d lines were read\n", glp_sdf_line(data)); +done: if (ret) mip->mip_stat = GLP_UNDEF; + if (data != NULL) glp_sdf_close_file(data); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_mip - write MIP solution to text file +* +* SYNOPSIS +* +* int glp_write_mip(glp_prob *mip, const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_mip writes the current MIP solution to a text +* file whose name is specified by the parameter fname. This file can +* be read back with the routine glp_read_mip. +* +* RETURNS +* +* On success the routine returns zero, otherwise non-zero. +* +* FILE FORMAT +* +* The file created by the routine glp_write_sol is a plain text file, +* which contains the following information: +* +* m n +* stat obj_val +* r_val[1] +* . . . +* r_val[m] +* c_val[1] +* . . . +* c_val[n] +* +* where: +* m is the number of rows (auxiliary variables); +* n is the number of columns (structural variables); +* stat is the solution status (GLP_UNDEF = 1, GLP_FEAS = 2, +* GLP_NOFEAS = 4, or GLP_OPT = 5); +* obj_val is the objective value; +* r_val[i], i = 1,...,m, is the value of i-th row; +* c_val[j], j = 1,...,n, is the value of j-th column. */ + +int glp_write_mip(glp_prob *mip, const char *fname) +{ glp_file *fp; + int i, j, ret = 0; + xprintf("Writing MIP solution to `%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* number of rows, number of columns */ + xfprintf(fp, "%d %d\n", mip->m, mip->n); + /* solution status, objective value */ + xfprintf(fp, "%d %.*g\n", mip->mip_stat, DBL_DIG, mip->mip_obj); + /* rows (auxiliary variables) */ + for (i = 1; i <= mip->m; i++) + xfprintf(fp, "%.*g\n", DBL_DIG, mip->row[i]->mipx); + /* columns (structural variables) */ + for (j = 1; j <= mip->n; j++) + xfprintf(fp, "%.*g\n", DBL_DIG, mip->col[j]->mipx); +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", 2 + mip->m + mip->n); +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi12.c b/resources/3rdparty/glpk-4.53/src/glpapi12.c new file mode 100644 index 000000000..8c2ff9073 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi12.c @@ -0,0 +1,2237 @@ +/* glpapi12.c (basis factorization and simplex tableau routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "draft.h" +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_bf_exists - check if the basis factorization exists +* +* SYNOPSIS +* +* int glp_bf_exists(glp_prob *lp); +* +* RETURNS +* +* If the basis factorization for the current basis associated with +* the specified problem object exists and therefore is available for +* computations, the routine glp_bf_exists returns non-zero. Otherwise +* the routine returns zero. */ + +int glp_bf_exists(glp_prob *lp) +{ int ret; + ret = (lp->m == 0 || lp->valid); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_factorize - compute the basis factorization +* +* SYNOPSIS +* +* int glp_factorize(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_factorize computes the basis factorization for the +* current basis associated with the specified problem object. +* +* RETURNS +* +* 0 The basis factorization has been successfully computed. +* +* GLP_EBADB +* The basis matrix is invalid, i.e. the number of basic (auxiliary +* and structural) variables differs from the number of rows in the +* problem object. +* +* GLP_ESING +* The basis matrix is singular within the working precision. +* +* GLP_ECOND +* The basis matrix is ill-conditioned. */ + +static int b_col(void *info, int j, int ind[], double val[]) +{ glp_prob *lp = info; + int m = lp->m; + GLPAIJ *aij; + int k, len; + xassert(1 <= j && j <= m); + /* determine the ordinal number of basic auxiliary or structural + variable x[k] corresponding to basic variable xB[j] */ + k = lp->head[j]; + /* build j-th column of the basic matrix, which is k-th column of + the scaled augmented matrix (I | -R*A*S) */ + if (k <= m) + { /* x[k] is auxiliary variable */ + len = 1; + ind[1] = k; + val[1] = 1.0; + } + else + { /* x[k] is structural variable */ + len = 0; + for (aij = lp->col[k-m]->ptr; aij != NULL; aij = aij->c_next) + { len++; + ind[len] = aij->row->i; + val[len] = - aij->row->rii * aij->val * aij->col->sjj; + } + } + return len; +} + +static void copy_bfcp(glp_prob *lp); + +int glp_factorize(glp_prob *lp) +{ int m = lp->m; + int n = lp->n; + GLPROW **row = lp->row; + GLPCOL **col = lp->col; + int *head = lp->head; + int j, k, stat, ret; + /* invalidate the basis factorization */ + lp->valid = 0; + /* build the basis header */ + j = 0; + for (k = 1; k <= m+n; k++) + { if (k <= m) + { stat = row[k]->stat; + row[k]->bind = 0; + } + else + { stat = col[k-m]->stat; + col[k-m]->bind = 0; + } + if (stat == GLP_BS) + { j++; + if (j > m) + { /* too many basic variables */ + ret = GLP_EBADB; + goto fini; + } + head[j] = k; + if (k <= m) + row[k]->bind = j; + else + col[k-m]->bind = j; + } + } + if (j < m) + { /* too few basic variables */ + ret = GLP_EBADB; + goto fini; + } + /* try to factorize the basis matrix */ + if (m > 0) + { if (lp->bfd == NULL) + { lp->bfd = bfd_create_it(); + copy_bfcp(lp); + } + switch (bfd_factorize(lp->bfd, m, lp->head, b_col, lp)) + { case 0: + /* ok */ + break; + case BFD_ESING: + /* singular matrix */ + ret = GLP_ESING; + goto fini; + case BFD_ECOND: + /* ill-conditioned matrix */ + ret = GLP_ECOND; + goto fini; + default: + xassert(lp != lp); + } + lp->valid = 1; + } + /* factorization successful */ + ret = 0; +fini: /* bring the return code to the calling program */ + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_bf_updated - check if the basis factorization has been updated +* +* SYNOPSIS +* +* int glp_bf_updated(glp_prob *lp); +* +* RETURNS +* +* If the basis factorization has been just computed from scratch, the +* routine glp_bf_updated returns zero. Otherwise, if the factorization +* has been updated one or more times, the routine returns non-zero. */ + +int glp_bf_updated(glp_prob *lp) +{ int cnt; + if (!(lp->m == 0 || lp->valid)) + xerror("glp_bf_update: basis factorization does not exist\n"); +#if 0 /* 15/XI-2009 */ + cnt = (lp->m == 0 ? 0 : lp->bfd->upd_cnt); +#else + cnt = (lp->m == 0 ? 0 : bfd_get_count(lp->bfd)); +#endif + return cnt; +} + +/*********************************************************************** +* NAME +* +* glp_get_bfcp - retrieve basis factorization control parameters +* +* SYNOPSIS +* +* void glp_get_bfcp(glp_prob *lp, glp_bfcp *parm); +* +* DESCRIPTION +* +* The routine glp_get_bfcp retrieves control parameters, which are +* used on computing and updating the basis factorization associated +* with the specified problem object. +* +* Current values of control parameters are stored by the routine in +* a glp_bfcp structure, which the parameter parm points to. */ + +void glp_get_bfcp(glp_prob *lp, glp_bfcp *parm) +{ glp_bfcp *bfcp = lp->bfcp; + if (bfcp == NULL) + { parm->type = GLP_BF_FT; + parm->lu_size = 0; + parm->piv_tol = 0.10; + parm->piv_lim = 4; + parm->suhl = GLP_ON; + parm->eps_tol = 1e-15; + parm->max_gro = 1e+10; + parm->nfs_max = 100; + parm->upd_tol = 1e-6; + parm->nrs_max = 100; + parm->rs_size = 0; + } + else + memcpy(parm, bfcp, sizeof(glp_bfcp)); + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_bfcp - change basis factorization control parameters +* +* SYNOPSIS +* +* void glp_set_bfcp(glp_prob *lp, const glp_bfcp *parm); +* +* DESCRIPTION +* +* The routine glp_set_bfcp changes control parameters, which are used +* by internal GLPK routines in computing and updating the basis +* factorization associated with the specified problem object. +* +* New values of the control parameters should be passed in a structure +* glp_bfcp, which the parameter parm points to. +* +* The parameter parm can be specified as NULL, in which case all +* control parameters are reset to their default values. */ + +#if 0 /* 15/XI-2009 */ +static void copy_bfcp(glp_prob *lp) +{ glp_bfcp _parm, *parm = &_parm; + BFD *bfd = lp->bfd; + glp_get_bfcp(lp, parm); + xassert(bfd != NULL); + bfd->type = parm->type; + bfd->lu_size = parm->lu_size; + bfd->piv_tol = parm->piv_tol; + bfd->piv_lim = parm->piv_lim; + bfd->suhl = parm->suhl; + bfd->eps_tol = parm->eps_tol; + bfd->max_gro = parm->max_gro; + bfd->nfs_max = parm->nfs_max; + bfd->upd_tol = parm->upd_tol; + bfd->nrs_max = parm->nrs_max; + bfd->rs_size = parm->rs_size; + return; +} +#else +static void copy_bfcp(glp_prob *lp) +{ glp_bfcp _parm, *parm = &_parm; + glp_get_bfcp(lp, parm); + bfd_set_parm(lp->bfd, parm); + return; +} +#endif + +void glp_set_bfcp(glp_prob *lp, const glp_bfcp *parm) +{ glp_bfcp *bfcp = lp->bfcp; + if (parm == NULL) + { /* reset to default values */ + if (bfcp != NULL) + xfree(bfcp), lp->bfcp = NULL; + } + else + { /* set to specified values */ + if (bfcp == NULL) + bfcp = lp->bfcp = xmalloc(sizeof(glp_bfcp)); + memcpy(bfcp, parm, sizeof(glp_bfcp)); + if (!(bfcp->type == GLP_BF_FT || bfcp->type == GLP_BF_BG || + bfcp->type == GLP_BF_GR)) + xerror("glp_set_bfcp: type = %d; invalid parameter\n", + bfcp->type); + if (bfcp->lu_size < 0) + xerror("glp_set_bfcp: lu_size = %d; invalid parameter\n", + bfcp->lu_size); + if (!(0.0 < bfcp->piv_tol && bfcp->piv_tol < 1.0)) + xerror("glp_set_bfcp: piv_tol = %g; invalid parameter\n", + bfcp->piv_tol); + if (bfcp->piv_lim < 1) + xerror("glp_set_bfcp: piv_lim = %d; invalid parameter\n", + bfcp->piv_lim); + if (!(bfcp->suhl == GLP_ON || bfcp->suhl == GLP_OFF)) + xerror("glp_set_bfcp: suhl = %d; invalid parameter\n", + bfcp->suhl); + if (!(0.0 <= bfcp->eps_tol && bfcp->eps_tol <= 1e-6)) + xerror("glp_set_bfcp: eps_tol = %g; invalid parameter\n", + bfcp->eps_tol); + if (bfcp->max_gro < 1.0) + xerror("glp_set_bfcp: max_gro = %g; invalid parameter\n", + bfcp->max_gro); + if (!(1 <= bfcp->nfs_max && bfcp->nfs_max <= 32767)) + xerror("glp_set_bfcp: nfs_max = %d; invalid parameter\n", + bfcp->nfs_max); + if (!(0.0 < bfcp->upd_tol && bfcp->upd_tol < 1.0)) + xerror("glp_set_bfcp: upd_tol = %g; invalid parameter\n", + bfcp->upd_tol); + if (!(1 <= bfcp->nrs_max && bfcp->nrs_max <= 32767)) + xerror("glp_set_bfcp: nrs_max = %d; invalid parameter\n", + bfcp->nrs_max); + if (bfcp->rs_size < 0) + xerror("glp_set_bfcp: rs_size = %d; invalid parameter\n", + bfcp->nrs_max); + if (bfcp->rs_size == 0) + bfcp->rs_size = 20 * bfcp->nrs_max; + } + if (lp->bfd != NULL) copy_bfcp(lp); + return; +} + +/*********************************************************************** +* NAME +* +* glp_get_bhead - retrieve the basis header information +* +* SYNOPSIS +* +* int glp_get_bhead(glp_prob *lp, int k); +* +* DESCRIPTION +* +* The routine glp_get_bhead returns the basis header information for +* the current basis associated with the specified problem object. +* +* RETURNS +* +* If xB[k], 1 <= k <= m, is i-th auxiliary variable (1 <= i <= m), the +* routine returns i. Otherwise, if xB[k] is j-th structural variable +* (1 <= j <= n), the routine returns m+j. Here m is the number of rows +* and n is the number of columns in the problem object. */ + +int glp_get_bhead(glp_prob *lp, int k) +{ if (!(lp->m == 0 || lp->valid)) + xerror("glp_get_bhead: basis factorization does not exist\n"); + if (!(1 <= k && k <= lp->m)) + xerror("glp_get_bhead: k = %d; index out of range\n", k); + return lp->head[k]; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_bind - retrieve row index in the basis header +* +* SYNOPSIS +* +* int glp_get_row_bind(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_bind returns the index k of basic variable +* xB[k], 1 <= k <= m, which is i-th auxiliary variable, 1 <= i <= m, +* in the current basis associated with the specified problem object, +* where m is the number of rows. However, if i-th auxiliary variable +* is non-basic, the routine returns zero. */ + +int glp_get_row_bind(glp_prob *lp, int i) +{ if (!(lp->m == 0 || lp->valid)) + xerror("glp_get_row_bind: basis factorization does not exist\n" + ); + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_bind: i = %d; row number out of range\n", + i); + return lp->row[i]->bind; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_bind - retrieve column index in the basis header +* +* SYNOPSIS +* +* int glp_get_col_bind(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_bind returns the index k of basic variable +* xB[k], 1 <= k <= m, which is j-th structural variable, 1 <= j <= n, +* in the current basis associated with the specified problem object, +* where m is the number of rows, n is the number of columns. However, +* if j-th structural variable is non-basic, the routine returns zero.*/ + +int glp_get_col_bind(glp_prob *lp, int j) +{ if (!(lp->m == 0 || lp->valid)) + xerror("glp_get_col_bind: basis factorization does not exist\n" + ); + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_bind: j = %d; column number out of range\n" + , j); + return lp->col[j]->bind; +} + +/*********************************************************************** +* NAME +* +* glp_ftran - perform forward transformation (solve system B*x = b) +* +* SYNOPSIS +* +* void glp_ftran(glp_prob *lp, double x[]); +* +* DESCRIPTION +* +* The routine glp_ftran performs forward transformation, i.e. solves +* the system B*x = b, where B is the basis matrix corresponding to the +* current basis for the specified problem object, x is the vector of +* unknowns to be computed, b is the vector of right-hand sides. +* +* On entry elements of the vector b should be stored in dense format +* in locations x[1], ..., x[m], where m is the number of rows. On exit +* the routine stores elements of the vector x in the same locations. +* +* SCALING/UNSCALING +* +* Let A~ = (I | -A) is the augmented constraint matrix of the original +* (unscaled) problem. In the scaled LP problem instead the matrix A the +* scaled matrix A" = R*A*S is actually used, so +* +* A~" = (I | A") = (I | R*A*S) = (R*I*inv(R) | R*A*S) = +* (1) +* = R*(I | A)*S~ = R*A~*S~, +* +* is the scaled augmented constraint matrix, where R and S are diagonal +* scaling matrices used to scale rows and columns of the matrix A, and +* +* S~ = diag(inv(R) | S) (2) +* +* is an augmented diagonal scaling matrix. +* +* By definition: +* +* A~ = (B | N), (3) +* +* where B is the basic matrix, which consists of basic columns of the +* augmented constraint matrix A~, and N is a matrix, which consists of +* non-basic columns of A~. From (1) it follows that: +* +* A~" = (B" | N") = (R*B*SB | R*N*SN), (4) +* +* where SB and SN are parts of the augmented scaling matrix S~, which +* correspond to basic and non-basic variables, respectively. Therefore +* +* B" = R*B*SB, (5) +* +* which is the scaled basis matrix. */ + +void glp_ftran(glp_prob *lp, double x[]) +{ int m = lp->m; + GLPROW **row = lp->row; + GLPCOL **col = lp->col; + int i, k; + /* B*x = b ===> (R*B*SB)*(inv(SB)*x) = R*b ===> + B"*x" = b", where b" = R*b, x = SB*x" */ + if (!(m == 0 || lp->valid)) + xerror("glp_ftran: basis factorization does not exist\n"); + /* b" := R*b */ + for (i = 1; i <= m; i++) + x[i] *= row[i]->rii; + /* x" := inv(B")*b" */ + if (m > 0) bfd_ftran(lp->bfd, x); + /* x := SB*x" */ + for (i = 1; i <= m; i++) + { k = lp->head[i]; + if (k <= m) + x[i] /= row[k]->rii; + else + x[i] *= col[k-m]->sjj; + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_btran - perform backward transformation (solve system B'*x = b) +* +* SYNOPSIS +* +* void glp_btran(glp_prob *lp, double x[]); +* +* DESCRIPTION +* +* The routine glp_btran performs backward transformation, i.e. solves +* the system B'*x = b, where B' is a matrix transposed to the basis +* matrix corresponding to the current basis for the specified problem +* problem object, x is the vector of unknowns to be computed, b is the +* vector of right-hand sides. +* +* On entry elements of the vector b should be stored in dense format +* in locations x[1], ..., x[m], where m is the number of rows. On exit +* the routine stores elements of the vector x in the same locations. +* +* SCALING/UNSCALING +* +* See comments to the routine glp_ftran. */ + +void glp_btran(glp_prob *lp, double x[]) +{ int m = lp->m; + GLPROW **row = lp->row; + GLPCOL **col = lp->col; + int i, k; + /* B'*x = b ===> (SB*B'*R)*(inv(R)*x) = SB*b ===> + (B")'*x" = b", where b" = SB*b, x = R*x" */ + if (!(m == 0 || lp->valid)) + xerror("glp_btran: basis factorization does not exist\n"); + /* b" := SB*b */ + for (i = 1; i <= m; i++) + { k = lp->head[i]; + if (k <= m) + x[i] /= row[k]->rii; + else + x[i] *= col[k-m]->sjj; + } + /* x" := inv[(B")']*b" */ + if (m > 0) bfd_btran(lp->bfd, x); + /* x := R*x" */ + for (i = 1; i <= m; i++) + x[i] *= row[i]->rii; + return; +} + +/*********************************************************************** +* NAME +* +* glp_warm_up - "warm up" LP basis +* +* SYNOPSIS +* +* int glp_warm_up(glp_prob *P); +* +* DESCRIPTION +* +* The routine glp_warm_up "warms up" the LP basis for the specified +* problem object using current statuses assigned to rows and columns +* (that is, to auxiliary and structural variables). +* +* This operation includes computing factorization of the basis matrix +* (if it does not exist), computing primal and dual components of basic +* solution, and determining the solution status. +* +* RETURNS +* +* 0 The operation has been successfully performed. +* +* GLP_EBADB +* The basis matrix is invalid, i.e. the number of basic (auxiliary +* and structural) variables differs from the number of rows in the +* problem object. +* +* GLP_ESING +* The basis matrix is singular within the working precision. +* +* GLP_ECOND +* The basis matrix is ill-conditioned. */ + +int glp_warm_up(glp_prob *P) +{ GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, j, type, stat, ret; + double eps, temp, *work; + /* invalidate basic solution */ + P->pbs_stat = P->dbs_stat = GLP_UNDEF; + P->obj_val = 0.0; + P->some = 0; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + row->prim = row->dual = 0.0; + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + col->prim = col->dual = 0.0; + } + /* compute the basis factorization, if necessary */ + if (!glp_bf_exists(P)) + { ret = glp_factorize(P); + if (ret != 0) goto done; + } + /* allocate working array */ + work = xcalloc(1+P->m, sizeof(double)); + /* determine and store values of non-basic variables, compute + vector (- N * xN) */ + for (i = 1; i <= P->m; i++) + work[i] = 0.0; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->stat == GLP_BS) + continue; + else if (row->stat == GLP_NL) + row->prim = row->lb; + else if (row->stat == GLP_NU) + row->prim = row->ub; + else if (row->stat == GLP_NF) + row->prim = 0.0; + else if (row->stat == GLP_NS) + row->prim = row->lb; + else + xassert(row != row); + /* N[j] is i-th column of matrix (I|-A) */ + work[i] -= row->prim; + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->stat == GLP_BS) + continue; + else if (col->stat == GLP_NL) + col->prim = col->lb; + else if (col->stat == GLP_NU) + col->prim = col->ub; + else if (col->stat == GLP_NF) + col->prim = 0.0; + else if (col->stat == GLP_NS) + col->prim = col->lb; + else + xassert(col != col); + /* N[j] is (m+j)-th column of matrix (I|-A) */ + if (col->prim != 0.0) + { for (aij = col->ptr; aij != NULL; aij = aij->c_next) + work[aij->row->i] += aij->val * col->prim; + } + } + /* compute vector of basic variables xB = - inv(B) * N * xN */ + glp_ftran(P, work); + /* store values of basic variables, check primal feasibility */ + P->pbs_stat = GLP_FEAS; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->stat != GLP_BS) + continue; + row->prim = work[row->bind]; + type = row->type; + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { eps = 1e-6 + 1e-9 * fabs(row->lb); + if (row->prim < row->lb - eps) + P->pbs_stat = GLP_INFEAS; + } + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { eps = 1e-6 + 1e-9 * fabs(row->ub); + if (row->prim > row->ub + eps) + P->pbs_stat = GLP_INFEAS; + } + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->stat != GLP_BS) + continue; + col->prim = work[col->bind]; + type = col->type; + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { eps = 1e-6 + 1e-9 * fabs(col->lb); + if (col->prim < col->lb - eps) + P->pbs_stat = GLP_INFEAS; + } + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { eps = 1e-6 + 1e-9 * fabs(col->ub); + if (col->prim > col->ub + eps) + P->pbs_stat = GLP_INFEAS; + } + } + /* compute value of the objective function */ + P->obj_val = P->c0; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + P->obj_val += col->coef * col->prim; + } + /* build vector cB of objective coefficients at basic variables */ + for (i = 1; i <= P->m; i++) + work[i] = 0.0; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->stat == GLP_BS) + work[col->bind] = col->coef; + } + /* compute vector of simplex multipliers pi = inv(B') * cB */ + glp_btran(P, work); + /* compute and store reduced costs of non-basic variables d[j] = + c[j] - N'[j] * pi, check dual feasibility */ + P->dbs_stat = GLP_FEAS; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->stat == GLP_BS) + { row->dual = 0.0; + continue; + } + /* N[j] is i-th column of matrix (I|-A) */ + row->dual = - work[i]; +#if 0 /* 07/III-2013 */ + type = row->type; + temp = (P->dir == GLP_MIN ? + row->dual : - row->dual); + if ((type == GLP_FR || type == GLP_LO) && temp < -1e-5 || + (type == GLP_FR || type == GLP_UP) && temp > +1e-5) + P->dbs_stat = GLP_INFEAS; +#else + stat = row->stat; + temp = (P->dir == GLP_MIN ? + row->dual : - row->dual); + if ((stat == GLP_NF || stat == GLP_NL) && temp < -1e-5 || + (stat == GLP_NF || stat == GLP_NU) && temp > +1e-5) + P->dbs_stat = GLP_INFEAS; +#endif + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->stat == GLP_BS) + { col->dual = 0.0; + continue; + } + /* N[j] is (m+j)-th column of matrix (I|-A) */ + col->dual = col->coef; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + col->dual += aij->val * work[aij->row->i]; +#if 0 /* 07/III-2013 */ + type = col->type; + temp = (P->dir == GLP_MIN ? + col->dual : - col->dual); + if ((type == GLP_FR || type == GLP_LO) && temp < -1e-5 || + (type == GLP_FR || type == GLP_UP) && temp > +1e-5) + P->dbs_stat = GLP_INFEAS; +#else + stat = col->stat; + temp = (P->dir == GLP_MIN ? + col->dual : - col->dual); + if ((stat == GLP_NF || stat == GLP_NL) && temp < -1e-5 || + (stat == GLP_NF || stat == GLP_NU) && temp > +1e-5) + P->dbs_stat = GLP_INFEAS; +#endif + } + /* free working array */ + xfree(work); + ret = 0; +done: return ret; +} + +/*********************************************************************** +* NAME +* +* glp_eval_tab_row - compute row of the simplex tableau +* +* SYNOPSIS +* +* int glp_eval_tab_row(glp_prob *lp, int k, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_eval_tab_row computes a row of the current simplex +* tableau for the basic variable, which is specified by the number k: +* if 1 <= k <= m, x[k] is k-th auxiliary variable; if m+1 <= k <= m+n, +* x[k] is (k-m)-th structural variable, where m is number of rows, and +* n is number of columns. The current basis must be available. +* +* The routine stores column indices and numerical values of non-zero +* elements of the computed row using sparse format to the locations +* ind[1], ..., ind[len] and val[1], ..., val[len], respectively, where +* 0 <= len <= n is number of non-zeros returned on exit. +* +* Element indices stored in the array ind have the same sense as the +* index k, i.e. indices 1 to m denote auxiliary variables and indices +* m+1 to m+n denote structural ones (all these variables are obviously +* non-basic by definition). +* +* The computed row shows how the specified basic variable x[k] = xB[i] +* depends on non-basic variables: +* +* xB[i] = alfa[i,1]*xN[1] + alfa[i,2]*xN[2] + ... + alfa[i,n]*xN[n], +* +* where alfa[i,j] are elements of the simplex table row, xN[j] are +* non-basic (auxiliary and structural) variables. +* +* RETURNS +* +* The routine returns number of non-zero elements in the simplex table +* row stored in the arrays ind and val. +* +* BACKGROUND +* +* The system of equality constraints of the LP problem is: +* +* xR = A * xS, (1) +* +* where xR is the vector of auxliary variables, xS is the vector of +* structural variables, A is the matrix of constraint coefficients. +* +* The system (1) can be written in homogenous form as follows: +* +* A~ * x = 0, (2) +* +* where A~ = (I | -A) is the augmented constraint matrix (has m rows +* and m+n columns), x = (xR | xS) is the vector of all (auxiliary and +* structural) variables. +* +* By definition for the current basis we have: +* +* A~ = (B | N), (3) +* +* where B is the basis matrix. Thus, the system (2) can be written as: +* +* B * xB + N * xN = 0. (4) +* +* From (4) it follows that: +* +* xB = A^ * xN, (5) +* +* where the matrix +* +* A^ = - inv(B) * N (6) +* +* is called the simplex table. +* +* It is understood that i-th row of the simplex table is: +* +* e * A^ = - e * inv(B) * N, (7) +* +* where e is a unity vector with e[i] = 1. +* +* To compute i-th row of the simplex table the routine first computes +* i-th row of the inverse: +* +* rho = inv(B') * e, (8) +* +* where B' is a matrix transposed to B, and then computes elements of +* i-th row of the simplex table as scalar products: +* +* alfa[i,j] = - rho * N[j] for all j, (9) +* +* where N[j] is a column of the augmented constraint matrix A~, which +* corresponds to some non-basic auxiliary or structural variable. */ + +int glp_eval_tab_row(glp_prob *lp, int k, int ind[], double val[]) +{ int m = lp->m; + int n = lp->n; + int i, t, len, lll, *iii; + double alfa, *rho, *vvv; + if (!(m == 0 || lp->valid)) + xerror("glp_eval_tab_row: basis factorization does not exist\n" + ); + if (!(1 <= k && k <= m+n)) + xerror("glp_eval_tab_row: k = %d; variable number out of range" + , k); + /* determine xB[i] which corresponds to x[k] */ + if (k <= m) + i = glp_get_row_bind(lp, k); + else + i = glp_get_col_bind(lp, k-m); + if (i == 0) + xerror("glp_eval_tab_row: k = %d; variable must be basic", k); + xassert(1 <= i && i <= m); + /* allocate working arrays */ + rho = xcalloc(1+m, sizeof(double)); + iii = xcalloc(1+m, sizeof(int)); + vvv = xcalloc(1+m, sizeof(double)); + /* compute i-th row of the inverse; see (8) */ + for (t = 1; t <= m; t++) rho[t] = 0.0; + rho[i] = 1.0; + glp_btran(lp, rho); + /* compute i-th row of the simplex table */ + len = 0; + for (k = 1; k <= m+n; k++) + { if (k <= m) + { /* x[k] is auxiliary variable, so N[k] is a unity column */ + if (glp_get_row_stat(lp, k) == GLP_BS) continue; + /* compute alfa[i,j]; see (9) */ + alfa = - rho[k]; + } + else + { /* x[k] is structural variable, so N[k] is a column of the + original constraint matrix A with negative sign */ + if (glp_get_col_stat(lp, k-m) == GLP_BS) continue; + /* compute alfa[i,j]; see (9) */ + lll = glp_get_mat_col(lp, k-m, iii, vvv); + alfa = 0.0; + for (t = 1; t <= lll; t++) alfa += rho[iii[t]] * vvv[t]; + } + /* store alfa[i,j] */ + if (alfa != 0.0) len++, ind[len] = k, val[len] = alfa; + } + xassert(len <= n); + /* free working arrays */ + xfree(rho); + xfree(iii); + xfree(vvv); + /* return to the calling program */ + return len; +} + +/*********************************************************************** +* NAME +* +* glp_eval_tab_col - compute column of the simplex tableau +* +* SYNOPSIS +* +* int glp_eval_tab_col(glp_prob *lp, int k, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_eval_tab_col computes a column of the current simplex +* table for the non-basic variable, which is specified by the number k: +* if 1 <= k <= m, x[k] is k-th auxiliary variable; if m+1 <= k <= m+n, +* x[k] is (k-m)-th structural variable, where m is number of rows, and +* n is number of columns. The current basis must be available. +* +* The routine stores row indices and numerical values of non-zero +* elements of the computed column using sparse format to the locations +* ind[1], ..., ind[len] and val[1], ..., val[len] respectively, where +* 0 <= len <= m is number of non-zeros returned on exit. +* +* Element indices stored in the array ind have the same sense as the +* index k, i.e. indices 1 to m denote auxiliary variables and indices +* m+1 to m+n denote structural ones (all these variables are obviously +* basic by the definition). +* +* The computed column shows how basic variables depend on the specified +* non-basic variable x[k] = xN[j]: +* +* xB[1] = ... + alfa[1,j]*xN[j] + ... +* xB[2] = ... + alfa[2,j]*xN[j] + ... +* . . . . . . +* xB[m] = ... + alfa[m,j]*xN[j] + ... +* +* where alfa[i,j] are elements of the simplex table column, xB[i] are +* basic (auxiliary and structural) variables. +* +* RETURNS +* +* The routine returns number of non-zero elements in the simplex table +* column stored in the arrays ind and val. +* +* BACKGROUND +* +* As it was explained in comments to the routine glp_eval_tab_row (see +* above) the simplex table is the following matrix: +* +* A^ = - inv(B) * N. (1) +* +* Therefore j-th column of the simplex table is: +* +* A^ * e = - inv(B) * N * e = - inv(B) * N[j], (2) +* +* where e is a unity vector with e[j] = 1, B is the basis matrix, N[j] +* is a column of the augmented constraint matrix A~, which corresponds +* to the given non-basic auxiliary or structural variable. */ + +int glp_eval_tab_col(glp_prob *lp, int k, int ind[], double val[]) +{ int m = lp->m; + int n = lp->n; + int t, len, stat; + double *col; + if (!(m == 0 || lp->valid)) + xerror("glp_eval_tab_col: basis factorization does not exist\n" + ); + if (!(1 <= k && k <= m+n)) + xerror("glp_eval_tab_col: k = %d; variable number out of range" + , k); + if (k <= m) + stat = glp_get_row_stat(lp, k); + else + stat = glp_get_col_stat(lp, k-m); + if (stat == GLP_BS) + xerror("glp_eval_tab_col: k = %d; variable must be non-basic", + k); + /* obtain column N[k] with negative sign */ + col = xcalloc(1+m, sizeof(double)); + for (t = 1; t <= m; t++) col[t] = 0.0; + if (k <= m) + { /* x[k] is auxiliary variable, so N[k] is a unity column */ + col[k] = -1.0; + } + else + { /* x[k] is structural variable, so N[k] is a column of the + original constraint matrix A with negative sign */ + len = glp_get_mat_col(lp, k-m, ind, val); + for (t = 1; t <= len; t++) col[ind[t]] = val[t]; + } + /* compute column of the simplex table, which corresponds to the + specified non-basic variable x[k] */ + glp_ftran(lp, col); + len = 0; + for (t = 1; t <= m; t++) + { if (col[t] != 0.0) + { len++; + ind[len] = glp_get_bhead(lp, t); + val[len] = col[t]; + } + } + xfree(col); + /* return to the calling program */ + return len; +} + +/*********************************************************************** +* NAME +* +* glp_transform_row - transform explicitly specified row +* +* SYNOPSIS +* +* int glp_transform_row(glp_prob *P, int len, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_transform_row performs the same operation as the +* routine glp_eval_tab_row with exception that the row to be +* transformed is specified explicitly as a sparse vector. +* +* The explicitly specified row may be thought as a linear form: +* +* x = a[1]*x[m+1] + a[2]*x[m+2] + ... + a[n]*x[m+n], (1) +* +* where x is an auxiliary variable for this row, a[j] are coefficients +* of the linear form, x[m+j] are structural variables. +* +* On entry column indices and numerical values of non-zero elements of +* the row should be stored in locations ind[1], ..., ind[len] and +* val[1], ..., val[len], where len is the number of non-zero elements. +* +* This routine uses the system of equality constraints and the current +* basis in order to express the auxiliary variable x in (1) through the +* current non-basic variables (as if the transformed row were added to +* the problem object and its auxiliary variable were basic), i.e. the +* resultant row has the form: +* +* x = alfa[1]*xN[1] + alfa[2]*xN[2] + ... + alfa[n]*xN[n], (2) +* +* where xN[j] are non-basic (auxiliary or structural) variables, n is +* the number of columns in the LP problem object. +* +* On exit the routine stores indices and numerical values of non-zero +* elements of the resultant row (2) in locations ind[1], ..., ind[len'] +* and val[1], ..., val[len'], where 0 <= len' <= n is the number of +* non-zero elements in the resultant row returned by the routine. Note +* that indices (numbers) of non-basic variables stored in the array ind +* correspond to original ordinal numbers of variables: indices 1 to m +* mean auxiliary variables and indices m+1 to m+n mean structural ones. +* +* RETURNS +* +* The routine returns len', which is the number of non-zero elements in +* the resultant row stored in the arrays ind and val. +* +* BACKGROUND +* +* The explicitly specified row (1) is transformed in the same way as it +* were the objective function row. +* +* From (1) it follows that: +* +* x = aB * xB + aN * xN, (3) +* +* where xB is the vector of basic variables, xN is the vector of +* non-basic variables. +* +* The simplex table, which corresponds to the current basis, is: +* +* xB = [-inv(B) * N] * xN. (4) +* +* Therefore substituting xB from (4) to (3) we have: +* +* x = aB * [-inv(B) * N] * xN + aN * xN = +* (5) +* = rho * (-N) * xN + aN * xN = alfa * xN, +* +* where: +* +* rho = inv(B') * aB, (6) +* +* and +* +* alfa = aN + rho * (-N) (7) +* +* is the resultant row computed by the routine. */ + +int glp_transform_row(glp_prob *P, int len, int ind[], double val[]) +{ int i, j, k, m, n, t, lll, *iii; + double alfa, *a, *aB, *rho, *vvv; + if (!glp_bf_exists(P)) + xerror("glp_transform_row: basis factorization does not exist " + "\n"); + m = glp_get_num_rows(P); + n = glp_get_num_cols(P); + /* unpack the row to be transformed to the array a */ + a = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) a[j] = 0.0; + if (!(0 <= len && len <= n)) + xerror("glp_transform_row: len = %d; invalid row length\n", + len); + for (t = 1; t <= len; t++) + { j = ind[t]; + if (!(1 <= j && j <= n)) + xerror("glp_transform_row: ind[%d] = %d; column index out o" + "f range\n", t, j); + if (val[t] == 0.0) + xerror("glp_transform_row: val[%d] = 0; zero coefficient no" + "t allowed\n", t); + if (a[j] != 0.0) + xerror("glp_transform_row: ind[%d] = %d; duplicate column i" + "ndices not allowed\n", t, j); + a[j] = val[t]; + } + /* construct the vector aB */ + aB = xcalloc(1+m, sizeof(double)); + for (i = 1; i <= m; i++) + { k = glp_get_bhead(P, i); + /* xB[i] is k-th original variable */ + xassert(1 <= k && k <= m+n); + aB[i] = (k <= m ? 0.0 : a[k-m]); + } + /* solve the system B'*rho = aB to compute the vector rho */ + rho = aB, glp_btran(P, rho); + /* compute coefficients at non-basic auxiliary variables */ + len = 0; + for (i = 1; i <= m; i++) + { if (glp_get_row_stat(P, i) != GLP_BS) + { alfa = - rho[i]; + if (alfa != 0.0) + { len++; + ind[len] = i; + val[len] = alfa; + } + } + } + /* compute coefficients at non-basic structural variables */ + iii = xcalloc(1+m, sizeof(int)); + vvv = xcalloc(1+m, sizeof(double)); + for (j = 1; j <= n; j++) + { if (glp_get_col_stat(P, j) != GLP_BS) + { alfa = a[j]; + lll = glp_get_mat_col(P, j, iii, vvv); + for (t = 1; t <= lll; t++) alfa += vvv[t] * rho[iii[t]]; + if (alfa != 0.0) + { len++; + ind[len] = m+j; + val[len] = alfa; + } + } + } + xassert(len <= n); + xfree(iii); + xfree(vvv); + xfree(aB); + xfree(a); + return len; +} + +/*********************************************************************** +* NAME +* +* glp_transform_col - transform explicitly specified column +* +* SYNOPSIS +* +* int glp_transform_col(glp_prob *P, int len, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_transform_col performs the same operation as the +* routine glp_eval_tab_col with exception that the column to be +* transformed is specified explicitly as a sparse vector. +* +* The explicitly specified column may be thought as if it were added +* to the original system of equality constraints: +* +* x[1] = a[1,1]*x[m+1] + ... + a[1,n]*x[m+n] + a[1]*x +* x[2] = a[2,1]*x[m+1] + ... + a[2,n]*x[m+n] + a[2]*x (1) +* . . . . . . . . . . . . . . . +* x[m] = a[m,1]*x[m+1] + ... + a[m,n]*x[m+n] + a[m]*x +* +* where x[i] are auxiliary variables, x[m+j] are structural variables, +* x is a structural variable for the explicitly specified column, a[i] +* are constraint coefficients for x. +* +* On entry row indices and numerical values of non-zero elements of +* the column should be stored in locations ind[1], ..., ind[len] and +* val[1], ..., val[len], where len is the number of non-zero elements. +* +* This routine uses the system of equality constraints and the current +* basis in order to express the current basic variables through the +* structural variable x in (1) (as if the transformed column were added +* to the problem object and the variable x were non-basic), i.e. the +* resultant column has the form: +* +* xB[1] = ... + alfa[1]*x +* xB[2] = ... + alfa[2]*x (2) +* . . . . . . +* xB[m] = ... + alfa[m]*x +* +* where xB are basic (auxiliary and structural) variables, m is the +* number of rows in the problem object. +* +* On exit the routine stores indices and numerical values of non-zero +* elements of the resultant column (2) in locations ind[1], ..., +* ind[len'] and val[1], ..., val[len'], where 0 <= len' <= m is the +* number of non-zero element in the resultant column returned by the +* routine. Note that indices (numbers) of basic variables stored in +* the array ind correspond to original ordinal numbers of variables: +* indices 1 to m mean auxiliary variables and indices m+1 to m+n mean +* structural ones. +* +* RETURNS +* +* The routine returns len', which is the number of non-zero elements +* in the resultant column stored in the arrays ind and val. +* +* BACKGROUND +* +* The explicitly specified column (1) is transformed in the same way +* as any other column of the constraint matrix using the formula: +* +* alfa = inv(B) * a, (3) +* +* where alfa is the resultant column computed by the routine. */ + +int glp_transform_col(glp_prob *P, int len, int ind[], double val[]) +{ int i, m, t; + double *a, *alfa; + if (!glp_bf_exists(P)) + xerror("glp_transform_col: basis factorization does not exist " + "\n"); + m = glp_get_num_rows(P); + /* unpack the column to be transformed to the array a */ + a = xcalloc(1+m, sizeof(double)); + for (i = 1; i <= m; i++) a[i] = 0.0; + if (!(0 <= len && len <= m)) + xerror("glp_transform_col: len = %d; invalid column length\n", + len); + for (t = 1; t <= len; t++) + { i = ind[t]; + if (!(1 <= i && i <= m)) + xerror("glp_transform_col: ind[%d] = %d; row index out of r" + "ange\n", t, i); + if (val[t] == 0.0) + xerror("glp_transform_col: val[%d] = 0; zero coefficient no" + "t allowed\n", t); + if (a[i] != 0.0) + xerror("glp_transform_col: ind[%d] = %d; duplicate row indi" + "ces not allowed\n", t, i); + a[i] = val[t]; + } + /* solve the system B*a = alfa to compute the vector alfa */ + alfa = a, glp_ftran(P, alfa); + /* store resultant coefficients */ + len = 0; + for (i = 1; i <= m; i++) + { if (alfa[i] != 0.0) + { len++; + ind[len] = glp_get_bhead(P, i); + val[len] = alfa[i]; + } + } + xfree(a); + return len; +} + +/*********************************************************************** +* NAME +* +* glp_prim_rtest - perform primal ratio test +* +* SYNOPSIS +* +* int glp_prim_rtest(glp_prob *P, int len, const int ind[], +* const double val[], int dir, double eps); +* +* DESCRIPTION +* +* The routine glp_prim_rtest performs the primal ratio test using an +* explicitly specified column of the simplex table. +* +* The current basic solution associated with the LP problem object +* must be primal feasible. +* +* The explicitly specified column of the simplex table shows how the +* basic variables xB depend on some non-basic variable x (which is not +* necessarily presented in the problem object): +* +* xB[1] = ... + alfa[1] * x + ... +* xB[2] = ... + alfa[2] * x + ... (*) +* . . . . . . . . +* xB[m] = ... + alfa[m] * x + ... +* +* The column (*) is specifed on entry to the routine using the sparse +* format. Ordinal numbers of basic variables xB[i] should be placed in +* locations ind[1], ..., ind[len], where ordinal number 1 to m denote +* auxiliary variables, and ordinal numbers m+1 to m+n denote structural +* variables. The corresponding non-zero coefficients alfa[i] should be +* placed in locations val[1], ..., val[len]. The arrays ind and val are +* not changed on exit. +* +* The parameter dir specifies direction in which the variable x changes +* on entering the basis: +1 means increasing, -1 means decreasing. +* +* The parameter eps is an absolute tolerance (small positive number) +* used by the routine to skip small alfa[j] of the row (*). +* +* The routine determines which basic variable (among specified in +* ind[1], ..., ind[len]) should leave the basis in order to keep primal +* feasibility. +* +* RETURNS +* +* The routine glp_prim_rtest returns the index piv in the arrays ind +* and val corresponding to the pivot element chosen, 1 <= piv <= len. +* If the adjacent basic solution is primal unbounded and therefore the +* choice cannot be made, the routine returns zero. +* +* COMMENTS +* +* If the non-basic variable x is presented in the LP problem object, +* the column (*) can be computed with the routine glp_eval_tab_col; +* otherwise it can be computed with the routine glp_transform_col. */ + +int glp_prim_rtest(glp_prob *P, int len, const int ind[], + const double val[], int dir, double eps) +{ int k, m, n, piv, t, type, stat; + double alfa, big, beta, lb, ub, temp, teta; + if (glp_get_prim_stat(P) != GLP_FEAS) + xerror("glp_prim_rtest: basic solution is not primal feasible " + "\n"); + if (!(dir == +1 || dir == -1)) + xerror("glp_prim_rtest: dir = %d; invalid parameter\n", dir); + if (!(0.0 < eps && eps < 1.0)) + xerror("glp_prim_rtest: eps = %g; invalid parameter\n", eps); + m = glp_get_num_rows(P); + n = glp_get_num_cols(P); + /* initial settings */ + piv = 0, teta = DBL_MAX, big = 0.0; + /* walk through the entries of the specified column */ + for (t = 1; t <= len; t++) + { /* get the ordinal number of basic variable */ + k = ind[t]; + if (!(1 <= k && k <= m+n)) + xerror("glp_prim_rtest: ind[%d] = %d; variable number out o" + "f range\n", t, k); + /* determine type, bounds, status and primal value of basic + variable xB[i] = x[k] in the current basic solution */ + if (k <= m) + { type = glp_get_row_type(P, k); + lb = glp_get_row_lb(P, k); + ub = glp_get_row_ub(P, k); + stat = glp_get_row_stat(P, k); + beta = glp_get_row_prim(P, k); + } + else + { type = glp_get_col_type(P, k-m); + lb = glp_get_col_lb(P, k-m); + ub = glp_get_col_ub(P, k-m); + stat = glp_get_col_stat(P, k-m); + beta = glp_get_col_prim(P, k-m); + } + if (stat != GLP_BS) + xerror("glp_prim_rtest: ind[%d] = %d; non-basic variable no" + "t allowed\n", t, k); + /* determine influence coefficient at basic variable xB[i] + in the explicitly specified column and turn to the case of + increasing the variable x in order to simplify the program + logic */ + alfa = (dir > 0 ? + val[t] : - val[t]); + /* analyze main cases */ + if (type == GLP_FR) + { /* xB[i] is free variable */ + continue; + } + else if (type == GLP_LO) +lo: { /* xB[i] has an lower bound */ + if (alfa > - eps) continue; + temp = (lb - beta) / alfa; + } + else if (type == GLP_UP) +up: { /* xB[i] has an upper bound */ + if (alfa < + eps) continue; + temp = (ub - beta) / alfa; + } + else if (type == GLP_DB) + { /* xB[i] has both lower and upper bounds */ + if (alfa < 0.0) goto lo; else goto up; + } + else if (type == GLP_FX) + { /* xB[i] is fixed variable */ + if (- eps < alfa && alfa < + eps) continue; + temp = 0.0; + } + else + xassert(type != type); + /* if the value of the variable xB[i] violates its lower or + upper bound (slightly, because the current basis is assumed + to be primal feasible), temp is negative; we can think this + happens due to round-off errors and the value is exactly on + the bound; this allows replacing temp by zero */ + if (temp < 0.0) temp = 0.0; + /* apply the minimal ratio test */ + if (teta > temp || teta == temp && big < fabs(alfa)) + piv = t, teta = temp, big = fabs(alfa); + } + /* return index of the pivot element chosen */ + return piv; +} + +/*********************************************************************** +* NAME +* +* glp_dual_rtest - perform dual ratio test +* +* SYNOPSIS +* +* int glp_dual_rtest(glp_prob *P, int len, const int ind[], +* const double val[], int dir, double eps); +* +* DESCRIPTION +* +* The routine glp_dual_rtest performs the dual ratio test using an +* explicitly specified row of the simplex table. +* +* The current basic solution associated with the LP problem object +* must be dual feasible. +* +* The explicitly specified row of the simplex table is a linear form +* that shows how some basic variable x (which is not necessarily +* presented in the problem object) depends on non-basic variables xN: +* +* x = alfa[1] * xN[1] + alfa[2] * xN[2] + ... + alfa[n] * xN[n]. (*) +* +* The row (*) is specified on entry to the routine using the sparse +* format. Ordinal numbers of non-basic variables xN[j] should be placed +* in locations ind[1], ..., ind[len], where ordinal numbers 1 to m +* denote auxiliary variables, and ordinal numbers m+1 to m+n denote +* structural variables. The corresponding non-zero coefficients alfa[j] +* should be placed in locations val[1], ..., val[len]. The arrays ind +* and val are not changed on exit. +* +* The parameter dir specifies direction in which the variable x changes +* on leaving the basis: +1 means that x goes to its lower bound, and -1 +* means that x goes to its upper bound. +* +* The parameter eps is an absolute tolerance (small positive number) +* used by the routine to skip small alfa[j] of the row (*). +* +* The routine determines which non-basic variable (among specified in +* ind[1], ..., ind[len]) should enter the basis in order to keep dual +* feasibility. +* +* RETURNS +* +* The routine glp_dual_rtest returns the index piv in the arrays ind +* and val corresponding to the pivot element chosen, 1 <= piv <= len. +* If the adjacent basic solution is dual unbounded and therefore the +* choice cannot be made, the routine returns zero. +* +* COMMENTS +* +* If the basic variable x is presented in the LP problem object, the +* row (*) can be computed with the routine glp_eval_tab_row; otherwise +* it can be computed with the routine glp_transform_row. */ + +int glp_dual_rtest(glp_prob *P, int len, const int ind[], + const double val[], int dir, double eps) +{ int k, m, n, piv, t, stat; + double alfa, big, cost, obj, temp, teta; + if (glp_get_dual_stat(P) != GLP_FEAS) + xerror("glp_dual_rtest: basic solution is not dual feasible\n") + ; + if (!(dir == +1 || dir == -1)) + xerror("glp_dual_rtest: dir = %d; invalid parameter\n", dir); + if (!(0.0 < eps && eps < 1.0)) + xerror("glp_dual_rtest: eps = %g; invalid parameter\n", eps); + m = glp_get_num_rows(P); + n = glp_get_num_cols(P); + /* take into account optimization direction */ + obj = (glp_get_obj_dir(P) == GLP_MIN ? +1.0 : -1.0); + /* initial settings */ + piv = 0, teta = DBL_MAX, big = 0.0; + /* walk through the entries of the specified row */ + for (t = 1; t <= len; t++) + { /* get ordinal number of non-basic variable */ + k = ind[t]; + if (!(1 <= k && k <= m+n)) + xerror("glp_dual_rtest: ind[%d] = %d; variable number out o" + "f range\n", t, k); + /* determine status and reduced cost of non-basic variable + x[k] = xN[j] in the current basic solution */ + if (k <= m) + { stat = glp_get_row_stat(P, k); + cost = glp_get_row_dual(P, k); + } + else + { stat = glp_get_col_stat(P, k-m); + cost = glp_get_col_dual(P, k-m); + } + if (stat == GLP_BS) + xerror("glp_dual_rtest: ind[%d] = %d; basic variable not al" + "lowed\n", t, k); + /* determine influence coefficient at non-basic variable xN[j] + in the explicitly specified row and turn to the case of + increasing the variable x in order to simplify the program + logic */ + alfa = (dir > 0 ? + val[t] : - val[t]); + /* analyze main cases */ + if (stat == GLP_NL) + { /* xN[j] is on its lower bound */ + if (alfa < + eps) continue; + temp = (obj * cost) / alfa; + } + else if (stat == GLP_NU) + { /* xN[j] is on its upper bound */ + if (alfa > - eps) continue; + temp = (obj * cost) / alfa; + } + else if (stat == GLP_NF) + { /* xN[j] is non-basic free variable */ + if (- eps < alfa && alfa < + eps) continue; + temp = 0.0; + } + else if (stat == GLP_NS) + { /* xN[j] is non-basic fixed variable */ + continue; + } + else + xassert(stat != stat); + /* if the reduced cost of the variable xN[j] violates its zero + bound (slightly, because the current basis is assumed to be + dual feasible), temp is negative; we can think this happens + due to round-off errors and the reduced cost is exact zero; + this allows replacing temp by zero */ + if (temp < 0.0) temp = 0.0; + /* apply the minimal ratio test */ + if (teta > temp || teta == temp && big < fabs(alfa)) + piv = t, teta = temp, big = fabs(alfa); + } + /* return index of the pivot element chosen */ + return piv; +} + +/*********************************************************************** +* NAME +* +* glp_analyze_row - simulate one iteration of dual simplex method +* +* SYNOPSIS +* +* int glp_analyze_row(glp_prob *P, int len, const int ind[], +* const double val[], int type, double rhs, double eps, int *piv, +* double *x, double *dx, double *y, double *dy, double *dz); +* +* DESCRIPTION +* +* Let the current basis be optimal or dual feasible, and there be +* specified a row (constraint), which is violated by the current basic +* solution. The routine glp_analyze_row simulates one iteration of the +* dual simplex method to determine some information on the adjacent +* basis (see below), where the specified row becomes active constraint +* (i.e. its auxiliary variable becomes non-basic). +* +* The current basic solution associated with the problem object passed +* to the routine must be dual feasible, and its primal components must +* be defined. +* +* The row to be analyzed must be previously transformed either with +* the routine glp_eval_tab_row (if the row is in the problem object) +* or with the routine glp_transform_row (if the row is external, i.e. +* not in the problem object). This is needed to express the row only +* through (auxiliary and structural) variables, which are non-basic in +* the current basis: +* +* y = alfa[1] * xN[1] + alfa[2] * xN[2] + ... + alfa[n] * xN[n], +* +* where y is an auxiliary variable of the row, alfa[j] is an influence +* coefficient, xN[j] is a non-basic variable. +* +* The row is passed to the routine in sparse format. Ordinal numbers +* of non-basic variables are stored in locations ind[1], ..., ind[len], +* where numbers 1 to m denote auxiliary variables while numbers m+1 to +* m+n denote structural variables. Corresponding non-zero coefficients +* alfa[j] are stored in locations val[1], ..., val[len]. The arrays +* ind and val are ot changed on exit. +* +* The parameters type and rhs specify the row type and its right-hand +* side as follows: +* +* type = GLP_LO: y = sum alfa[j] * xN[j] >= rhs +* +* type = GLP_UP: y = sum alfa[j] * xN[j] <= rhs +* +* The parameter eps is an absolute tolerance (small positive number) +* used by the routine to skip small coefficients alfa[j] on performing +* the dual ratio test. +* +* If the operation was successful, the routine stores the following +* information to corresponding location (if some parameter is NULL, +* its value is not stored): +* +* piv index in the array ind and val, 1 <= piv <= len, determining +* the non-basic variable, which would enter the adjacent basis; +* +* x value of the non-basic variable in the current basis; +* +* dx difference between values of the non-basic variable in the +* adjacent and current bases, dx = x.new - x.old; +* +* y value of the row (i.e. of its auxiliary variable) in the +* current basis; +* +* dy difference between values of the row in the adjacent and +* current bases, dy = y.new - y.old; +* +* dz difference between values of the objective function in the +* adjacent and current bases, dz = z.new - z.old. Note that in +* case of minimization dz >= 0, and in case of maximization +* dz <= 0, i.e. in the adjacent basis the objective function +* always gets worse (degrades). */ + +int _glp_analyze_row(glp_prob *P, int len, const int ind[], + const double val[], int type, double rhs, double eps, int *_piv, + double *_x, double *_dx, double *_y, double *_dy, double *_dz) +{ int t, k, dir, piv, ret = 0; + double x, dx, y, dy, dz; + if (P->pbs_stat == GLP_UNDEF) + xerror("glp_analyze_row: primal basic solution components are " + "undefined\n"); + if (P->dbs_stat != GLP_FEAS) + xerror("glp_analyze_row: basic solution is not dual feasible\n" + ); + /* compute the row value y = sum alfa[j] * xN[j] in the current + basis */ + if (!(0 <= len && len <= P->n)) + xerror("glp_analyze_row: len = %d; invalid row length\n", len); + y = 0.0; + for (t = 1; t <= len; t++) + { /* determine value of x[k] = xN[j] in the current basis */ + k = ind[t]; + if (!(1 <= k && k <= P->m+P->n)) + xerror("glp_analyze_row: ind[%d] = %d; row/column index out" + " of range\n", t, k); + if (k <= P->m) + { /* x[k] is auxiliary variable */ + if (P->row[k]->stat == GLP_BS) + xerror("glp_analyze_row: ind[%d] = %d; basic auxiliary v" + "ariable is not allowed\n", t, k); + x = P->row[k]->prim; + } + else + { /* x[k] is structural variable */ + if (P->col[k-P->m]->stat == GLP_BS) + xerror("glp_analyze_row: ind[%d] = %d; basic structural " + "variable is not allowed\n", t, k); + x = P->col[k-P->m]->prim; + } + y += val[t] * x; + } + /* check if the row is primal infeasible in the current basis, + i.e. the constraint is violated at the current point */ + if (type == GLP_LO) + { if (y >= rhs) + { /* the constraint is not violated */ + ret = 1; + goto done; + } + /* in the adjacent basis y goes to its lower bound */ + dir = +1; + } + else if (type == GLP_UP) + { if (y <= rhs) + { /* the constraint is not violated */ + ret = 1; + goto done; + } + /* in the adjacent basis y goes to its upper bound */ + dir = -1; + } + else + xerror("glp_analyze_row: type = %d; invalid parameter\n", + type); + /* compute dy = y.new - y.old */ + dy = rhs - y; + /* perform dual ratio test to determine which non-basic variable + should enter the adjacent basis to keep it dual feasible */ + piv = glp_dual_rtest(P, len, ind, val, dir, eps); + if (piv == 0) + { /* no dual feasible adjacent basis exists */ + ret = 2; + goto done; + } + /* non-basic variable x[k] = xN[j] should enter the basis */ + k = ind[piv]; + xassert(1 <= k && k <= P->m+P->n); + /* determine its value in the current basis */ + if (k <= P->m) + x = P->row[k]->prim; + else + x = P->col[k-P->m]->prim; + /* compute dx = x.new - x.old = dy / alfa[j] */ + xassert(val[piv] != 0.0); + dx = dy / val[piv]; + /* compute dz = z.new - z.old = d[j] * dx, where d[j] is reduced + cost of xN[j] in the current basis */ + if (k <= P->m) + dz = P->row[k]->dual * dx; + else + dz = P->col[k-P->m]->dual * dx; + /* store the analysis results */ + if (_piv != NULL) *_piv = piv; + if (_x != NULL) *_x = x; + if (_dx != NULL) *_dx = dx; + if (_y != NULL) *_y = y; + if (_dy != NULL) *_dy = dy; + if (_dz != NULL) *_dz = dz; +done: return ret; +} + +#if 0 +int main(void) +{ /* example program for the routine glp_analyze_row */ + glp_prob *P; + glp_smcp parm; + int i, k, len, piv, ret, ind[1+100]; + double rhs, x, dx, y, dy, dz, val[1+100]; + P = glp_create_prob(); + /* read plan.mps (see glpk/examples) */ + ret = glp_read_mps(P, GLP_MPS_DECK, NULL, "plan.mps"); + glp_assert(ret == 0); + /* and solve it to optimality */ + ret = glp_simplex(P, NULL); + glp_assert(ret == 0); + glp_assert(glp_get_status(P) == GLP_OPT); + /* the optimal objective value is 296.217 */ + /* we would like to know what happens if we would add a new row + (constraint) to plan.mps: + .01 * bin1 + .01 * bin2 + .02 * bin4 + .02 * bin5 <= 12 */ + /* first, we specify this new row */ + glp_create_index(P); + len = 0; + ind[++len] = glp_find_col(P, "BIN1"), val[len] = .01; + ind[++len] = glp_find_col(P, "BIN2"), val[len] = .01; + ind[++len] = glp_find_col(P, "BIN4"), val[len] = .02; + ind[++len] = glp_find_col(P, "BIN5"), val[len] = .02; + rhs = 12; + /* then we can compute value of the row (i.e. of its auxiliary + variable) in the current basis to see if the constraint is + violated */ + y = 0.0; + for (k = 1; k <= len; k++) + y += val[k] * glp_get_col_prim(P, ind[k]); + glp_printf("y = %g\n", y); + /* this prints y = 15.1372, so the constraint is violated, since + we require that y <= rhs = 12 */ + /* now we transform the row to express it only through non-basic + (auxiliary and artificial) variables */ + len = glp_transform_row(P, len, ind, val); + /* finally, we simulate one step of the dual simplex method to + obtain necessary information for the adjacent basis */ + ret = _glp_analyze_row(P, len, ind, val, GLP_UP, rhs, 1e-9, &piv, + &x, &dx, &y, &dy, &dz); + glp_assert(ret == 0); + glp_printf("k = %d, x = %g; dx = %g; y = %g; dy = %g; dz = %g\n", + ind[piv], x, dx, y, dy, dz); + /* this prints dz = 5.64418 and means that in the adjacent basis + the objective function would be 296.217 + 5.64418 = 301.861 */ + /* now we actually include the row into the problem object; note + that the arrays ind and val are clobbered, so we need to build + them once again */ + len = 0; + ind[++len] = glp_find_col(P, "BIN1"), val[len] = .01; + ind[++len] = glp_find_col(P, "BIN2"), val[len] = .01; + ind[++len] = glp_find_col(P, "BIN4"), val[len] = .02; + ind[++len] = glp_find_col(P, "BIN5"), val[len] = .02; + rhs = 12; + i = glp_add_rows(P, 1); + glp_set_row_bnds(P, i, GLP_UP, 0, rhs); + glp_set_mat_row(P, i, len, ind, val); + /* and perform one dual simplex iteration */ + glp_init_smcp(&parm); + parm.meth = GLP_DUAL; + parm.it_lim = 1; + glp_simplex(P, &parm); + /* the current objective value is 301.861 */ + return 0; +} +#endif + +/*********************************************************************** +* NAME +* +* glp_analyze_bound - analyze active bound of non-basic variable +* +* SYNOPSIS +* +* void glp_analyze_bound(glp_prob *P, int k, double *limit1, int *var1, +* double *limit2, int *var2); +* +* DESCRIPTION +* +* The routine glp_analyze_bound analyzes the effect of varying the +* active bound of specified non-basic variable. +* +* The non-basic variable is specified by the parameter k, where +* 1 <= k <= m means auxiliary variable of corresponding row while +* m+1 <= k <= m+n means structural variable (column). +* +* Note that the current basic solution must be optimal, and the basis +* factorization must exist. +* +* Results of the analysis have the following meaning. +* +* value1 is the minimal value of the active bound, at which the basis +* still remains primal feasible and thus optimal. -DBL_MAX means that +* the active bound has no lower limit. +* +* var1 is the ordinal number of an auxiliary (1 to m) or structural +* (m+1 to n) basic variable, which reaches its bound first and thereby +* limits further decreasing the active bound being analyzed. +* if value1 = -DBL_MAX, var1 is set to 0. +* +* value2 is the maximal value of the active bound, at which the basis +* still remains primal feasible and thus optimal. +DBL_MAX means that +* the active bound has no upper limit. +* +* var2 is the ordinal number of an auxiliary (1 to m) or structural +* (m+1 to n) basic variable, which reaches its bound first and thereby +* limits further increasing the active bound being analyzed. +* if value2 = +DBL_MAX, var2 is set to 0. */ + +void glp_analyze_bound(glp_prob *P, int k, double *value1, int *var1, + double *value2, int *var2) +{ GLPROW *row; + GLPCOL *col; + int m, n, stat, kase, p, len, piv, *ind; + double x, new_x, ll, uu, xx, delta, *val; + /* sanity checks */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_analyze_bound: P = %p; invalid problem object\n", + P); + m = P->m, n = P->n; + if (!(P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS)) + xerror("glp_analyze_bound: optimal basic solution required\n"); + if (!(m == 0 || P->valid)) + xerror("glp_analyze_bound: basis factorization required\n"); + if (!(1 <= k && k <= m+n)) + xerror("glp_analyze_bound: k = %d; variable number out of rang" + "e\n", k); + /* retrieve information about the specified non-basic variable + x[k] whose active bound is to be analyzed */ + if (k <= m) + { row = P->row[k]; + stat = row->stat; + x = row->prim; + } + else + { col = P->col[k-m]; + stat = col->stat; + x = col->prim; + } + if (stat == GLP_BS) + xerror("glp_analyze_bound: k = %d; basic variable not allowed " + "\n", k); + /* allocate working arrays */ + ind = xcalloc(1+m, sizeof(int)); + val = xcalloc(1+m, sizeof(double)); + /* compute column of the simplex table corresponding to the + non-basic variable x[k] */ + len = glp_eval_tab_col(P, k, ind, val); + xassert(0 <= len && len <= m); + /* perform analysis */ + for (kase = -1; kase <= +1; kase += 2) + { /* kase < 0 means active bound of x[k] is decreasing; + kase > 0 means active bound of x[k] is increasing */ + /* use the primal ratio test to determine some basic variable + x[p] which reaches its bound first */ + piv = glp_prim_rtest(P, len, ind, val, kase, 1e-9); + if (piv == 0) + { /* nothing limits changing the active bound of x[k] */ + p = 0; + new_x = (kase < 0 ? -DBL_MAX : +DBL_MAX); + goto store; + } + /* basic variable x[p] limits changing the active bound of + x[k]; determine its value in the current basis */ + xassert(1 <= piv && piv <= len); + p = ind[piv]; + if (p <= m) + { row = P->row[p]; + ll = glp_get_row_lb(P, row->i); + uu = glp_get_row_ub(P, row->i); + stat = row->stat; + xx = row->prim; + } + else + { col = P->col[p-m]; + ll = glp_get_col_lb(P, col->j); + uu = glp_get_col_ub(P, col->j); + stat = col->stat; + xx = col->prim; + } + xassert(stat == GLP_BS); + /* determine delta x[p] = bound of x[p] - value of x[p] */ + if (kase < 0 && val[piv] > 0.0 || + kase > 0 && val[piv] < 0.0) + { /* delta x[p] < 0, so x[p] goes toward its lower bound */ + xassert(ll != -DBL_MAX); + delta = ll - xx; + } + else + { /* delta x[p] > 0, so x[p] goes toward its upper bound */ + xassert(uu != +DBL_MAX); + delta = uu - xx; + } + /* delta x[p] = alfa[p,k] * delta x[k], so new x[k] = x[k] + + delta x[k] = x[k] + delta x[p] / alfa[p,k] is the value of + x[k] in the adjacent basis */ + xassert(val[piv] != 0.0); + new_x = x + delta / val[piv]; +store: /* store analysis results */ + if (kase < 0) + { if (value1 != NULL) *value1 = new_x; + if (var1 != NULL) *var1 = p; + } + else + { if (value2 != NULL) *value2 = new_x; + if (var2 != NULL) *var2 = p; + } + } + /* free working arrays */ + xfree(ind); + xfree(val); + return; +} + +/*********************************************************************** +* NAME +* +* glp_analyze_coef - analyze objective coefficient at basic variable +* +* SYNOPSIS +* +* void glp_analyze_coef(glp_prob *P, int k, double *coef1, int *var1, +* double *value1, double *coef2, int *var2, double *value2); +* +* DESCRIPTION +* +* The routine glp_analyze_coef analyzes the effect of varying the +* objective coefficient at specified basic variable. +* +* The basic variable is specified by the parameter k, where +* 1 <= k <= m means auxiliary variable of corresponding row while +* m+1 <= k <= m+n means structural variable (column). +* +* Note that the current basic solution must be optimal, and the basis +* factorization must exist. +* +* Results of the analysis have the following meaning. +* +* coef1 is the minimal value of the objective coefficient, at which +* the basis still remains dual feasible and thus optimal. -DBL_MAX +* means that the objective coefficient has no lower limit. +* +* var1 is the ordinal number of an auxiliary (1 to m) or structural +* (m+1 to n) non-basic variable, whose reduced cost reaches its zero +* bound first and thereby limits further decreasing the objective +* coefficient being analyzed. If coef1 = -DBL_MAX, var1 is set to 0. +* +* value1 is value of the basic variable being analyzed in an adjacent +* basis, which is defined as follows. Let the objective coefficient +* reaches its minimal value (coef1) and continues decreasing. Then the +* reduced cost of the limiting non-basic variable (var1) becomes dual +* infeasible and the current basis becomes non-optimal that forces the +* limiting non-basic variable to enter the basis replacing there some +* basic variable that leaves the basis to keep primal feasibility. +* Should note that on determining the adjacent basis current bounds +* of the basic variable being analyzed are ignored as if it were free +* (unbounded) variable, so it cannot leave the basis. It may happen +* that no dual feasible adjacent basis exists, in which case value1 is +* set to -DBL_MAX or +DBL_MAX. +* +* coef2 is the maximal value of the objective coefficient, at which +* the basis still remains dual feasible and thus optimal. +DBL_MAX +* means that the objective coefficient has no upper limit. +* +* var2 is the ordinal number of an auxiliary (1 to m) or structural +* (m+1 to n) non-basic variable, whose reduced cost reaches its zero +* bound first and thereby limits further increasing the objective +* coefficient being analyzed. If coef2 = +DBL_MAX, var2 is set to 0. +* +* value2 is value of the basic variable being analyzed in an adjacent +* basis, which is defined exactly in the same way as value1 above with +* exception that now the objective coefficient is increasing. */ + +void glp_analyze_coef(glp_prob *P, int k, double *coef1, int *var1, + double *value1, double *coef2, int *var2, double *value2) +{ GLPROW *row; GLPCOL *col; + int m, n, type, stat, kase, p, q, dir, clen, cpiv, rlen, rpiv, + *cind, *rind; + double lb, ub, coef, x, lim_coef, new_x, d, delta, ll, uu, xx, + *rval, *cval; + /* sanity checks */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_analyze_coef: P = %p; invalid problem object\n", + P); + m = P->m, n = P->n; + if (!(P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS)) + xerror("glp_analyze_coef: optimal basic solution required\n"); + if (!(m == 0 || P->valid)) + xerror("glp_analyze_coef: basis factorization required\n"); + if (!(1 <= k && k <= m+n)) + xerror("glp_analyze_coef: k = %d; variable number out of range" + "\n", k); + /* retrieve information about the specified basic variable x[k] + whose objective coefficient c[k] is to be analyzed */ + if (k <= m) + { row = P->row[k]; + type = row->type; + lb = row->lb; + ub = row->ub; + coef = 0.0; + stat = row->stat; + x = row->prim; + } + else + { col = P->col[k-m]; + type = col->type; + lb = col->lb; + ub = col->ub; + coef = col->coef; + stat = col->stat; + x = col->prim; + } + if (stat != GLP_BS) + xerror("glp_analyze_coef: k = %d; non-basic variable not allow" + "ed\n", k); + /* allocate working arrays */ + cind = xcalloc(1+m, sizeof(int)); + cval = xcalloc(1+m, sizeof(double)); + rind = xcalloc(1+n, sizeof(int)); + rval = xcalloc(1+n, sizeof(double)); + /* compute row of the simplex table corresponding to the basic + variable x[k] */ + rlen = glp_eval_tab_row(P, k, rind, rval); + xassert(0 <= rlen && rlen <= n); + /* perform analysis */ + for (kase = -1; kase <= +1; kase += 2) + { /* kase < 0 means objective coefficient c[k] is decreasing; + kase > 0 means objective coefficient c[k] is increasing */ + /* note that decreasing c[k] is equivalent to increasing dual + variable lambda[k] and vice versa; we need to correctly set + the dir flag as required by the routine glp_dual_rtest */ + if (P->dir == GLP_MIN) + dir = - kase; + else if (P->dir == GLP_MAX) + dir = + kase; + else + xassert(P != P); + /* use the dual ratio test to determine non-basic variable + x[q] whose reduced cost d[q] reaches zero bound first */ + rpiv = glp_dual_rtest(P, rlen, rind, rval, dir, 1e-9); + if (rpiv == 0) + { /* nothing limits changing c[k] */ + lim_coef = (kase < 0 ? -DBL_MAX : +DBL_MAX); + q = 0; + /* x[k] keeps its current value */ + new_x = x; + goto store; + } + /* non-basic variable x[q] limits changing coefficient c[k]; + determine its status and reduced cost d[k] in the current + basis */ + xassert(1 <= rpiv && rpiv <= rlen); + q = rind[rpiv]; + xassert(1 <= q && q <= m+n); + if (q <= m) + { row = P->row[q]; + stat = row->stat; + d = row->dual; + } + else + { col = P->col[q-m]; + stat = col->stat; + d = col->dual; + } + /* note that delta d[q] = new d[q] - d[q] = - d[q], because + new d[q] = 0; delta d[q] = alfa[k,q] * delta c[k], so + delta c[k] = delta d[q] / alfa[k,q] = - d[q] / alfa[k,q] */ + xassert(rval[rpiv] != 0.0); + delta = - d / rval[rpiv]; + /* compute new c[k] = c[k] + delta c[k], which is the limiting + value of the objective coefficient c[k] */ + lim_coef = coef + delta; + /* let c[k] continue decreasing/increasing that makes d[q] + dual infeasible and forces x[q] to enter the basis; + to perform the primal ratio test we need to know in which + direction x[q] changes on entering the basis; we determine + that analyzing the sign of delta d[q] (see above), since + d[q] may be close to zero having wrong sign */ + /* let, for simplicity, the problem is minimization */ + if (kase < 0 && rval[rpiv] > 0.0 || + kase > 0 && rval[rpiv] < 0.0) + { /* delta d[q] < 0, so d[q] being non-negative will become + negative, so x[q] will increase */ + dir = +1; + } + else + { /* delta d[q] > 0, so d[q] being non-positive will become + positive, so x[q] will decrease */ + dir = -1; + } + /* if the problem is maximization, correct the direction */ + if (P->dir == GLP_MAX) dir = - dir; + /* check that we didn't make a silly mistake */ + if (dir > 0) + xassert(stat == GLP_NL || stat == GLP_NF); + else + xassert(stat == GLP_NU || stat == GLP_NF); + /* compute column of the simplex table corresponding to the + non-basic variable x[q] */ + clen = glp_eval_tab_col(P, q, cind, cval); + /* make x[k] temporarily free (unbounded) */ + if (k <= m) + { row = P->row[k]; + row->type = GLP_FR; + row->lb = row->ub = 0.0; + } + else + { col = P->col[k-m]; + col->type = GLP_FR; + col->lb = col->ub = 0.0; + } + /* use the primal ratio test to determine some basic variable + which leaves the basis */ + cpiv = glp_prim_rtest(P, clen, cind, cval, dir, 1e-9); + /* restore original bounds of the basic variable x[k] */ + if (k <= m) + { row = P->row[k]; + row->type = type; + row->lb = lb, row->ub = ub; + } + else + { col = P->col[k-m]; + col->type = type; + col->lb = lb, col->ub = ub; + } + if (cpiv == 0) + { /* non-basic variable x[q] can change unlimitedly */ + if (dir < 0 && rval[rpiv] > 0.0 || + dir > 0 && rval[rpiv] < 0.0) + { /* delta x[k] = alfa[k,q] * delta x[q] < 0 */ + new_x = -DBL_MAX; + } + else + { /* delta x[k] = alfa[k,q] * delta x[q] > 0 */ + new_x = +DBL_MAX; + } + goto store; + } + /* some basic variable x[p] limits changing non-basic variable + x[q] in the adjacent basis */ + xassert(1 <= cpiv && cpiv <= clen); + p = cind[cpiv]; + xassert(1 <= p && p <= m+n); + xassert(p != k); + if (p <= m) + { row = P->row[p]; + xassert(row->stat == GLP_BS); + ll = glp_get_row_lb(P, row->i); + uu = glp_get_row_ub(P, row->i); + xx = row->prim; + } + else + { col = P->col[p-m]; + xassert(col->stat == GLP_BS); + ll = glp_get_col_lb(P, col->j); + uu = glp_get_col_ub(P, col->j); + xx = col->prim; + } + /* determine delta x[p] = new x[p] - x[p] */ + if (dir < 0 && cval[cpiv] > 0.0 || + dir > 0 && cval[cpiv] < 0.0) + { /* delta x[p] < 0, so x[p] goes toward its lower bound */ + xassert(ll != -DBL_MAX); + delta = ll - xx; + } + else + { /* delta x[p] > 0, so x[p] goes toward its upper bound */ + xassert(uu != +DBL_MAX); + delta = uu - xx; + } + /* compute new x[k] = x[k] + alfa[k,q] * delta x[q], where + delta x[q] = delta x[p] / alfa[p,q] */ + xassert(cval[cpiv] != 0.0); + new_x = x + (rval[rpiv] / cval[cpiv]) * delta; +store: /* store analysis results */ + if (kase < 0) + { if (coef1 != NULL) *coef1 = lim_coef; + if (var1 != NULL) *var1 = q; + if (value1 != NULL) *value1 = new_x; + } + else + { if (coef2 != NULL) *coef2 = lim_coef; + if (var2 != NULL) *var2 = q; + if (value2 != NULL) *value2 = new_x; + } + } + /* free working arrays */ + xfree(cind); + xfree(cval); + xfree(rind); + xfree(rval); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi13.c b/resources/3rdparty/glpk-4.53/src/glpapi13.c new file mode 100644 index 000000000..a4ad10b66 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi13.c @@ -0,0 +1,706 @@ +/* glpapi13.c (branch-and-bound interface routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" + +/*********************************************************************** +* NAME +* +* glp_ios_reason - determine reason for calling the callback routine +* +* SYNOPSIS +* +* glp_ios_reason(glp_tree *tree); +* +* RETURNS +* +* The routine glp_ios_reason returns a code, which indicates why the +* user-defined callback routine is being called. */ + +int glp_ios_reason(glp_tree *tree) +{ return + tree->reason; +} + +/*********************************************************************** +* NAME +* +* glp_ios_get_prob - access the problem object +* +* SYNOPSIS +* +* glp_prob *glp_ios_get_prob(glp_tree *tree); +* +* DESCRIPTION +* +* The routine glp_ios_get_prob can be called from the user-defined +* callback routine to access the problem object, which is used by the +* MIP solver. It is the original problem object passed to the routine +* glp_intopt if the MIP presolver is not used; otherwise it is an +* internal problem object built by the presolver. If the current +* subproblem exists, LP segment of the problem object corresponds to +* its LP relaxation. +* +* RETURNS +* +* The routine glp_ios_get_prob returns a pointer to the problem object +* used by the MIP solver. */ + +glp_prob *glp_ios_get_prob(glp_tree *tree) +{ return + tree->mip; +} + +/*********************************************************************** +* NAME +* +* glp_ios_tree_size - determine size of the branch-and-bound tree +* +* SYNOPSIS +* +* void glp_ios_tree_size(glp_tree *tree, int *a_cnt, int *n_cnt, +* int *t_cnt); +* +* DESCRIPTION +* +* The routine glp_ios_tree_size stores the following three counts which +* characterize the current size of the branch-and-bound tree: +* +* a_cnt is the current number of active nodes, i.e. the current size of +* the active list; +* +* n_cnt is the current number of all (active and inactive) nodes; +* +* t_cnt is the total number of nodes including those which have been +* already removed from the tree. This count is increased whenever +* a new node appears in the tree and never decreased. +* +* If some of the parameters a_cnt, n_cnt, t_cnt is a null pointer, the +* corresponding count is not stored. */ + +void glp_ios_tree_size(glp_tree *tree, int *a_cnt, int *n_cnt, + int *t_cnt) +{ if (a_cnt != NULL) *a_cnt = tree->a_cnt; + if (n_cnt != NULL) *n_cnt = tree->n_cnt; + if (t_cnt != NULL) *t_cnt = tree->t_cnt; + return; +} + +/*********************************************************************** +* NAME +* +* glp_ios_curr_node - determine current active subproblem +* +* SYNOPSIS +* +* int glp_ios_curr_node(glp_tree *tree); +* +* RETURNS +* +* The routine glp_ios_curr_node returns the reference number of the +* current active subproblem. However, if the current subproblem does +* not exist, the routine returns zero. */ + +int glp_ios_curr_node(glp_tree *tree) +{ IOSNPD *node; + /* obtain pointer to the current subproblem */ + node = tree->curr; + /* return its reference number */ + return node == NULL ? 0 : node->p; +} + +/*********************************************************************** +* NAME +* +* glp_ios_next_node - determine next active subproblem +* +* SYNOPSIS +* +* int glp_ios_next_node(glp_tree *tree, int p); +* +* RETURNS +* +* If the parameter p is zero, the routine glp_ios_next_node returns +* the reference number of the first active subproblem. However, if the +* tree is empty, zero is returned. +* +* If the parameter p is not zero, it must specify the reference number +* of some active subproblem, in which case the routine returns the +* reference number of the next active subproblem. However, if there is +* no next active subproblem in the list, zero is returned. +* +* All subproblems in the active list are ordered chronologically, i.e. +* subproblem A precedes subproblem B if A was created before B. */ + +int glp_ios_next_node(glp_tree *tree, int p) +{ IOSNPD *node; + if (p == 0) + { /* obtain pointer to the first active subproblem */ + node = tree->head; + } + else + { /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_next_node: p = %d; invalid subproblem refer" + "ence number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* the specified subproblem must be active */ + if (node->count != 0) + xerror("glp_ios_next_node: p = %d; subproblem not in the ac" + "tive list\n", p); + /* obtain pointer to the next active subproblem */ + node = node->next; + } + /* return the reference number */ + return node == NULL ? 0 : node->p; +} + +/*********************************************************************** +* NAME +* +* glp_ios_prev_node - determine previous active subproblem +* +* SYNOPSIS +* +* int glp_ios_prev_node(glp_tree *tree, int p); +* +* RETURNS +* +* If the parameter p is zero, the routine glp_ios_prev_node returns +* the reference number of the last active subproblem. However, if the +* tree is empty, zero is returned. +* +* If the parameter p is not zero, it must specify the reference number +* of some active subproblem, in which case the routine returns the +* reference number of the previous active subproblem. However, if there +* is no previous active subproblem in the list, zero is returned. +* +* All subproblems in the active list are ordered chronologically, i.e. +* subproblem A precedes subproblem B if A was created before B. */ + +int glp_ios_prev_node(glp_tree *tree, int p) +{ IOSNPD *node; + if (p == 0) + { /* obtain pointer to the last active subproblem */ + node = tree->tail; + } + else + { /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_prev_node: p = %d; invalid subproblem refer" + "ence number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* the specified subproblem must be active */ + if (node->count != 0) + xerror("glp_ios_prev_node: p = %d; subproblem not in the ac" + "tive list\n", p); + /* obtain pointer to the previous active subproblem */ + node = node->prev; + } + /* return the reference number */ + return node == NULL ? 0 : node->p; +} + +/*********************************************************************** +* NAME +* +* glp_ios_up_node - determine parent subproblem +* +* SYNOPSIS +* +* int glp_ios_up_node(glp_tree *tree, int p); +* +* RETURNS +* +* The parameter p must specify the reference number of some (active or +* inactive) subproblem, in which case the routine iet_get_up_node +* returns the reference number of its parent subproblem. However, if +* the specified subproblem is the root of the tree and, therefore, has +* no parent, the routine returns zero. */ + +int glp_ios_up_node(glp_tree *tree, int p) +{ IOSNPD *node; + /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_up_node: p = %d; invalid subproblem reference " + "number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* obtain pointer to the parent subproblem */ + node = node->up; + /* return the reference number */ + return node == NULL ? 0 : node->p; +} + +/*********************************************************************** +* NAME +* +* glp_ios_node_level - determine subproblem level +* +* SYNOPSIS +* +* int glp_ios_node_level(glp_tree *tree, int p); +* +* RETURNS +* +* The routine glp_ios_node_level returns the level of the subproblem, +* whose reference number is p, in the branch-and-bound tree. (The root +* subproblem has level 0, and the level of any other subproblem is the +* level of its parent plus one.) */ + +int glp_ios_node_level(glp_tree *tree, int p) +{ IOSNPD *node; + /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_node_level: p = %d; invalid subproblem referen" + "ce number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* return the node level */ + return node->level; +} + +/*********************************************************************** +* NAME +* +* glp_ios_node_bound - determine subproblem local bound +* +* SYNOPSIS +* +* double glp_ios_node_bound(glp_tree *tree, int p); +* +* RETURNS +* +* The routine glp_ios_node_bound returns the local bound for (active or +* inactive) subproblem, whose reference number is p. +* +* COMMENTS +* +* The local bound for subproblem p is an lower (minimization) or upper +* (maximization) bound for integer optimal solution to this subproblem +* (not to the original problem). This bound is local in the sense that +* only subproblems in the subtree rooted at node p cannot have better +* integer feasible solutions. +* +* On creating a subproblem (due to the branching step) its local bound +* is inherited from its parent and then may get only stronger (never +* weaker). For the root subproblem its local bound is initially set to +* -DBL_MAX (minimization) or +DBL_MAX (maximization) and then improved +* as the root LP relaxation has been solved. +* +* Note that the local bound is not necessarily the optimal objective +* value to corresponding LP relaxation; it may be stronger. */ + +double glp_ios_node_bound(glp_tree *tree, int p) +{ IOSNPD *node; + /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_node_bound: p = %d; invalid subproblem referen" + "ce number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* return the node local bound */ + return node->bound; +} + +/*********************************************************************** +* NAME +* +* glp_ios_best_node - find active subproblem with best local bound +* +* SYNOPSIS +* +* int glp_ios_best_node(glp_tree *tree); +* +* RETURNS +* +* The routine glp_ios_best_node returns the reference number of the +* active subproblem, whose local bound is best (i.e. smallest in case +* of minimization or largest in case of maximization). However, if the +* tree is empty, the routine returns zero. +* +* COMMENTS +* +* The best local bound is an lower (minimization) or upper +* (maximization) bound for integer optimal solution to the original +* MIP problem. */ + +int glp_ios_best_node(glp_tree *tree) +{ return + ios_best_node(tree); +} + +/*********************************************************************** +* NAME +* +* glp_ios_mip_gap - compute relative MIP gap +* +* SYNOPSIS +* +* double glp_ios_mip_gap(glp_tree *tree); +* +* DESCRIPTION +* +* The routine glp_ios_mip_gap computes the relative MIP gap with the +* following formula: +* +* gap = |best_mip - best_bnd| / (|best_mip| + DBL_EPSILON), +* +* where best_mip is the best integer feasible solution found so far, +* best_bnd is the best (global) bound. If no integer feasible solution +* has been found yet, gap is set to DBL_MAX. +* +* RETURNS +* +* The routine glp_ios_mip_gap returns the relative MIP gap. */ + +double glp_ios_mip_gap(glp_tree *tree) +{ return + ios_relative_gap(tree); +} + +/*********************************************************************** +* NAME +* +* glp_ios_node_data - access subproblem application-specific data +* +* SYNOPSIS +* +* void *glp_ios_node_data(glp_tree *tree, int p); +* +* DESCRIPTION +* +* The routine glp_ios_node_data allows the application accessing a +* memory block allocated for the subproblem (which may be active or +* inactive), whose reference number is p. +* +* The size of the block is defined by the control parameter cb_size +* passed to the routine glp_intopt. The block is initialized by binary +* zeros on creating corresponding subproblem, and its contents is kept +* until the subproblem will be removed from the tree. +* +* The application may use these memory blocks to store specific data +* for each subproblem. +* +* RETURNS +* +* The routine glp_ios_node_data returns a pointer to the memory block +* for the specified subproblem. Note that if cb_size = 0, the routine +* returns a null pointer. */ + +void *glp_ios_node_data(glp_tree *tree, int p) +{ IOSNPD *node; + /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_node_level: p = %d; invalid subproblem referen" + "ce number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* return pointer to the application-specific data */ + return node->data; +} + +/*********************************************************************** +* NAME +* +* glp_ios_row_attr - retrieve additional row attributes +* +* SYNOPSIS +* +* void glp_ios_row_attr(glp_tree *tree, int i, glp_attr *attr); +* +* DESCRIPTION +* +* The routine glp_ios_row_attr retrieves additional attributes of row +* i and stores them in the structure glp_attr. */ + +void glp_ios_row_attr(glp_tree *tree, int i, glp_attr *attr) +{ GLPROW *row; + if (!(1 <= i && i <= tree->mip->m)) + xerror("glp_ios_row_attr: i = %d; row number out of range\n", + i); + row = tree->mip->row[i]; + attr->level = row->level; + attr->origin = row->origin; + attr->klass = row->klass; + return; +} + +/**********************************************************************/ + +int glp_ios_pool_size(glp_tree *tree) +{ /* determine current size of the cut pool */ + if (tree->reason != GLP_ICUTGEN) + xerror("glp_ios_pool_size: operation not allowed\n"); + xassert(tree->local != NULL); + return tree->local->size; +} + +/**********************************************************************/ + +int glp_ios_add_row(glp_tree *tree, + const char *name, int klass, int flags, int len, const int ind[], + const double val[], int type, double rhs) +{ /* add row (constraint) to the cut pool */ + int num; + if (tree->reason != GLP_ICUTGEN) + xerror("glp_ios_add_row: operation not allowed\n"); + xassert(tree->local != NULL); + num = ios_add_row(tree, tree->local, name, klass, flags, len, + ind, val, type, rhs); + return num; +} + +/**********************************************************************/ + +void glp_ios_del_row(glp_tree *tree, int i) +{ /* remove row (constraint) from the cut pool */ + if (tree->reason != GLP_ICUTGEN) + xerror("glp_ios_del_row: operation not allowed\n"); + ios_del_row(tree, tree->local, i); + return; +} + +/**********************************************************************/ + +void glp_ios_clear_pool(glp_tree *tree) +{ /* remove all rows (constraints) from the cut pool */ + if (tree->reason != GLP_ICUTGEN) + xerror("glp_ios_clear_pool: operation not allowed\n"); + ios_clear_pool(tree, tree->local); + return; +} + +/*********************************************************************** +* NAME +* +* glp_ios_can_branch - check if can branch upon specified variable +* +* SYNOPSIS +* +* int glp_ios_can_branch(glp_tree *tree, int j); +* +* RETURNS +* +* If j-th variable (column) can be used to branch upon, the routine +* glp_ios_can_branch returns non-zero, otherwise zero. */ + +int glp_ios_can_branch(glp_tree *tree, int j) +{ if (!(1 <= j && j <= tree->mip->n)) + xerror("glp_ios_can_branch: j = %d; column number out of range" + "\n", j); + return tree->non_int[j]; +} + +/*********************************************************************** +* NAME +* +* glp_ios_branch_upon - choose variable to branch upon +* +* SYNOPSIS +* +* void glp_ios_branch_upon(glp_tree *tree, int j, int sel); +* +* DESCRIPTION +* +* The routine glp_ios_branch_upon can be called from the user-defined +* callback routine in response to the reason GLP_IBRANCH to choose a +* branching variable, whose ordinal number is j. Should note that only +* variables, for which the routine glp_ios_can_branch returns non-zero, +* can be used to branch upon. +* +* The parameter sel is a flag that indicates which branch (subproblem) +* should be selected next to continue the search: +* +* GLP_DN_BRNCH - select down-branch; +* GLP_UP_BRNCH - select up-branch; +* GLP_NO_BRNCH - use general selection technique. */ + +void glp_ios_branch_upon(glp_tree *tree, int j, int sel) +{ if (!(1 <= j && j <= tree->mip->n)) + xerror("glp_ios_branch_upon: j = %d; column number out of rang" + "e\n", j); + if (!(sel == GLP_DN_BRNCH || sel == GLP_UP_BRNCH || + sel == GLP_NO_BRNCH)) + xerror("glp_ios_branch_upon: sel = %d: invalid branch selectio" + "n flag\n", sel); + if (!(tree->non_int[j])) + xerror("glp_ios_branch_upon: j = %d; variable cannot be used t" + "o branch upon\n", j); + if (tree->br_var != 0) + xerror("glp_ios_branch_upon: branching variable already chosen" + "\n"); + tree->br_var = j; + tree->br_sel = sel; + return; +} + +/*********************************************************************** +* NAME +* +* glp_ios_select_node - select subproblem to continue the search +* +* SYNOPSIS +* +* void glp_ios_select_node(glp_tree *tree, int p); +* +* DESCRIPTION +* +* The routine glp_ios_select_node can be called from the user-defined +* callback routine in response to the reason GLP_ISELECT to select an +* active subproblem, whose reference number is p. The search will be +* continued from the subproblem selected. */ + +void glp_ios_select_node(glp_tree *tree, int p) +{ IOSNPD *node; + /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_select_node: p = %d; invalid subproblem refere" + "nce number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* the specified subproblem must be active */ + if (node->count != 0) + xerror("glp_ios_select_node: p = %d; subproblem not in the act" + "ive list\n", p); + /* no subproblem must be selected yet */ + if (tree->next_p != 0) + xerror("glp_ios_select_node: subproblem already selected\n"); + /* select the specified subproblem to continue the search */ + tree->next_p = p; + return; +} + +/*********************************************************************** +* NAME +* +* glp_ios_heur_sol - provide solution found by heuristic +* +* SYNOPSIS +* +* int glp_ios_heur_sol(glp_tree *tree, const double x[]); +* +* DESCRIPTION +* +* The routine glp_ios_heur_sol can be called from the user-defined +* callback routine in response to the reason GLP_IHEUR to provide an +* integer feasible solution found by a primal heuristic. +* +* Primal values of *all* variables (columns) found by the heuristic +* should be placed in locations x[1], ..., x[n], where n is the number +* of columns in the original problem object. Note that the routine +* glp_ios_heur_sol *does not* check primal feasibility of the solution +* provided. +* +* Using the solution passed in the array x the routine computes value +* of the objective function. If the objective value is better than the +* best known integer feasible solution, the routine computes values of +* auxiliary variables (rows) and stores all solution components in the +* problem object. +* +* RETURNS +* +* If the provided solution is accepted, the routine glp_ios_heur_sol +* returns zero. Otherwise, if the provided solution is rejected, the +* routine returns non-zero. */ + +int glp_ios_heur_sol(glp_tree *tree, const double x[]) +{ glp_prob *mip = tree->mip; + int m = tree->orig_m; + int n = tree->n; + int i, j; + double obj; + xassert(mip->m >= m); + xassert(mip->n == n); + /* check values of integer variables and compute value of the + objective function */ + obj = mip->c0; + for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + if (col->kind == GLP_IV) + { /* provided value must be integral */ + if (x[j] != floor(x[j])) return 1; + } + obj += col->coef * x[j]; + } + /* check if the provided solution is better than the best known + integer feasible solution */ + if (mip->mip_stat == GLP_FEAS) + { switch (mip->dir) + { case GLP_MIN: + if (obj >= tree->mip->mip_obj) return 1; + break; + case GLP_MAX: + if (obj <= tree->mip->mip_obj) return 1; + break; + default: + xassert(mip != mip); + } + } + /* it is better; store it in the problem object */ + if (tree->parm->msg_lev >= GLP_MSG_ON) + xprintf("Solution found by heuristic: %.12g\n", obj); + mip->mip_stat = GLP_FEAS; + mip->mip_obj = obj; + for (j = 1; j <= n; j++) + mip->col[j]->mipx = x[j]; + for (i = 1; i <= m; i++) + { GLPROW *row = mip->row[i]; + GLPAIJ *aij; + row->mipx = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + row->mipx += aij->val * aij->col->mipx; + } +#if 1 /* 11/VII-2013 */ + ios_process_sol(tree); +#endif + return 0; +} + +/*********************************************************************** +* NAME +* +* glp_ios_terminate - terminate the solution process. +* +* SYNOPSIS +* +* void glp_ios_terminate(glp_tree *tree); +* +* DESCRIPTION +* +* The routine glp_ios_terminate sets a flag indicating that the MIP +* solver should prematurely terminate the search. */ + +void glp_ios_terminate(glp_tree *tree) +{ if (tree->parm->msg_lev >= GLP_MSG_DBG) + xprintf("The search is prematurely terminated due to applicati" + "on request\n"); + tree->stop = 1; + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi14.c b/resources/3rdparty/glpk-4.53/src/glpapi14.c new file mode 100644 index 000000000..fc3b73757 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi14.c @@ -0,0 +1,272 @@ +/* glpapi14.c (processing models in GNU MathProg language) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "draft.h" +#include "glpmpl.h" +#include "prob.h" + +glp_tran *glp_mpl_alloc_wksp(void) +{ /* allocate the MathProg translator workspace */ + glp_tran *tran; + tran = mpl_initialize(); + return tran; +} + +#if 1 /* 08/XII-2009 */ +void _glp_mpl_init_rand(glp_tran *tran, int seed) +{ if (tran->phase != 0) + xerror("glp_mpl_init_rand: invalid call sequence\n"); + rng_init_rand(tran->rand, seed); + return; +} +#endif + +int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip) +{ /* read and translate model section */ + int ret; + if (tran->phase != 0) + xerror("glp_mpl_read_model: invalid call sequence\n"); + ret = mpl_read_model(tran, (char *)fname, skip); + if (ret == 1 || ret == 2) + ret = 0; + else if (ret == 4) + ret = 1; + else + xassert(ret != ret); + return ret; +} + +int glp_mpl_read_data(glp_tran *tran, const char *fname) +{ /* read and translate data section */ + int ret; + if (!(tran->phase == 1 || tran->phase == 2)) + xerror("glp_mpl_read_data: invalid call sequence\n"); + ret = mpl_read_data(tran, (char *)fname); + if (ret == 2) + ret = 0; + else if (ret == 4) + ret = 1; + else + xassert(ret != ret); + return ret; +} + +int glp_mpl_generate(glp_tran *tran, const char *fname) +{ /* generate the model */ + int ret; + if (!(tran->phase == 1 || tran->phase == 2)) + xerror("glp_mpl_generate: invalid call sequence\n"); + ret = mpl_generate(tran, (char *)fname); + if (ret == 3) + ret = 0; + else if (ret == 4) + ret = 1; + return ret; +} + +void glp_mpl_build_prob(glp_tran *tran, glp_prob *prob) +{ /* build LP/MIP problem instance from the model */ + int m, n, i, j, t, kind, type, len, *ind; + double lb, ub, *val; + if (tran->phase != 3) + xerror("glp_mpl_build_prob: invalid call sequence\n"); + /* erase the problem object */ + glp_erase_prob(prob); + /* set problem name */ + glp_set_prob_name(prob, mpl_get_prob_name(tran)); + /* build rows (constraints) */ + m = mpl_get_num_rows(tran); + if (m > 0) + glp_add_rows(prob, m); + for (i = 1; i <= m; i++) + { /* set row name */ + glp_set_row_name(prob, i, mpl_get_row_name(tran, i)); + /* set row bounds */ + type = mpl_get_row_bnds(tran, i, &lb, &ub); + switch (type) + { case MPL_FR: type = GLP_FR; break; + case MPL_LO: type = GLP_LO; break; + case MPL_UP: type = GLP_UP; break; + case MPL_DB: type = GLP_DB; break; + case MPL_FX: type = GLP_FX; break; + default: xassert(type != type); + } + if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb))) + { type = GLP_FX; + if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub; + } + glp_set_row_bnds(prob, i, type, lb, ub); + /* warn about non-zero constant term */ + if (mpl_get_row_c0(tran, i) != 0.0) + xprintf("glp_mpl_build_prob: row %s; constant term %.12g ig" + "nored\n", + mpl_get_row_name(tran, i), mpl_get_row_c0(tran, i)); + } + /* build columns (variables) */ + n = mpl_get_num_cols(tran); + if (n > 0) + glp_add_cols(prob, n); + for (j = 1; j <= n; j++) + { /* set column name */ + glp_set_col_name(prob, j, mpl_get_col_name(tran, j)); + /* set column kind */ + kind = mpl_get_col_kind(tran, j); + switch (kind) + { case MPL_NUM: + break; + case MPL_INT: + case MPL_BIN: + glp_set_col_kind(prob, j, GLP_IV); + break; + default: + xassert(kind != kind); + } + /* set column bounds */ + type = mpl_get_col_bnds(tran, j, &lb, &ub); + switch (type) + { case MPL_FR: type = GLP_FR; break; + case MPL_LO: type = GLP_LO; break; + case MPL_UP: type = GLP_UP; break; + case MPL_DB: type = GLP_DB; break; + case MPL_FX: type = GLP_FX; break; + default: xassert(type != type); + } + if (kind == MPL_BIN) + { if (type == GLP_FR || type == GLP_UP || lb < 0.0) lb = 0.0; + if (type == GLP_FR || type == GLP_LO || ub > 1.0) ub = 1.0; + type = GLP_DB; + } + if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb))) + { type = GLP_FX; + if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub; + } + glp_set_col_bnds(prob, j, type, lb, ub); + } + /* load the constraint matrix */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + for (i = 1; i <= m; i++) + { len = mpl_get_mat_row(tran, i, ind, val); + glp_set_mat_row(prob, i, len, ind, val); + } + /* build objective function (the first objective is used) */ + for (i = 1; i <= m; i++) + { kind = mpl_get_row_kind(tran, i); + if (kind == MPL_MIN || kind == MPL_MAX) + { /* set objective name */ + glp_set_obj_name(prob, mpl_get_row_name(tran, i)); + /* set optimization direction */ + glp_set_obj_dir(prob, kind == MPL_MIN ? GLP_MIN : GLP_MAX); + /* set constant term */ + glp_set_obj_coef(prob, 0, mpl_get_row_c0(tran, i)); + /* set objective coefficients */ + len = mpl_get_mat_row(tran, i, ind, val); + for (t = 1; t <= len; t++) + glp_set_obj_coef(prob, ind[t], val[t]); + break; + } + } + /* free working arrays */ + xfree(ind); + xfree(val); + return; +} + +int glp_mpl_postsolve(glp_tran *tran, glp_prob *prob, int sol) +{ /* postsolve the model */ + int i, j, m, n, stat, ret; + double prim, dual; + if (!(tran->phase == 3 && !tran->flag_p)) + xerror("glp_mpl_postsolve: invalid call sequence\n"); + if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP)) + xerror("glp_mpl_postsolve: sol = %d; invalid parameter\n", + sol); + m = mpl_get_num_rows(tran); + n = mpl_get_num_cols(tran); + if (!(m == glp_get_num_rows(prob) && + n == glp_get_num_cols(prob))) + xerror("glp_mpl_postsolve: wrong problem object\n"); + if (!mpl_has_solve_stmt(tran)) + { ret = 0; + goto done; + } + for (i = 1; i <= m; i++) + { if (sol == GLP_SOL) + { stat = glp_get_row_stat(prob, i); + prim = glp_get_row_prim(prob, i); + dual = glp_get_row_dual(prob, i); + } + else if (sol == GLP_IPT) + { stat = 0; + prim = glp_ipt_row_prim(prob, i); + dual = glp_ipt_row_dual(prob, i); + } + else if (sol == GLP_MIP) + { stat = 0; + prim = glp_mip_row_val(prob, i); + dual = 0.0; + } + else + xassert(sol != sol); + if (fabs(prim) < 1e-9) prim = 0.0; + if (fabs(dual) < 1e-9) dual = 0.0; + mpl_put_row_soln(tran, i, stat, prim, dual); + } + for (j = 1; j <= n; j++) + { if (sol == GLP_SOL) + { stat = glp_get_col_stat(prob, j); + prim = glp_get_col_prim(prob, j); + dual = glp_get_col_dual(prob, j); + } + else if (sol == GLP_IPT) + { stat = 0; + prim = glp_ipt_col_prim(prob, j); + dual = glp_ipt_col_dual(prob, j); + } + else if (sol == GLP_MIP) + { stat = 0; + prim = glp_mip_col_val(prob, j); + dual = 0.0; + } + else + xassert(sol != sol); + if (fabs(prim) < 1e-9) prim = 0.0; + if (fabs(dual) < 1e-9) dual = 0.0; + mpl_put_col_soln(tran, j, stat, prim, dual); + } + ret = mpl_postsolve(tran); + if (ret == 3) + ret = 0; + else if (ret == 4) + ret = 1; +done: return ret; +} + +void glp_mpl_free_wksp(glp_tran *tran) +{ /* free the MathProg translator workspace */ + mpl_terminate(tran); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi15.c b/resources/3rdparty/glpk-4.53/src/glpapi15.c new file mode 100644 index 000000000..ecc6c32d3 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi15.c @@ -0,0 +1,615 @@ +/* glpapi15.c (basic graph and network routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpsdf.h" +#include "prob.h" + +#define xfprintf glp_format + +/* CAUTION: DO NOT CHANGE THE LIMITS BELOW */ + +#define NV_MAX 100000000 /* = 100*10^6 */ +/* maximal number of vertices in the graph */ + +#define NA_MAX 500000000 /* = 500*10^6 */ +/* maximal number of arcs in the graph */ + +/*********************************************************************** +* NAME +* +* glp_create_graph - create graph +* +* SYNOPSIS +* +* glp_graph *glp_create_graph(int v_size, int a_size); +* +* DESCRIPTION +* +* The routine creates a new graph, which initially is empty, i.e. has +* no vertices and arcs. +* +* The parameter v_size specifies the size of data associated with each +* vertex of the graph (0 to 256 bytes). +* +* The parameter a_size specifies the size of data associated with each +* arc of the graph (0 to 256 bytes). +* +* RETURNS +* +* The routine returns a pointer to the graph created. */ + +static void create_graph(glp_graph *G, int v_size, int a_size) +{ G->pool = dmp_create_pool(); + G->name = NULL; + G->nv_max = 50; + G->nv = G->na = 0; + G->v = xcalloc(1+G->nv_max, sizeof(glp_vertex *)); + G->index = NULL; + G->v_size = v_size; + G->a_size = a_size; + return; +} + +glp_graph *glp_create_graph(int v_size, int a_size) +{ glp_graph *G; + if (!(0 <= v_size && v_size <= 256)) + xerror("glp_create_graph: v_size = %d; invalid size of vertex " + "data\n", v_size); + if (!(0 <= a_size && a_size <= 256)) + xerror("glp_create_graph: a_size = %d; invalid size of arc dat" + "a\n", a_size); + G = xmalloc(sizeof(glp_graph)); + create_graph(G, v_size, a_size); + return G; +} + +/*********************************************************************** +* NAME +* +* glp_set_graph_name - assign (change) graph name +* +* SYNOPSIS +* +* void glp_set_graph_name(glp_graph *G, const char *name); +* +* DESCRIPTION +* +* The routine glp_set_graph_name assigns a symbolic name specified by +* the character string name (1 to 255 chars) to the graph. +* +* If the parameter name is NULL or an empty string, the routine erases +* the existing symbolic name of the graph. */ + +void glp_set_graph_name(glp_graph *G, const char *name) +{ if (G->name != NULL) + { dmp_free_atom(G->pool, G->name, strlen(G->name)+1); + G->name = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int j; + for (j = 0; name[j] != '\0'; j++) + { if (j == 256) + xerror("glp_set_graph_name: graph name too long\n"); + if (iscntrl((unsigned char)name[j])) + xerror("glp_set_graph_name: graph name contains invalid " + "character(s)\n"); + } + G->name = dmp_get_atom(G->pool, strlen(name)+1); + strcpy(G->name, name); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_add_vertices - add new vertices to graph +* +* SYNOPSIS +* +* int glp_add_vertices(glp_graph *G, int nadd); +* +* DESCRIPTION +* +* The routine glp_add_vertices adds nadd vertices to the specified +* graph. New vertices are always added to the end of the vertex list, +* so ordinal numbers of existing vertices remain unchanged. +* +* Being added each new vertex is isolated (has no incident arcs). +* +* RETURNS +* +* The routine glp_add_vertices returns an ordinal number of the first +* new vertex added to the graph. */ + +int glp_add_vertices(glp_graph *G, int nadd) +{ int i, nv_new; + if (nadd < 1) + xerror("glp_add_vertices: nadd = %d; invalid number of vertice" + "s\n", nadd); + if (nadd > NV_MAX - G->nv) + xerror("glp_add_vertices: nadd = %d; too many vertices\n", + nadd); + /* determine new number of vertices */ + nv_new = G->nv + nadd; + /* increase the room, if necessary */ + if (G->nv_max < nv_new) + { glp_vertex **save = G->v; + while (G->nv_max < nv_new) + { G->nv_max += G->nv_max; + xassert(G->nv_max > 0); + } + G->v = xcalloc(1+G->nv_max, sizeof(glp_vertex *)); + memcpy(&G->v[1], &save[1], G->nv * sizeof(glp_vertex *)); + xfree(save); + } + /* add new vertices to the end of the vertex list */ + for (i = G->nv+1; i <= nv_new; i++) + { glp_vertex *v; + G->v[i] = v = dmp_get_atom(G->pool, sizeof(glp_vertex)); + v->i = i; + v->name = NULL; + v->entry = NULL; + if (G->v_size == 0) + v->data = NULL; + else + { v->data = dmp_get_atom(G->pool, G->v_size); + memset(v->data, 0, G->v_size); + } + v->temp = NULL; + v->in = v->out = NULL; + } + /* set new number of vertices */ + G->nv = nv_new; + /* return the ordinal number of the first vertex added */ + return nv_new - nadd + 1; +} + +/**********************************************************************/ + +void glp_set_vertex_name(glp_graph *G, int i, const char *name) +{ /* assign (change) vertex name */ + glp_vertex *v; + if (!(1 <= i && i <= G->nv)) + xerror("glp_set_vertex_name: i = %d; vertex number out of rang" + "e\n", i); + v = G->v[i]; + if (v->name != NULL) + { if (v->entry != NULL) + { xassert(G->index != NULL); + avl_delete_node(G->index, v->entry); + v->entry = NULL; + } + dmp_free_atom(G->pool, v->name, strlen(v->name)+1); + v->name = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int k; + for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_set_vertex_name: i = %d; vertex name too lon" + "g\n", i); + if (iscntrl((unsigned char)name[k])) + xerror("glp_set_vertex_name: i = %d; vertex name contain" + "s invalid character(s)\n", i); + } + v->name = dmp_get_atom(G->pool, strlen(name)+1); + strcpy(v->name, name); + if (G->index != NULL) + { xassert(v->entry == NULL); + v->entry = avl_insert_node(G->index, v->name); + avl_set_node_link(v->entry, v); + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_add_arc - add new arc to graph +* +* SYNOPSIS +* +* glp_arc *glp_add_arc(glp_graph *G, int i, int j); +* +* DESCRIPTION +* +* The routine glp_add_arc adds a new arc to the specified graph. +* +* The parameters i and j specify the ordinal numbers of, resp., tail +* and head vertices of the arc. Note that self-loops and multiple arcs +* are allowed. +* +* RETURNS +* +* The routine glp_add_arc returns a pointer to the arc added. */ + +glp_arc *glp_add_arc(glp_graph *G, int i, int j) +{ glp_arc *a; + if (!(1 <= i && i <= G->nv)) + xerror("glp_add_arc: i = %d; tail vertex number out of range\n" + , i); + if (!(1 <= j && j <= G->nv)) + xerror("glp_add_arc: j = %d; head vertex number out of range\n" + , j); + if (G->na == NA_MAX) + xerror("glp_add_arc: too many arcs\n"); + a = dmp_get_atom(G->pool, sizeof(glp_arc)); + a->tail = G->v[i]; + a->head = G->v[j]; + if (G->a_size == 0) + a->data = NULL; + else + { a->data = dmp_get_atom(G->pool, G->a_size); + memset(a->data, 0, G->a_size); + } + a->temp = NULL; + a->t_prev = NULL; + a->t_next = G->v[i]->out; + if (a->t_next != NULL) a->t_next->t_prev = a; + a->h_prev = NULL; + a->h_next = G->v[j]->in; + if (a->h_next != NULL) a->h_next->h_prev = a; + G->v[i]->out = G->v[j]->in = a; + G->na++; + return a; +} + +/*********************************************************************** +* NAME +* +* glp_del_vertices - delete vertices from graph +* +* SYNOPSIS +* +* void glp_del_vertices(glp_graph *G, int ndel, const int num[]); +* +* DESCRIPTION +* +* The routine glp_del_vertices deletes vertices along with all +* incident arcs from the specified graph. Ordinal numbers of vertices +* to be deleted should be placed in locations num[1], ..., num[ndel], +* ndel > 0. +* +* Note that deleting vertices involves changing ordinal numbers of +* other vertices remaining in the graph. New ordinal numbers of the +* remaining vertices are assigned under the assumption that the +* original order of vertices is not changed. */ + +void glp_del_vertices(glp_graph *G, int ndel, const int num[]) +{ glp_vertex *v; + int i, k, nv_new; + /* scan the list of vertices to be deleted */ + if (!(1 <= ndel && ndel <= G->nv)) + xerror("glp_del_vertices: ndel = %d; invalid number of vertice" + "s\n", ndel); + for (k = 1; k <= ndel; k++) + { /* take the number of vertex to be deleted */ + i = num[k]; + /* obtain pointer to i-th vertex */ + if (!(1 <= i && i <= G->nv)) + xerror("glp_del_vertices: num[%d] = %d; vertex number out o" + "f range\n", k, i); + v = G->v[i]; + /* check that the vertex is not marked yet */ + if (v->i == 0) + xerror("glp_del_vertices: num[%d] = %d; duplicate vertex nu" + "mbers not allowed\n", k, i); + /* erase symbolic name assigned to the vertex */ + glp_set_vertex_name(G, i, NULL); + xassert(v->name == NULL); + xassert(v->entry == NULL); + /* free vertex data, if allocated */ + if (v->data != NULL) + dmp_free_atom(G->pool, v->data, G->v_size); + /* delete all incoming arcs */ + while (v->in != NULL) + glp_del_arc(G, v->in); + /* delete all outgoing arcs */ + while (v->out != NULL) + glp_del_arc(G, v->out); + /* mark the vertex to be deleted */ + v->i = 0; + } + /* delete all marked vertices from the vertex list */ + nv_new = 0; + for (i = 1; i <= G->nv; i++) + { /* obtain pointer to i-th vertex */ + v = G->v[i]; + /* check if the vertex is marked */ + if (v->i == 0) + { /* it is marked, delete it */ + dmp_free_atom(G->pool, v, sizeof(glp_vertex)); + } + else + { /* it is not marked, keep it */ + v->i = ++nv_new; + G->v[v->i] = v; + } + } + /* set new number of vertices in the graph */ + G->nv = nv_new; + return; +} + +/*********************************************************************** +* NAME +* +* glp_del_arc - delete arc from graph +* +* SYNOPSIS +* +* void glp_del_arc(glp_graph *G, glp_arc *a); +* +* DESCRIPTION +* +* The routine glp_del_arc deletes an arc from the specified graph. +* The arc to be deleted must exist. */ + +void glp_del_arc(glp_graph *G, glp_arc *a) +{ /* some sanity checks */ + xassert(G->na > 0); + xassert(1 <= a->tail->i && a->tail->i <= G->nv); + xassert(a->tail == G->v[a->tail->i]); + xassert(1 <= a->head->i && a->head->i <= G->nv); + xassert(a->head == G->v[a->head->i]); + /* remove the arc from the list of incoming arcs */ + if (a->h_prev == NULL) + a->head->in = a->h_next; + else + a->h_prev->h_next = a->h_next; + if (a->h_next == NULL) + ; + else + a->h_next->h_prev = a->h_prev; + /* remove the arc from the list of outgoing arcs */ + if (a->t_prev == NULL) + a->tail->out = a->t_next; + else + a->t_prev->t_next = a->t_next; + if (a->t_next == NULL) + ; + else + a->t_next->t_prev = a->t_prev; + /* free arc data, if allocated */ + if (a->data != NULL) + dmp_free_atom(G->pool, a->data, G->a_size); + /* delete the arc from the graph */ + dmp_free_atom(G->pool, a, sizeof(glp_arc)); + G->na--; + return; +} + +/*********************************************************************** +* NAME +* +* glp_erase_graph - erase graph content +* +* SYNOPSIS +* +* void glp_erase_graph(glp_graph *G, int v_size, int a_size); +* +* DESCRIPTION +* +* The routine glp_erase_graph erases the content of the specified +* graph. The effect of this operation is the same as if the graph +* would be deleted with the routine glp_delete_graph and then created +* anew with the routine glp_create_graph, with exception that the +* handle (pointer) to the graph remains valid. */ + +static void delete_graph(glp_graph *G) +{ dmp_delete_pool(G->pool); + xfree(G->v); + if (G->index != NULL) avl_delete_tree(G->index); + return; +} + +void glp_erase_graph(glp_graph *G, int v_size, int a_size) +{ if (!(0 <= v_size && v_size <= 256)) + xerror("glp_erase_graph: v_size = %d; invalid size of vertex d" + "ata\n", v_size); + if (!(0 <= a_size && a_size <= 256)) + xerror("glp_erase_graph: a_size = %d; invalid size of arc data" + "\n", a_size); + delete_graph(G); + create_graph(G, v_size, a_size); + return; +} + +/*********************************************************************** +* NAME +* +* glp_delete_graph - delete graph +* +* SYNOPSIS +* +* void glp_delete_graph(glp_graph *G); +* +* DESCRIPTION +* +* The routine glp_delete_graph deletes the specified graph and frees +* all the memory allocated to this program object. */ + +void glp_delete_graph(glp_graph *G) +{ delete_graph(G); + xfree(G); + return; +} + +/**********************************************************************/ + +void glp_create_v_index(glp_graph *G) +{ /* create vertex name index */ + glp_vertex *v; + int i; + if (G->index == NULL) + { G->index = avl_create_tree(avl_strcmp, NULL); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + xassert(v->entry == NULL); + if (v->name != NULL) + { v->entry = avl_insert_node(G->index, v->name); + avl_set_node_link(v->entry, v); + } + } + } + return; +} + +int glp_find_vertex(glp_graph *G, const char *name) +{ /* find vertex by its name */ + AVLNODE *node; + int i = 0; + if (G->index == NULL) + xerror("glp_find_vertex: vertex name index does not exist\n"); + if (!(name == NULL || name[0] == '\0' || strlen(name) > 255)) + { node = avl_find_node(G->index, name); + if (node != NULL) + i = ((glp_vertex *)avl_get_node_link(node))->i; + } + return i; +} + +void glp_delete_v_index(glp_graph *G) +{ /* delete vertex name index */ + int i; + if (G->index != NULL) + { avl_delete_tree(G->index), G->index = NULL; + for (i = 1; i <= G->nv; i++) G->v[i]->entry = NULL; + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_read_graph - read graph from plain text file +* +* SYNOPSIS +* +* int glp_read_graph(glp_graph *G, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_graph reads a graph from a plain text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_graph(glp_graph *G, const char *fname) +{ glp_data *data; + jmp_buf jump; + int nv, na, i, j, k, ret; + glp_erase_graph(G, G->v_size, G->a_size); + xprintf("Reading graph from `%s'...\n", fname); + data = glp_sdf_open_file(fname); + if (data == NULL) + { ret = 1; + goto done; + } + if (setjmp(jump)) + { ret = 1; + goto done; + } + glp_sdf_set_jump(data, jump); + nv = glp_sdf_read_int(data); + if (nv < 0) + glp_sdf_error(data, "invalid number of vertices\n"); + na = glp_sdf_read_int(data); + if (na < 0) + glp_sdf_error(data, "invalid number of arcs\n"); + xprintf("Graph has %d vert%s and %d arc%s\n", + nv, nv == 1 ? "ex" : "ices", na, na == 1 ? "" : "s"); + if (nv > 0) glp_add_vertices(G, nv); + for (k = 1; k <= na; k++) + { i = glp_sdf_read_int(data); + if (!(1 <= i && i <= nv)) + glp_sdf_error(data, "tail vertex number out of range\n"); + j = glp_sdf_read_int(data); + if (!(1 <= j && j <= nv)) + glp_sdf_error(data, "head vertex number out of range\n"); + glp_add_arc(G, i, j); + } + xprintf("%d lines were read\n", glp_sdf_line(data)); + ret = 0; +done: if (data != NULL) glp_sdf_close_file(data); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_graph - write graph to plain text file +* +* SYNOPSIS +* +* int glp_write_graph(glp_graph *G, const char *fname). +* +* DESCRIPTION +* +* The routine glp_write_graph writes the specified graph to a plain +* text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_graph(glp_graph *G, const char *fname) +{ glp_file *fp; + glp_vertex *v; + glp_arc *a; + int i, count, ret; + xprintf("Writing graph to `%s'...\n", fname); + fp = glp_open(fname, "w"), count = 0; + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "%d %d\n", G->nv, G->na), count++; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + xfprintf(fp, "%d %d\n", a->tail->i, a->head->i), count++; + } +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi16.c b/resources/3rdparty/glpk-4.53/src/glpapi16.c new file mode 100644 index 000000000..9af86e2bd --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi16.c @@ -0,0 +1,330 @@ +/* glpapi16.c (graph and network analysis routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "mc13d.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_weak_comp - find all weakly connected components of graph +* +* SYNOPSIS +* +* int glp_weak_comp(glp_graph *G, int v_num); +* +* DESCRIPTION +* +* The routine glp_weak_comp finds all weakly connected components of +* the specified graph. +* +* The parameter v_num specifies an offset of the field of type int +* in the vertex data block, to which the routine stores the number of +* a (weakly) connected component containing that vertex. If v_num < 0, +* no component numbers are stored. +* +* The components are numbered in arbitrary order from 1 to nc, where +* nc is the total number of components found, 0 <= nc <= |V|. +* +* RETURNS +* +* The routine returns nc, the total number of components found. */ + +int glp_weak_comp(glp_graph *G, int v_num) +{ glp_vertex *v; + glp_arc *a; + int f, i, j, nc, nv, pos1, pos2, *prev, *next, *list; + if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int)) + xerror("glp_weak_comp: v_num = %d; invalid offset\n", v_num); + nv = G->nv; + if (nv == 0) + { nc = 0; + goto done; + } + /* allocate working arrays */ + prev = xcalloc(1+nv, sizeof(int)); + next = xcalloc(1+nv, sizeof(int)); + list = xcalloc(1+nv, sizeof(int)); + /* if vertex i is unlabelled, prev[i] is the index of previous + unlabelled vertex, and next[i] is the index of next unlabelled + vertex; if vertex i is labelled, then prev[i] < 0, and next[i] + is the connected component number */ + /* initially all vertices are unlabelled */ + f = 1; + for (i = 1; i <= nv; i++) + prev[i] = i - 1, next[i] = i + 1; + next[nv] = 0; + /* main loop (until all vertices have been labelled) */ + nc = 0; + while (f != 0) + { /* take an unlabelled vertex */ + i = f; + /* and remove it from the list of unlabelled vertices */ + f = next[i]; + if (f != 0) prev[f] = 0; + /* label the vertex; it begins a new component */ + prev[i] = -1, next[i] = ++nc; + /* breadth first search */ + list[1] = i, pos1 = pos2 = 1; + while (pos1 <= pos2) + { /* dequeue vertex i */ + i = list[pos1++]; + /* consider all arcs incoming to vertex i */ + for (a = G->v[i]->in; a != NULL; a = a->h_next) + { /* vertex j is adjacent to vertex i */ + j = a->tail->i; + if (prev[j] >= 0) + { /* vertex j is unlabelled */ + /* remove it from the list of unlabelled vertices */ + if (prev[j] == 0) + f = next[j]; + else + next[prev[j]] = next[j]; + if (next[j] == 0) + ; + else + prev[next[j]] = prev[j]; + /* label the vertex */ + prev[j] = -1, next[j] = nc; + /* and enqueue it for further consideration */ + list[++pos2] = j; + } + } + /* consider all arcs outgoing from vertex i */ + for (a = G->v[i]->out; a != NULL; a = a->t_next) + { /* vertex j is adjacent to vertex i */ + j = a->head->i; + if (prev[j] >= 0) + { /* vertex j is unlabelled */ + /* remove it from the list of unlabelled vertices */ + if (prev[j] == 0) + f = next[j]; + else + next[prev[j]] = next[j]; + if (next[j] == 0) + ; + else + prev[next[j]] = prev[j]; + /* label the vertex */ + prev[j] = -1, next[j] = nc; + /* and enqueue it for further consideration */ + list[++pos2] = j; + } + } + } + } + /* store component numbers */ + if (v_num >= 0) + { for (i = 1; i <= nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_num, &next[i], sizeof(int)); + } + } + /* free working arrays */ + xfree(prev); + xfree(next); + xfree(list); +done: return nc; +} + +/*********************************************************************** +* NAME +* +* glp_strong_comp - find all strongly connected components of graph +* +* SYNOPSIS +* +* int glp_strong_comp(glp_graph *G, int v_num); +* +* DESCRIPTION +* +* The routine glp_strong_comp finds all strongly connected components +* of the specified graph. +* +* The parameter v_num specifies an offset of the field of type int +* in the vertex data block, to which the routine stores the number of +* a strongly connected component containing that vertex. If v_num < 0, +* no component numbers are stored. +* +* The components are numbered in arbitrary order from 1 to nc, where +* nc is the total number of components found, 0 <= nc <= |V|. However, +* the component numbering has the property that for every arc (i->j) +* in the graph the condition num(i) >= num(j) holds. +* +* RETURNS +* +* The routine returns nc, the total number of components found. */ + +int glp_strong_comp(glp_graph *G, int v_num) +{ glp_vertex *v; + glp_arc *a; + int i, k, last, n, na, nc, *icn, *ip, *lenr, *ior, *ib, *lowl, + *numb, *prev; + if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int)) + xerror("glp_strong_comp: v_num = %d; invalid offset\n", + v_num); + n = G->nv; + if (n == 0) + { nc = 0; + goto done; + } + na = G->na; + icn = xcalloc(1+na, sizeof(int)); + ip = xcalloc(1+n, sizeof(int)); + lenr = xcalloc(1+n, sizeof(int)); + ior = xcalloc(1+n, sizeof(int)); + ib = xcalloc(1+n, sizeof(int)); + lowl = xcalloc(1+n, sizeof(int)); + numb = xcalloc(1+n, sizeof(int)); + prev = xcalloc(1+n, sizeof(int)); + k = 1; + for (i = 1; i <= n; i++) + { v = G->v[i]; + ip[i] = k; + for (a = v->out; a != NULL; a = a->t_next) + icn[k++] = a->head->i; + lenr[i] = k - ip[i]; + } + xassert(na == k-1); + nc = mc13d(n, icn, ip, lenr, ior, ib, lowl, numb, prev); + if (v_num >= 0) + { xassert(ib[1] == 1); + for (k = 1; k <= nc; k++) + { last = (k < nc ? ib[k+1] : n+1); + xassert(ib[k] < last); + for (i = ib[k]; i < last; i++) + { v = G->v[ior[i]]; + memcpy((char *)v->data + v_num, &k, sizeof(int)); + } + } + } + xfree(icn); + xfree(ip); + xfree(lenr); + xfree(ior); + xfree(ib); + xfree(lowl); + xfree(numb); + xfree(prev); +done: return nc; +} + +/*********************************************************************** +* NAME +* +* glp_top_sort - topological sorting of acyclic digraph +* +* SYNOPSIS +* +* int glp_top_sort(glp_graph *G, int v_num); +* +* DESCRIPTION +* +* The routine glp_top_sort performs topological sorting of vertices of +* the specified acyclic digraph. +* +* The parameter v_num specifies an offset of the field of type int in +* the vertex data block, to which the routine stores the vertex number +* assigned. If v_num < 0, vertex numbers are not stored. +* +* The vertices are numbered from 1 to n, where n is the total number +* of vertices in the graph. The vertex numbering has the property that +* for every arc (i->j) in the graph the condition num(i) < num(j) +* holds. Special case num(i) = 0 means that vertex i is not assigned a +* number, because the graph is *not* acyclic. +* +* RETURNS +* +* If the graph is acyclic and therefore all the vertices have been +* assigned numbers, the routine glp_top_sort returns zero. Otherwise, +* if the graph is not acyclic, the routine returns the number of +* vertices which have not been numbered, i.e. for which num(i) = 0. */ + +static int top_sort(glp_graph *G, int num[]) +{ glp_arc *a; + int i, j, cnt, top, *stack, *indeg; + /* allocate working arrays */ + indeg = xcalloc(1+G->nv, sizeof(int)); + stack = xcalloc(1+G->nv, sizeof(int)); + /* determine initial indegree of each vertex; push into the stack + the vertices having zero indegree */ + top = 0; + for (i = 1; i <= G->nv; i++) + { num[i] = indeg[i] = 0; + for (a = G->v[i]->in; a != NULL; a = a->h_next) + indeg[i]++; + if (indeg[i] == 0) + stack[++top] = i; + } + /* assign numbers to vertices in the sorted order */ + cnt = 0; + while (top > 0) + { /* pull vertex i from the stack */ + i = stack[top--]; + /* it has zero indegree in the current graph */ + xassert(indeg[i] == 0); + /* so assign it a next number */ + xassert(num[i] == 0); + num[i] = ++cnt; + /* remove vertex i from the current graph, update indegree of + its adjacent vertices, and push into the stack new vertices + whose indegree becomes zero */ + for (a = G->v[i]->out; a != NULL; a = a->t_next) + { j = a->head->i; + /* there exists arc (i->j) in the graph */ + xassert(indeg[j] > 0); + indeg[j]--; + if (indeg[j] == 0) + stack[++top] = j; + } + } + /* free working arrays */ + xfree(indeg); + xfree(stack); + return G->nv - cnt; +} + +int glp_top_sort(glp_graph *G, int v_num) +{ glp_vertex *v; + int i, cnt, *num; + if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int)) + xerror("glp_top_sort: v_num = %d; invalid offset\n", v_num); + if (G->nv == 0) + { cnt = 0; + goto done; + } + num = xcalloc(1+G->nv, sizeof(int)); + cnt = top_sort(G, num); + if (v_num >= 0) + { for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_num, &num[i], sizeof(int)); + } + } + xfree(num); +done: return cnt; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi17.c b/resources/3rdparty/glpk-4.53/src/glpapi17.c new file mode 100644 index 000000000..425c6a5a8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi17.c @@ -0,0 +1,1269 @@ +/* glpapi17.c (flow network problems) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "ffalg.h" +#include "mc21a.h" +#include "okalg.h" +#include "prob.h" +#include "relax4.h" + +/*********************************************************************** +* NAME +* +* glp_mincost_lp - convert minimum cost flow problem to LP +* +* SYNOPSIS +* +* void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names, +* int v_rhs, int a_low, int a_cap, int a_cost); +* +* DESCRIPTION +* +* The routine glp_mincost_lp builds an LP problem, which corresponds +* to the minimum cost flow problem on the specified network G. */ + +void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names, int v_rhs, + int a_low, int a_cap, int a_cost) +{ glp_vertex *v; + glp_arc *a; + int i, j, type, ind[1+2]; + double rhs, low, cap, cost, val[1+2]; + if (!(names == GLP_ON || names == GLP_OFF)) + xerror("glp_mincost_lp: names = %d; invalid parameter\n", + names); + if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_mincost_lp: v_rhs = %d; invalid offset\n", v_rhs); + if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_lp: a_low = %d; invalid offset\n", a_low); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_lp: a_cap = %d; invalid offset\n", a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_lp: a_cost = %d; invalid offset\n", a_cost) + ; + glp_erase_prob(lp); + if (names) glp_set_prob_name(lp, G->name); + if (G->nv > 0) glp_add_rows(lp, G->nv); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (names) glp_set_row_name(lp, i, v->name); + if (v_rhs >= 0) + memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double)); + else + rhs = 0.0; + glp_set_row_bnds(lp, i, GLP_FX, rhs, rhs); + } + if (G->na > 0) glp_add_cols(lp, G->na); + for (i = 1, j = 0; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { j++; + if (names) + { char name[50+1]; + sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); + xassert(strlen(name) < sizeof(name)); + glp_set_col_name(lp, j, name); + } + if (a->tail->i != a->head->i) + { ind[1] = a->tail->i, val[1] = +1.0; + ind[2] = a->head->i, val[2] = -1.0; + glp_set_mat_col(lp, j, 2, ind, val); + } + if (a_low >= 0) + memcpy(&low, (char *)a->data + a_low, sizeof(double)); + else + low = 0.0; + if (a_cap >= 0) + memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); + else + cap = 1.0; + if (cap == DBL_MAX) + type = GLP_LO; + else if (low != cap) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp, j, type, low, cap); + if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 0.0; + glp_set_obj_coef(lp, j, cost); + } + } + xassert(j == G->na); + return; +} + +/**********************************************************************/ + +int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, double *sol, int a_x, int v_pi) +{ /* find minimum-cost flow with out-of-kilter algorithm */ + glp_vertex *v; + glp_arc *a; + int nv, na, i, k, s, t, *tail, *head, *low, *cap, *cost, *x, *pi, + ret; + double sum, temp; + if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: v_rhs = %d; invalid offset\n", + v_rhs); + if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: a_low = %d; invalid offset\n", + a_low); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: a_cap = %d; invalid offset\n", + a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: a_cost = %d; invalid offset\n", + a_cost); + if (a_x >= 0 && a_x > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: a_x = %d; invalid offset\n", a_x); + if (v_pi >= 0 && v_pi > G->v_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: v_pi = %d; invalid offset\n", v_pi); + /* s is artificial source node */ + s = G->nv + 1; + /* t is artificial sink node */ + t = s + 1; + /* nv is the total number of nodes in the resulting network */ + nv = t; + /* na is the total number of arcs in the resulting network */ + na = G->na + 1; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (v_rhs >= 0) + memcpy(&temp, (char *)v->data + v_rhs, sizeof(double)); + else + temp = 0.0; + if (temp != 0.0) na++; + } + /* allocate working arrays */ + tail = xcalloc(1+na, sizeof(int)); + head = xcalloc(1+na, sizeof(int)); + low = xcalloc(1+na, sizeof(int)); + cap = xcalloc(1+na, sizeof(int)); + cost = xcalloc(1+na, sizeof(int)); + x = xcalloc(1+na, sizeof(int)); + pi = xcalloc(1+nv, sizeof(int)); + /* construct the resulting network */ + k = 0; + /* (original arcs) */ + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + tail[k] = a->tail->i; + head[k] = a->head->i; + if (tail[k] == head[k]) + { ret = GLP_EDATA; + goto done; + } + if (a_low >= 0) + memcpy(&temp, (char *)a->data + a_low, sizeof(double)); + else + temp = 0.0; + if (!(0.0 <= temp && temp <= (double)INT_MAX && + temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + low[k] = (int)temp; + if (a_cap >= 0) + memcpy(&temp, (char *)a->data + a_cap, sizeof(double)); + else + temp = 1.0; + if (!((double)low[k] <= temp && temp <= (double)INT_MAX && + temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + cap[k] = (int)temp; + if (a_cost >= 0) + memcpy(&temp, (char *)a->data + a_cost, sizeof(double)); + else + temp = 0.0; + if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + cost[k] = (int)temp; + } + } + /* (artificial arcs) */ + sum = 0.0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (v_rhs >= 0) + memcpy(&temp, (char *)v->data + v_rhs, sizeof(double)); + else + temp = 0.0; + if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + if (temp > 0.0) + { /* artificial arc from s to original source i */ + k++; + tail[k] = s; + head[k] = i; + low[k] = cap[k] = (int)(+temp); /* supply */ + cost[k] = 0; + sum += (double)temp; + } + else if (temp < 0.0) + { /* artificial arc from original sink i to t */ + k++; + tail[k] = i; + head[k] = t; + low[k] = cap[k] = (int)(-temp); /* demand */ + cost[k] = 0; + } + } + /* (feedback arc from t to s) */ + k++; + xassert(k == na); + tail[k] = t; + head[k] = s; + if (sum > (double)INT_MAX) + { ret = GLP_EDATA; + goto done; + } + low[k] = cap[k] = (int)sum; /* total supply/demand */ + cost[k] = 0; + /* find minimal-cost circulation in the resulting network */ + ret = okalg(nv, na, tail, head, low, cap, cost, x, pi); + switch (ret) + { case 0: + /* optimal circulation found */ + ret = 0; + break; + case 1: + /* no feasible circulation exists */ + ret = GLP_ENOPFS; + break; + case 2: + /* integer overflow occured */ + ret = GLP_ERANGE; + goto done; + case 3: + /* optimality test failed (logic error) */ + ret = GLP_EFAIL; + goto done; + default: + xassert(ret != ret); + } + /* store solution components */ + /* (objective function = the total cost) */ + if (sol != NULL) + { temp = 0.0; + for (k = 1; k <= na; k++) + temp += (double)cost[k] * (double)x[k]; + *sol = temp; + } + /* (arc flows) */ + if (a_x >= 0) + { k = 0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { temp = (double)x[++k]; + memcpy((char *)a->data + a_x, &temp, sizeof(double)); + } + } + } + /* (node potentials = Lagrange multipliers) */ + if (v_pi >= 0) + { for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + temp = - (double)pi[i]; + memcpy((char *)v->data + v_pi, &temp, sizeof(double)); + } + } +done: /* free working arrays */ + xfree(tail); + xfree(head); + xfree(low); + xfree(cap); + xfree(cost); + xfree(x); + xfree(pi); + return ret; +} + +/**********************************************************************/ + +static int overflow(int u, int v) +{ /* check for integer overflow on computing u + v */ + if (u > 0 && v > 0 && u + v < 0) return 1; + if (u < 0 && v < 0 && u + v > 0) return 1; + return 0; +} + +int glp_mincost_relax4(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, int crash, double *sol, int a_x, int a_rc) +{ /* find minimum-cost flow with Bertsekas-Tseng relaxation method + (RELAX-IV) */ + glp_vertex *v; + glp_arc *a; + struct relax4_csa csa; + int i, k, large, n, na, ret; + double cap, cost, low, rc, rhs, sum, x; + if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: v_rhs = %d; invalid offset\n", + v_rhs); + if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: a_low = %d; invalid offset\n", + a_low); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: a_cap = %d; invalid offset\n", + a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: a_cost = %d; invalid offset\n", + a_cost); + if (a_x >= 0 && a_x > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: a_x = %d; invalid offset\n", + a_x); + if (a_rc >= 0 && a_rc > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: a_rc = %d; invalid offset\n", + a_rc); + csa.n = n = G->nv; /* number of nodes */ + csa.na = na = G->na; /* number of arcs */ + csa.large = large = INT_MAX / 4; + csa.repeat = 0; + csa.crash = crash; + /* allocate working arrays */ + csa.startn = xcalloc(1+na, sizeof(int)); + csa.endn = xcalloc(1+na, sizeof(int)); + csa.fou = xcalloc(1+n, sizeof(int)); + csa.nxtou = xcalloc(1+na, sizeof(int)); + csa.fin = xcalloc(1+n, sizeof(int)); + csa.nxtin = xcalloc(1+na, sizeof(int)); + csa.rc = xcalloc(1+na, sizeof(int)); + csa.u = xcalloc(1+na, sizeof(int)); + csa.dfct = xcalloc(1+n, sizeof(int)); + csa.x = xcalloc(1+na, sizeof(int)); + csa.label = xcalloc(1+n, sizeof(int)); + csa.prdcsr = xcalloc(1+n, sizeof(int)); + csa.save = xcalloc(1+na, sizeof(int)); + csa.tfstou = xcalloc(1+n, sizeof(int)); + csa.tnxtou = xcalloc(1+na, sizeof(int)); + csa.tfstin = xcalloc(1+n, sizeof(int)); + csa.tnxtin = xcalloc(1+na, sizeof(int)); + csa.nxtqueue = xcalloc(1+n, sizeof(int)); + csa.scan = xcalloc(1+n, sizeof(char)); + csa.mark = xcalloc(1+n, sizeof(char)); + if (crash) + { csa.extend_arc = xcalloc(1+n, sizeof(int)); + csa.sb_level = xcalloc(1+n, sizeof(int)); + csa.sb_arc = xcalloc(1+n, sizeof(int)); + } + else + { csa.extend_arc = NULL; + csa.sb_level = NULL; + csa.sb_arc = NULL; + } + /* scan nodes */ + for (i = 1; i <= n; i++) + { v = G->v[i]; + /* get supply at i-th node */ + if (v_rhs >= 0) + memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double)); + else + rhs = 0.0; + if (!(fabs(rhs) <= (double)large && rhs == floor(rhs))) + { ret = GLP_EDATA; + goto done; + } + /* set demand at i-th node */ + csa.dfct[i] = -(int)rhs; + } + /* scan arcs */ + k = 0; + for (i = 1; i <= n; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + /* set endpoints of k-th arc */ + if (a->tail->i == a->head->i) + { /* self-loops not allowed */ + ret = GLP_EDATA; + goto done; + } + csa.startn[k] = a->tail->i; + csa.endn[k] = a->head->i; + /* set per-unit cost for k-th arc flow */ + if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 0.0; + if (!(fabs(cost) <= (double)large && cost == floor(cost))) + { ret = GLP_EDATA; + goto done; + } + csa.rc[k] = (int)cost; + /* get lower bound for k-th arc flow */ + if (a_low >= 0) + memcpy(&low, (char *)a->data + a_low, sizeof(double)); + else + low = 0.0; + if (!(0.0 <= low && low <= (double)large && + low == floor(low))) + { ret = GLP_EDATA; + goto done; + } + /* get upper bound for k-th arc flow */ + if (a_cap >= 0) + memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); + else + cap = 1.0; + if (!(low <= cap && cap <= (double)large && + cap == floor(cap))) + { ret = GLP_EDATA; + goto done; + } + /* substitute x = x' + low, where 0 <= x' <= cap - low */ + csa.u[k] = (int)(cap - low); + /* correct demands at endpoints of k-th arc */ + if (overflow(csa.dfct[a->tail->i], +low)) + { ret = GLP_ERANGE; + goto done; + } + csa.dfct[a->tail->i] += low; + if (overflow(csa.dfct[a->head->i], -low)) + { ret = GLP_ERANGE; + goto done; + } + csa.dfct[a->head->i] -= low; + } + } + /* construct linked list for network topology */ + relax4_inidat(&csa); + /* find minimum-cost flow */ + ret = relax4(&csa); + if (ret != 0) + { /* problem is found to be infeasible */ + xassert(1 <= ret && ret <= 8); + ret = GLP_ENOPFS; + goto done; + } + /* store solution */ + sum = 0.0; + k = 0; + for (i = 1; i <= n; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + /* get lower bound for k-th arc flow */ + if (a_low >= 0) + memcpy(&low, (char *)a->data + a_low, sizeof(double)); + else + low = 0.0; + /* store original flow x = x' + low thru k-th arc */ + x = (double)csa.x[k] + low; + if (a_x >= 0) + memcpy((char *)a->data + a_x, &x, sizeof(double)); + /* store reduced cost for k-th arc flow */ + rc = (double)csa.rc[k]; + if (a_rc >= 0) + memcpy((char *)a->data + a_rc, &rc, sizeof(double)); + /* get per-unit cost for k-th arc flow */ + if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 0.0; + /* compute the total cost */ + sum += cost * x; + } + } + /* store the total cost */ + if (sol != NULL) + *sol = sum; +done: /* free working arrays */ + xfree(csa.startn); + xfree(csa.endn); + xfree(csa.fou); + xfree(csa.nxtou); + xfree(csa.fin); + xfree(csa.nxtin); + xfree(csa.rc); + xfree(csa.u); + xfree(csa.dfct); + xfree(csa.x); + xfree(csa.label); + xfree(csa.prdcsr); + xfree(csa.save); + xfree(csa.tfstou); + xfree(csa.tnxtou); + xfree(csa.tfstin); + xfree(csa.tnxtin); + xfree(csa.nxtqueue); + xfree(csa.scan); + xfree(csa.mark); + if (crash) + { xfree(csa.extend_arc); + xfree(csa.sb_level); + xfree(csa.sb_arc); + } + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_maxflow_lp - convert maximum flow problem to LP +* +* SYNOPSIS +* +* void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s, +* int t, int a_cap); +* +* DESCRIPTION +* +* The routine glp_maxflow_lp builds an LP problem, which corresponds +* to the maximum flow problem on the specified network G. */ + +void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s, + int t, int a_cap) +{ glp_vertex *v; + glp_arc *a; + int i, j, type, ind[1+2]; + double cap, val[1+2]; + if (!(names == GLP_ON || names == GLP_OFF)) + xerror("glp_maxflow_lp: names = %d; invalid parameter\n", + names); + if (!(1 <= s && s <= G->nv)) + xerror("glp_maxflow_lp: s = %d; source node number out of rang" + "e\n", s); + if (!(1 <= t && t <= G->nv)) + xerror("glp_maxflow_lp: t = %d: sink node number out of range " + "\n", t); + if (s == t) + xerror("glp_maxflow_lp: s = t = %d; source and sink nodes must" + " be distinct\n", s); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_maxflow_lp: a_cap = %d; invalid offset\n", a_cap); + glp_erase_prob(lp); + if (names) glp_set_prob_name(lp, G->name); + glp_set_obj_dir(lp, GLP_MAX); + glp_add_rows(lp, G->nv); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (names) glp_set_row_name(lp, i, v->name); + if (i == s) + type = GLP_LO; + else if (i == t) + type = GLP_UP; + else + type = GLP_FX; + glp_set_row_bnds(lp, i, type, 0.0, 0.0); + } + if (G->na > 0) glp_add_cols(lp, G->na); + for (i = 1, j = 0; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { j++; + if (names) + { char name[50+1]; + sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); + xassert(strlen(name) < sizeof(name)); + glp_set_col_name(lp, j, name); + } + if (a->tail->i != a->head->i) + { ind[1] = a->tail->i, val[1] = +1.0; + ind[2] = a->head->i, val[2] = -1.0; + glp_set_mat_col(lp, j, 2, ind, val); + } + if (a_cap >= 0) + memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); + else + cap = 1.0; + if (cap == DBL_MAX) + type = GLP_LO; + else if (cap != 0.0) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp, j, type, 0.0, cap); + if (a->tail->i == s) + glp_set_obj_coef(lp, j, +1.0); + else if (a->head->i == s) + glp_set_obj_coef(lp, j, -1.0); + } + } + xassert(j == G->na); + return; +} + +int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap, + double *sol, int a_x, int v_cut) +{ /* find maximal flow with Ford-Fulkerson algorithm */ + glp_vertex *v; + glp_arc *a; + int nv, na, i, k, flag, *tail, *head, *cap, *x, ret; + char *cut; + double temp; + if (!(1 <= s && s <= G->nv)) + xerror("glp_maxflow_ffalg: s = %d; source node number out of r" + "ange\n", s); + if (!(1 <= t && t <= G->nv)) + xerror("glp_maxflow_ffalg: t = %d: sink node number out of ran" + "ge\n", t); + if (s == t) + xerror("glp_maxflow_ffalg: s = t = %d; source and sink nodes m" + "ust be distinct\n", s); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_maxflow_ffalg: a_cap = %d; invalid offset\n", + a_cap); + if (v_cut >= 0 && v_cut > G->v_size - (int)sizeof(int)) + xerror("glp_maxflow_ffalg: v_cut = %d; invalid offset\n", + v_cut); + /* allocate working arrays */ + nv = G->nv; + na = G->na; + tail = xcalloc(1+na, sizeof(int)); + head = xcalloc(1+na, sizeof(int)); + cap = xcalloc(1+na, sizeof(int)); + x = xcalloc(1+na, sizeof(int)); + if (v_cut < 0) + cut = NULL; + else + cut = xcalloc(1+nv, sizeof(char)); + /* copy the flow network */ + k = 0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + tail[k] = a->tail->i; + head[k] = a->head->i; + if (tail[k] == head[k]) + { ret = GLP_EDATA; + goto done; + } + if (a_cap >= 0) + memcpy(&temp, (char *)a->data + a_cap, sizeof(double)); + else + temp = 1.0; + if (!(0.0 <= temp && temp <= (double)INT_MAX && + temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + cap[k] = (int)temp; + } + } + xassert(k == na); + /* find maximal flow in the flow network */ + ffalg(nv, na, tail, head, s, t, cap, x, cut); + ret = 0; + /* store solution components */ + /* (objective function = total flow through the network) */ + if (sol != NULL) + { temp = 0.0; + for (k = 1; k <= na; k++) + { if (tail[k] == s) + temp += (double)x[k]; + else if (head[k] == s) + temp -= (double)x[k]; + } + *sol = temp; + } + /* (arc flows) */ + if (a_x >= 0) + { k = 0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { temp = (double)x[++k]; + memcpy((char *)a->data + a_x, &temp, sizeof(double)); + } + } + } + /* (node flags) */ + if (v_cut >= 0) + { for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + flag = cut[i]; + memcpy((char *)v->data + v_cut, &flag, sizeof(int)); + } + } +done: /* free working arrays */ + xfree(tail); + xfree(head); + xfree(cap); + xfree(x); + if (cut != NULL) xfree(cut); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_check_asnprob - check correctness of assignment problem data +* +* SYNOPSIS +* +* int glp_check_asnprob(glp_graph *G, int v_set); +* +* RETURNS +* +* If the specified assignment problem data are correct, the routine +* glp_check_asnprob returns zero, otherwise, non-zero. */ + +int glp_check_asnprob(glp_graph *G, int v_set) +{ glp_vertex *v; + int i, k, ret = 0; + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_check_asnprob: v_set = %d; invalid offset\n", + v_set); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (v_set >= 0) + { memcpy(&k, (char *)v->data + v_set, sizeof(int)); + if (k == 0) + { if (v->in != NULL) + { ret = 1; + break; + } + } + else if (k == 1) + { if (v->out != NULL) + { ret = 2; + break; + } + } + else + { ret = 3; + break; + } + } + else + { if (v->in != NULL && v->out != NULL) + { ret = 4; + break; + } + } + } + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_asnprob_lp - convert assignment problem to LP +* +* SYNOPSIS +* +* int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, +* int v_set, int a_cost); +* +* DESCRIPTION +* +* The routine glp_asnprob_lp builds an LP problem, which corresponds +* to the assignment problem on the specified graph G. +* +* RETURNS +* +* If the LP problem has been successfully built, the routine returns +* zero, otherwise, non-zero. */ + +int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, + int v_set, int a_cost) +{ glp_vertex *v; + glp_arc *a; + int i, j, ret, ind[1+2]; + double cost, val[1+2]; + if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX || + form == GLP_ASN_MMP)) + xerror("glp_asnprob_lp: form = %d; invalid parameter\n", + form); + if (!(names == GLP_ON || names == GLP_OFF)) + xerror("glp_asnprob_lp: names = %d; invalid parameter\n", + names); + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_asnprob_lp: v_set = %d; invalid offset\n", + v_set); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_asnprob_lp: a_cost = %d; invalid offset\n", + a_cost); + ret = glp_check_asnprob(G, v_set); + if (ret != 0) goto done; + glp_erase_prob(P); + if (names) glp_set_prob_name(P, G->name); + glp_set_obj_dir(P, form == GLP_ASN_MIN ? GLP_MIN : GLP_MAX); + if (G->nv > 0) glp_add_rows(P, G->nv); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (names) glp_set_row_name(P, i, v->name); + glp_set_row_bnds(P, i, form == GLP_ASN_MMP ? GLP_UP : GLP_FX, + 1.0, 1.0); + } + if (G->na > 0) glp_add_cols(P, G->na); + for (i = 1, j = 0; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { j++; + if (names) + { char name[50+1]; + sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); + xassert(strlen(name) < sizeof(name)); + glp_set_col_name(P, j, name); + } + ind[1] = a->tail->i, val[1] = +1.0; + ind[2] = a->head->i, val[2] = +1.0; + glp_set_mat_col(P, j, 2, ind, val); + glp_set_col_bnds(P, j, GLP_DB, 0.0, 1.0); + if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 1.0; + glp_set_obj_coef(P, j, cost); + } + } + xassert(j == G->na); +done: return ret; +} + +/**********************************************************************/ + +int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost, + double *sol, int a_x) +{ /* solve assignment problem with out-of-kilter algorithm */ + glp_vertex *v; + glp_arc *a; + int nv, na, i, k, *tail, *head, *low, *cap, *cost, *x, *pi, ret; + double temp; + if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX || + form == GLP_ASN_MMP)) + xerror("glp_asnprob_okalg: form = %d; invalid parameter\n", + form); + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_asnprob_okalg: v_set = %d; invalid offset\n", + v_set); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_asnprob_okalg: a_cost = %d; invalid offset\n", + a_cost); + if (a_x >= 0 && a_x > G->a_size - (int)sizeof(int)) + xerror("glp_asnprob_okalg: a_x = %d; invalid offset\n", a_x); + if (glp_check_asnprob(G, v_set)) + return GLP_EDATA; + /* nv is the total number of nodes in the resulting network */ + nv = G->nv + 1; + /* na is the total number of arcs in the resulting network */ + na = G->na + G->nv; + /* allocate working arrays */ + tail = xcalloc(1+na, sizeof(int)); + head = xcalloc(1+na, sizeof(int)); + low = xcalloc(1+na, sizeof(int)); + cap = xcalloc(1+na, sizeof(int)); + cost = xcalloc(1+na, sizeof(int)); + x = xcalloc(1+na, sizeof(int)); + pi = xcalloc(1+nv, sizeof(int)); + /* construct the resulting network */ + k = 0; + /* (original arcs) */ + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + tail[k] = a->tail->i; + head[k] = a->head->i; + low[k] = 0; + cap[k] = 1; + if (a_cost >= 0) + memcpy(&temp, (char *)a->data + a_cost, sizeof(double)); + else + temp = 1.0; + if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + cost[k] = (int)temp; + if (form != GLP_ASN_MIN) cost[k] = - cost[k]; + } + } + /* (artificial arcs) */ + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + k++; + if (v->out == NULL) + tail[k] = i, head[k] = nv; + else if (v->in == NULL) + tail[k] = nv, head[k] = i; + else + xassert(v != v); + low[k] = (form == GLP_ASN_MMP ? 0 : 1); + cap[k] = 1; + cost[k] = 0; + } + xassert(k == na); + /* find minimal-cost circulation in the resulting network */ + ret = okalg(nv, na, tail, head, low, cap, cost, x, pi); + switch (ret) + { case 0: + /* optimal circulation found */ + ret = 0; + break; + case 1: + /* no feasible circulation exists */ + ret = GLP_ENOPFS; + break; + case 2: + /* integer overflow occured */ + ret = GLP_ERANGE; + goto done; + case 3: + /* optimality test failed (logic error) */ + ret = GLP_EFAIL; + goto done; + default: + xassert(ret != ret); + } + /* store solution components */ + /* (objective function = the total cost) */ + if (sol != NULL) + { temp = 0.0; + for (k = 1; k <= na; k++) + temp += (double)cost[k] * (double)x[k]; + if (form != GLP_ASN_MIN) temp = - temp; + *sol = temp; + } + /* (arc flows) */ + if (a_x >= 0) + { k = 0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + if (ret == 0) + xassert(x[k] == 0 || x[k] == 1); + memcpy((char *)a->data + a_x, &x[k], sizeof(int)); + } + } + } +done: /* free working arrays */ + xfree(tail); + xfree(head); + xfree(low); + xfree(cap); + xfree(cost); + xfree(x); + xfree(pi); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_asnprob_hall - find bipartite matching of maximum cardinality +* +* SYNOPSIS +* +* int glp_asnprob_hall(glp_graph *G, int v_set, int a_x); +* +* DESCRIPTION +* +* The routine glp_asnprob_hall finds a matching of maximal cardinality +* in the specified bipartite graph G. It uses a version of the Fortran +* routine MC21A developed by I.S.Duff [1], which implements Hall's +* algorithm [2]. +* +* RETURNS +* +* The routine glp_asnprob_hall returns the cardinality of the matching +* found. However, if the specified graph is incorrect (as detected by +* the routine glp_check_asnprob), the routine returns negative value. +* +* REFERENCES +* +* 1. I.S.Duff, Algorithm 575: Permutations for zero-free diagonal, ACM +* Trans. on Math. Softw. 7 (1981), 387-390. +* +* 2. M.Hall, "An Algorithm for distinct representatives," Amer. Math. +* Monthly 63 (1956), 716-717. */ + +int glp_asnprob_hall(glp_graph *G, int v_set, int a_x) +{ glp_vertex *v; + glp_arc *a; + int card, i, k, loc, n, n1, n2, xij; + int *num, *icn, *ip, *lenr, *iperm, *pr, *arp, *cv, *out; + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_asnprob_hall: v_set = %d; invalid offset\n", + v_set); + if (a_x >= 0 && a_x > G->a_size - (int)sizeof(int)) + xerror("glp_asnprob_hall: a_x = %d; invalid offset\n", a_x); + if (glp_check_asnprob(G, v_set)) + return -1; + /* determine the number of vertices in sets R and S and renumber + vertices in S which correspond to columns of the matrix; skip + all isolated vertices */ + num = xcalloc(1+G->nv, sizeof(int)); + n1 = n2 = 0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (v->in == NULL && v->out != NULL) + n1++, num[i] = 0; /* vertex in R */ + else if (v->in != NULL && v->out == NULL) + n2++, num[i] = n2; /* vertex in S */ + else + { xassert(v->in == NULL && v->out == NULL); + num[i] = -1; /* isolated vertex */ + } + } + /* the matrix must be square, thus, if it has more columns than + rows, extra rows will be just empty, and vice versa */ + n = (n1 >= n2 ? n1 : n2); + /* allocate working arrays */ + icn = xcalloc(1+G->na, sizeof(int)); + ip = xcalloc(1+n, sizeof(int)); + lenr = xcalloc(1+n, sizeof(int)); + iperm = xcalloc(1+n, sizeof(int)); + pr = xcalloc(1+n, sizeof(int)); + arp = xcalloc(1+n, sizeof(int)); + cv = xcalloc(1+n, sizeof(int)); + out = xcalloc(1+n, sizeof(int)); + /* build the adjacency matrix of the bipartite graph in row-wise + format (rows are vertices in R, columns are vertices in S) */ + k = 0, loc = 1; + for (i = 1; i <= G->nv; i++) + { if (num[i] != 0) continue; + /* vertex i in R */ + ip[++k] = loc; + v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { xassert(num[a->head->i] != 0); + icn[loc++] = num[a->head->i]; + } + lenr[k] = loc - ip[k]; + } + xassert(loc-1 == G->na); + /* make all extra rows empty (all extra columns are empty due to + the row-wise format used) */ + for (k++; k <= n; k++) + ip[k] = loc, lenr[k] = 0; + /* find a row permutation that maximizes the number of non-zeros + on the main diagonal */ + card = mc21a(n, icn, ip, lenr, iperm, pr, arp, cv, out); +#if 1 /* 18/II-2010 */ + /* FIXED: if card = n, arp remains clobbered on exit */ + for (i = 1; i <= n; i++) + arp[i] = 0; + for (i = 1; i <= card; i++) + { k = iperm[i]; + xassert(1 <= k && k <= n); + xassert(arp[k] == 0); + arp[k] = i; + } +#endif + /* store solution, if necessary */ + if (a_x < 0) goto skip; + k = 0; + for (i = 1; i <= G->nv; i++) + { if (num[i] != 0) continue; + /* vertex i in R */ + k++; + v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { /* arp[k] is the number of matched column or zero */ + if (arp[k] == num[a->head->i]) + { xassert(arp[k] != 0); + xij = 1; + } + else + xij = 0; + memcpy((char *)a->data + a_x, &xij, sizeof(int)); + } + } +skip: /* free working arrays */ + xfree(num); + xfree(icn); + xfree(ip); + xfree(lenr); + xfree(iperm); + xfree(pr); + xfree(arp); + xfree(cv); + xfree(out); + return card; +} + +/*********************************************************************** +* NAME +* +* glp_cpp - solve critical path problem +* +* SYNOPSIS +* +* double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls); +* +* DESCRIPTION +* +* The routine glp_cpp solves the critical path problem represented in +* the form of the project network. +* +* The parameter G is a pointer to the graph object, which specifies +* the project network. This graph must be acyclic. Multiple arcs are +* allowed being considered as single arcs. +* +* The parameter v_t specifies an offset of the field of type double +* in the vertex data block, which contains time t[i] >= 0 needed to +* perform corresponding job j. If v_t < 0, it is assumed that t[i] = 1 +* for all jobs. +* +* The parameter v_es specifies an offset of the field of type double +* in the vertex data block, to which the routine stores earliest start +* time for corresponding job. If v_es < 0, this time is not stored. +* +* The parameter v_ls specifies an offset of the field of type double +* in the vertex data block, to which the routine stores latest start +* time for corresponding job. If v_ls < 0, this time is not stored. +* +* RETURNS +* +* The routine glp_cpp returns the minimal project duration, that is, +* minimal time needed to perform all jobs in the project. */ + +static void sorting(glp_graph *G, int list[]); + +double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls) +{ glp_vertex *v; + glp_arc *a; + int i, j, k, nv, *list; + double temp, total, *t, *es, *ls; + if (v_t >= 0 && v_t > G->v_size - (int)sizeof(double)) + xerror("glp_cpp: v_t = %d; invalid offset\n", v_t); + if (v_es >= 0 && v_es > G->v_size - (int)sizeof(double)) + xerror("glp_cpp: v_es = %d; invalid offset\n", v_es); + if (v_ls >= 0 && v_ls > G->v_size - (int)sizeof(double)) + xerror("glp_cpp: v_ls = %d; invalid offset\n", v_ls); + nv = G->nv; + if (nv == 0) + { total = 0.0; + goto done; + } + /* allocate working arrays */ + t = xcalloc(1+nv, sizeof(double)); + es = xcalloc(1+nv, sizeof(double)); + ls = xcalloc(1+nv, sizeof(double)); + list = xcalloc(1+nv, sizeof(int)); + /* retrieve job times */ + for (i = 1; i <= nv; i++) + { v = G->v[i]; + if (v_t >= 0) + { memcpy(&t[i], (char *)v->data + v_t, sizeof(double)); + if (t[i] < 0.0) + xerror("glp_cpp: t[%d] = %g; invalid time\n", i, t[i]); + } + else + t[i] = 1.0; + } + /* perform topological sorting to determine the list of nodes + (jobs) such that if list[k] = i and list[kk] = j and there + exists arc (i->j), then k < kk */ + sorting(G, list); + /* FORWARD PASS */ + /* determine earliest start times */ + for (k = 1; k <= nv; k++) + { j = list[k]; + es[j] = 0.0; + for (a = G->v[j]->in; a != NULL; a = a->h_next) + { i = a->tail->i; + /* there exists arc (i->j) in the project network */ + temp = es[i] + t[i]; + if (es[j] < temp) es[j] = temp; + } + } + /* determine the minimal project duration */ + total = 0.0; + for (i = 1; i <= nv; i++) + { temp = es[i] + t[i]; + if (total < temp) total = temp; + } + /* BACKWARD PASS */ + /* determine latest start times */ + for (k = nv; k >= 1; k--) + { i = list[k]; + ls[i] = total - t[i]; + for (a = G->v[i]->out; a != NULL; a = a->t_next) + { j = a->head->i; + /* there exists arc (i->j) in the project network */ + temp = ls[j] - t[i]; + if (ls[i] > temp) ls[i] = temp; + } + /* avoid possible round-off errors */ + if (ls[i] < es[i]) ls[i] = es[i]; + } + /* store results, if necessary */ + if (v_es >= 0) + { for (i = 1; i <= nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_es, &es[i], sizeof(double)); + } + } + if (v_ls >= 0) + { for (i = 1; i <= nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_ls, &ls[i], sizeof(double)); + } + } + /* free working arrays */ + xfree(t); + xfree(es); + xfree(ls); + xfree(list); +done: return total; +} + +static void sorting(glp_graph *G, int list[]) +{ /* perform topological sorting to determine the list of nodes + (jobs) such that if list[k] = i and list[kk] = j and there + exists arc (i->j), then k < kk */ + int i, k, nv, v_size, *num; + void **save; + nv = G->nv; + v_size = G->v_size; + save = xcalloc(1+nv, sizeof(void *)); + num = xcalloc(1+nv, sizeof(int)); + G->v_size = sizeof(int); + for (i = 1; i <= nv; i++) + { save[i] = G->v[i]->data; + G->v[i]->data = &num[i]; + list[i] = 0; + } + if (glp_top_sort(G, 0) != 0) + xerror("glp_cpp: project network is not acyclic\n"); + G->v_size = v_size; + for (i = 1; i <= nv; i++) + { G->v[i]->data = save[i]; + k = num[i]; + xassert(1 <= k && k <= nv); + xassert(list[k] == 0); + list[k] = i; + } + xfree(save); + xfree(num); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi18.c b/resources/3rdparty/glpk-4.53/src/glpapi18.c new file mode 100644 index 000000000..07ab490d5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi18.c @@ -0,0 +1,123 @@ +/* glpapi18.c (maximum clique problem) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "prob.h" +#include "wclique.h" + +static void set_edge(int nv, unsigned char a[], int i, int j) +{ int k; + xassert(1 <= j && j < i && i <= nv); + k = ((i - 1) * (i - 2)) / 2 + (j - 1); + a[k / CHAR_BIT] |= + (unsigned char)(1 << ((CHAR_BIT - 1) - k % CHAR_BIT)); + return; +} + +int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set) +{ /* find maximum weight clique with exact algorithm */ + glp_arc *e; + int i, j, k, len, x, *w, *ind, ret = 0; + unsigned char *a; + double s, t; + if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) + xerror("glp_wclique_exact: v_wgt = %d; invalid parameter\n", + v_wgt); + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_wclique_exact: v_set = %d; invalid parameter\n", + v_set); + if (G->nv == 0) + { /* empty graph has only empty clique */ + if (sol != NULL) *sol = 0.0; + return 0; + } + /* allocate working arrays */ + w = xcalloc(1+G->nv, sizeof(int)); + ind = xcalloc(1+G->nv, sizeof(int)); + len = G->nv; /* # vertices */ + len = len * (len - 1) / 2; /* # entries in lower triangle */ + len = (len + (CHAR_BIT - 1)) / CHAR_BIT; /* # bytes needed */ + a = xcalloc(len, sizeof(char)); + memset(a, 0, len * sizeof(char)); + /* determine vertex weights */ + s = 0.0; + for (i = 1; i <= G->nv; i++) + { if (v_wgt >= 0) + { memcpy(&t, (char *)G->v[i]->data + v_wgt, sizeof(double)); + if (!(0.0 <= t && t <= (double)INT_MAX && t == floor(t))) + { ret = GLP_EDATA; + goto done; + } + w[i] = (int)t; + } + else + w[i] = 1; + s += (double)w[i]; + } + if (s > (double)INT_MAX) + { ret = GLP_EDATA; + goto done; + } + /* build the adjacency matrix */ + for (i = 1; i <= G->nv; i++) + { for (e = G->v[i]->in; e != NULL; e = e->h_next) + { j = e->tail->i; + /* there exists edge (j,i) in the graph */ + if (i > j) set_edge(G->nv, a, i, j); + } + for (e = G->v[i]->out; e != NULL; e = e->t_next) + { j = e->head->i; + /* there exists edge (i,j) in the graph */ + if (i > j) set_edge(G->nv, a, i, j); + } + } + /* find maximum weight clique in the graph */ + len = wclique(G->nv, w, a, ind); + /* compute the clique weight */ + s = 0.0; + for (k = 1; k <= len; k++) + { i = ind[k]; + xassert(1 <= i && i <= G->nv); + s += (double)w[i]; + } + if (sol != NULL) *sol = s; + /* mark vertices included in the clique */ + if (v_set >= 0) + { x = 0; + for (i = 1; i <= G->nv; i++) + memcpy((char *)G->v[i]->data + v_set, &x, sizeof(int)); + x = 1; + for (k = 1; k <= len; k++) + { i = ind[k]; + memcpy((char *)G->v[i]->data + v_set, &x, sizeof(int)); + } + } +done: /* free working arrays */ + xfree(w); + xfree(ind); + xfree(a); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi19.c b/resources/3rdparty/glpk-4.53/src/glpapi19.c new file mode 100644 index 000000000..49fee3898 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi19.c @@ -0,0 +1,133 @@ +/* glpapi19.c (driver to MiniSat solver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "minisat.h" +#include "prob.h" + +int glp_minisat1(glp_prob *P) +{ /* solve CNF-SAT problem with MiniSat solver */ + solver *s; + GLPAIJ *aij; + int i, j, len, ret, *ind; + double sum; + /* check problem object */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_minisat1: P = %p; invalid problem object\n", + P); + if (P->tree != NULL) + xerror("glp_minisat1: operation not allowed\n"); + /* integer solution is currently undefined */ + P->mip_stat = GLP_UNDEF; + P->mip_obj = 0.0; + /* check that problem object encodes CNF-SAT instance */ + if (glp_check_cnfsat(P) != 0) + { xprintf("glp_minisat1: problem object does not encode CNF-SAT " + "instance\n"); + ret = GLP_EDATA; + goto done; + } + /* solve CNF-SAT problem */ + xprintf("Solving CNF-SAT problem...\n"); + xprintf("Instance has %d variable%s, %d clause%s, and %d literal%" + "s\n", P->n, P->n == 1 ? "" : "s", P->m, P->m == 1 ? "" : "s", + P->nnz, P->nnz == 1 ? "" : "s"); + /* if CNF-SAT has no clauses, it is satisfiable */ + if (P->m == 0) + { P->mip_stat = GLP_OPT; + for (j = 1; j <= P->n; j++) + P->col[j]->mipx = 0.0; + goto fini; + } + /* if CNF-SAT has an empty clause, it is unsatisfiable */ + for (i = 1; i <= P->m; i++) + { if (P->row[i]->ptr == NULL) + { P->mip_stat = GLP_NOFEAS; + goto fini; + } + } + /* prepare input data for the solver */ + s = solver_new(); + solver_setnvars(s, P->n); + ind = xcalloc(1+P->n, sizeof(int)); + for (i = 1; i <= P->m; i++) + { len = 0; + for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) + { ind[++len] = toLit(aij->col->j-1); + if (aij->val < 0.0) + ind[len] = lit_neg(ind[len]); + } + xassert(len > 0); + xassert(solver_addclause(s, &ind[1], &ind[1+len])); + } + xfree(ind); + /* call the solver */ + s->verbosity = 1; + if (solver_solve(s, 0, 0)) + { /* instance is reported as satisfiable */ + P->mip_stat = GLP_OPT; + /* copy solution to the problem object */ + xassert(s->model.size == P->n); + for (j = 1; j <= P->n; j++) + { P->col[j]->mipx = + s->model.ptr[j-1] == l_True ? 1.0 : 0.0; + } + /* compute row values */ + for (i = 1; i <= P->m; i++) + { sum = 0; + for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) + sum += aij->val * aij->col->mipx; + P->row[i]->mipx = sum; + } + /* check integer feasibility */ + for (i = 1; i <= P->m; i++) + { if (P->row[i]->mipx < P->row[i]->lb) + { /* solution is wrong */ + P->mip_stat = GLP_UNDEF; + break; + } + } + } + else + { /* instance is reported as unsatisfiable */ + P->mip_stat = GLP_NOFEAS; + } + solver_delete(s); +fini: /* report the instance status */ + if (P->mip_stat == GLP_OPT) + { xprintf("SATISFIABLE\n"); + ret = 0; + } + else if (P->mip_stat == GLP_NOFEAS) + { xprintf("UNSATISFIABLE\n"); + ret = 0; + } + else + { xprintf("glp_minisat1: solver failed\n"); + ret = GLP_EFAIL; + } +done: return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi20.c b/resources/3rdparty/glpk-4.53/src/glpapi20.c new file mode 100644 index 000000000..2a2f6f988 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi20.c @@ -0,0 +1,257 @@ +/* glpapi20.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpnpp.h" + +int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound) +{ /* solve integer feasibility problem */ + NPP *npp = NULL; + glp_prob *mip = NULL; + int *obj_ind = NULL; + double *obj_val = NULL; + int obj_row = 0; + int i, j, k, obj_len, temp, ret; + /* check the problem object */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_intfeas1: P = %p; invalid problem object\n", + P); + if (P->tree != NULL) + xerror("glp_intfeas1: operation not allowed\n"); + /* integer solution is currently undefined */ + P->mip_stat = GLP_UNDEF; + P->mip_obj = 0.0; + /* check columns (variables) */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; +#if 0 /* currently binarization is not yet implemented */ + if (!(col->kind == GLP_IV || col->type == GLP_FX)) + { xprintf("glp_intfeas1: column %d: non-integer non-fixed var" + "iable not allowed\n", j); +#else + if (!((col->kind == GLP_IV && col->lb == 0.0 && col->ub == 1.0) + || col->type == GLP_FX)) + { xprintf("glp_intfeas1: column %d: non-binary non-fixed vari" + "able not allowed\n", j); +#endif + ret = GLP_EDATA; + goto done; + } + temp = (int)col->lb; + if ((double)temp != col->lb) + { if (col->type == GLP_FX) + xprintf("glp_intfeas1: column %d: fixed value %g is non-" + "integer or out of range\n", j, col->lb); + else + xprintf("glp_intfeas1: column %d: lower bound %g is non-" + "integer or out of range\n", j, col->lb); + ret = GLP_EDATA; + goto done; + } + temp = (int)col->ub; + if ((double)temp != col->ub) + { xprintf("glp_intfeas1: column %d: upper bound %g is non-int" + "eger or out of range\n", j, col->ub); + ret = GLP_EDATA; + goto done; + } + if (col->type == GLP_DB && col->lb > col->ub) + { xprintf("glp_intfeas1: column %d: lower bound %g is greater" + " than upper bound %g\n", j, col->lb, col->ub); + ret = GLP_EBOUND; + goto done; + } + } + /* check rows (constraints) */ + for (i = 1; i <= P->m; i++) + { GLPROW *row = P->row[i]; + GLPAIJ *aij; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { temp = (int)aij->val; + if ((double)temp != aij->val) + { xprintf("glp_intfeas1: row = %d, column %d: constraint c" + "oefficient %g is non-integer or out of range\n", + i, aij->col->j, aij->val); + ret = GLP_EDATA; + goto done; + } + } + temp = (int)row->lb; + if ((double)temp != row->lb) + { if (row->type == GLP_FX) + xprintf("glp_intfeas1: row = %d: fixed value %g is non-i" + "nteger or out of range\n", i, row->lb); + else + xprintf("glp_intfeas1: row = %d: lower bound %g is non-i" + "nteger or out of range\n", i, row->lb); + ret = GLP_EDATA; + goto done; + } + temp = (int)row->ub; + if ((double)temp != row->ub) + { xprintf("glp_intfeas1: row = %d: upper bound %g is non-inte" + "ger or out of range\n", i, row->ub); + ret = GLP_EDATA; + goto done; + } + if (row->type == GLP_DB && row->lb > row->ub) + { xprintf("glp_intfeas1: row %d: lower bound %g is greater th" + "an upper bound %g\n", i, row->lb, row->ub); + ret = GLP_EBOUND; + goto done; + } + } + /* check the objective function */ + temp = (int)P->c0; + if ((double)temp != P->c0) + { xprintf("glp_intfeas1: objective constant term %g is non-integ" + "er or out of range\n", P->c0); + ret = GLP_EDATA; + goto done; + } + for (j = 1; j <= P->n; j++) + { temp = (int)P->col[j]->coef; + if ((double)temp != P->col[j]->coef) + { xprintf("glp_intfeas1: column %d: objective coefficient is " + "non-integer or out of range\n", j, P->col[j]->coef); + ret = GLP_EDATA; + goto done; + } + } + /* save the objective function and set it to zero */ + obj_ind = xcalloc(1+P->n, sizeof(int)); + obj_val = xcalloc(1+P->n, sizeof(double)); + obj_len = 0; + obj_ind[0] = 0; + obj_val[0] = P->c0; + P->c0 = 0.0; + for (j = 1; j <= P->n; j++) + { if (P->col[j]->coef != 0.0) + { obj_len++; + obj_ind[obj_len] = j; + obj_val[obj_len] = P->col[j]->coef; + P->col[j]->coef = 0.0; + } + } + /* add inequality to bound the objective function, if required */ + if (!use_bound) + xprintf("Will search for ANY feasible solution\n"); + else + { xprintf("Will search only for solution not worse than %d\n", + obj_bound); + obj_row = glp_add_rows(P, 1); + glp_set_mat_row(P, obj_row, obj_len, obj_ind, obj_val); + if (P->dir == GLP_MIN) + glp_set_row_bnds(P, obj_row, + GLP_UP, 0.0, (double)obj_bound - obj_val[0]); + else if (P->dir == GLP_MAX) + glp_set_row_bnds(P, obj_row, + GLP_LO, (double)obj_bound - obj_val[0], 0.0); + else + xassert(P != P); + } + /* create preprocessor workspace */ + xprintf("Translating to CNF-SAT...\n"); + xprintf("Original problem has %d row%s, %d column%s, and %d non-z" + "ero%s\n", P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : + "s", P->nnz, P->nnz == 1 ? "" : "s"); + npp = npp_create_wksp(); + /* load the original problem into the preprocessor workspace */ + npp_load_prob(npp, P, GLP_OFF, GLP_MIP, GLP_OFF); + /* perform translation to SAT-CNF problem instance */ + ret = npp_sat_encode_prob(npp); + if (ret == 0) + ; + else if (ret == GLP_ENOPFS) + xprintf("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION\n"); + else if (ret == GLP_ERANGE) + xprintf("glp_intfeas1: translation to SAT-CNF failed because o" + "f integer overflow\n"); + else + xassert(ret != ret); + if (ret != 0) + goto done; + /* build SAT-CNF problem instance and try to solve it */ + mip = glp_create_prob(); + npp_build_prob(npp, mip); + ret = glp_minisat1(mip); + /* only integer feasible solution can be postprocessed */ + if (!(mip->mip_stat == GLP_OPT || mip->mip_stat == GLP_FEAS)) + { P->mip_stat = mip->mip_stat; + goto done; + } + /* postprocess the solution found */ + npp_postprocess(npp, mip); + /* the transformed problem is no longer needed */ + glp_delete_prob(mip), mip = NULL; + /* store solution to the original problem object */ + npp_unload_sol(npp, P); + /* change the solution status to 'integer feasible' */ + P->mip_stat = GLP_FEAS; + /* check integer feasibility */ + for (i = 1; i <= P->m; i++) + { GLPROW *row; + GLPAIJ *aij; + double sum; + row = P->row[i]; + sum = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + sum += aij->val * aij->col->mipx; + xassert(sum == row->mipx); + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + xassert(sum >= row->lb); + if (row->type == GLP_UP || row->type == GLP_DB || + row->type == GLP_FX) + xassert(sum <= row->ub); + } + /* compute value of the original objective function */ + P->mip_obj = obj_val[0]; + for (k = 1; k <= obj_len; k++) + P->mip_obj += obj_val[k] * P->col[obj_ind[k]]->mipx; + xprintf("Objective value = %17.9e\n", P->mip_obj); +done: /* delete the transformed problem, if it exists */ + if (mip != NULL) + glp_delete_prob(mip); + /* delete the preprocessor workspace, if it exists */ + if (npp != NULL) + npp_delete_wksp(npp); + /* remove inequality used to bound the objective function */ + if (obj_row > 0) + { int ind[1+1]; + ind[1] = obj_row; + glp_del_rows(P, 1, ind); + } + /* restore the original objective function */ + if (obj_ind != NULL) + { P->c0 = obj_val[0]; + for (k = 1; k <= obj_len; k++) + P->col[obj_ind[k]]->coef = obj_val[k]; + xfree(obj_ind); + xfree(obj_val); + } + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpapi21.c b/resources/3rdparty/glpk-4.53/src/glpapi21.c new file mode 100644 index 000000000..3b54a0dfb --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpapi21.c @@ -0,0 +1,1428 @@ +/* glpapi21.c (stand-alone LP/MIP solver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "draft.h" +#include "env.h" +#include "glpgmp.h" +#include "misc.h" +#include "prob.h" + +struct csa +{ /* common storage area */ + glp_prob *prob; + /* LP/MIP problem object */ + glp_bfcp bfcp; + /* basis factorization control parameters */ + glp_smcp smcp; + /* simplex method control parameters */ + glp_iptcp iptcp; + /* interior-point method control parameters */ + glp_iocp iocp; + /* integer optimizer control parameters */ + glp_tran *tran; + /* model translator workspace */ + glp_graph *graph; + /* network problem object */ + int format; + /* problem file format: */ +#define FMT_MPS_DECK 1 /* fixed MPS */ +#define FMT_MPS_FILE 2 /* free MPS */ +#define FMT_LP 3 /* CPLEX LP */ +#define FMT_GLP 4 /* GLPK LP/MIP */ +#define FMT_MATHPROG 5 /* MathProg */ +#define FMT_MIN_COST 6 /* DIMACS min-cost flow */ +#define FMT_MAX_FLOW 7 /* DIMACS maximum flow */ +#if 1 /* 06/VIII-2011 */ +#define FMT_CNF 8 /* DIMACS CNF-SAT */ +#endif + const char *in_file; + /* name of input problem file */ +#define DATA_MAX 10 + /* maximal number of input data files */ + int ndf; + /* number of input data files specified */ + const char *in_data[1+DATA_MAX]; + /* name(s) of input data file(s) */ + const char *out_dpy; + /* name of output file to send display output; NULL means the + display output is sent to the terminal */ + int seed; + /* seed value to be passed to the MathProg translator; initially + set to 1; 0x80000000 means the value is omitted */ + int solution; + /* solution type flag: */ +#define SOL_BASIC 1 /* basic */ +#define SOL_INTERIOR 2 /* interior-point */ +#define SOL_INTEGER 3 /* mixed integer */ + const char *in_res; + /* name of input solution file in raw format */ + int dir; + /* optimization direction flag: + 0 - not specified + GLP_MIN - minimization + GLP_MAX - maximization */ + int scale; + /* automatic problem scaling flag */ + const char *out_sol; + /* name of output solution file in printable format */ + const char *out_res; + /* name of output solution file in raw format */ + const char *out_ranges; + /* name of output file to write sensitivity analysis report */ + int check; + /* input data checking flag; no solution is performed */ + const char *new_name; + /* new name to be assigned to the problem */ + const char *out_mps; + /* name of output problem file in fixed MPS format */ + const char *out_freemps; + /* name of output problem file in free MPS format */ + const char *out_cpxlp; + /* name of output problem file in CPLEX LP format */ + const char *out_glp; + /* name of output problem file in GLPK format */ +#if 0 + const char *out_pb; + /* name of output problem file in OPB format */ + const char *out_npb; + /* name of output problem file in normalized OPB format */ +#endif +#if 1 /* 06/VIII-2011 */ + const char *out_cnf; + /* name of output problem file in DIMACS CNF-SAT format */ +#endif + const char *log_file; + /* name of output file to hardcopy terminal output */ + int crash; + /* initial basis option: */ +#define USE_STD_BASIS 1 /* use standard basis */ +#define USE_ADV_BASIS 2 /* use advanced basis */ +#define USE_CPX_BASIS 3 /* use Bixby's basis */ +#define USE_INI_BASIS 4 /* use initial basis from ini_file */ + const char *ini_file; + /* name of input file containing initial basis */ + int exact; + /* flag to use glp_exact rather than glp_simplex */ + int xcheck; + /* flag to check final basis with glp_exact */ + int nomip; + /* flag to consider MIP as pure LP */ +#if 1 /* 15/VIII-2011 */ + int minisat; + /* option to solve feasibility problem with MiniSat solver */ + int use_bnd; + /* option to bound objective function */ + int obj_bnd; + /* upper (minization) or lower (maximization) objective bound */ +#endif +#if 1 /* 11/VII-2013 */ + const char *use_sol; + /* name of input mip solution file in GLPK format */ +#endif +}; + +static void print_help(const char *my_name) +{ /* print help information */ + xprintf("Usage: %s [options...] filename\n", my_name); + xprintf("\n"); + xprintf("General options:\n"); + xprintf(" --mps read LP/MIP problem in fixed MPS fo" + "rmat\n"); + xprintf(" --freemps read LP/MIP problem in free MPS for" + "mat (default)\n"); + xprintf(" --lp read LP/MIP problem in CPLEX LP for" + "mat\n"); + xprintf(" --glp read LP/MIP problem in GLPK format " + "\n"); + xprintf(" --math read LP/MIP model written in GNU Ma" + "thProg modeling\n"); + xprintf(" language\n"); + xprintf(" -m filename, --model filename\n"); + xprintf(" read model section and optional dat" + "a section from\n"); + xprintf(" filename (same as --math)\n"); + xprintf(" -d filename, --data filename\n"); + xprintf(" read data section from filename (fo" + "r --math only);\n"); + xprintf(" if model file also has data section" + ", it is ignored\n"); + xprintf(" -y filename, --display filename\n"); + xprintf(" send display output to filename (fo" + "r --math only);\n"); + xprintf(" by default the output is sent to te" + "rminal\n"); + xprintf(" --seed value initialize pseudo-random number gen" + "erator used in\n"); + xprintf(" MathProg model with specified seed " + "(any integer);\n"); + xprintf(" if seed value is ?, some random see" + "d will be used\n"); + xprintf(" --mincost read min-cost flow problem in DIMAC" + "S format\n"); + xprintf(" --maxflow read maximum flow problem in DIMACS" + " format\n"); +#if 1 /* 06/VIII-2011 */ + xprintf(" --cnf read CNF-SAT problem in DIMACS form" + "at\n"); +#endif + xprintf(" --simplex use simplex method (default)\n"); + xprintf(" --interior use interior point method (LP only)" + "\n"); + xprintf(" -r filename, --read filename\n"); + xprintf(" read solution from filename rather " + "to find it with\n"); + xprintf(" the solver\n"); + xprintf(" --min minimization\n"); + xprintf(" --max maximization\n"); + xprintf(" --scale scale problem (default)\n"); + xprintf(" --noscale do not scale problem\n"); + xprintf(" -o filename, --output filename\n"); + xprintf(" write solution to filename in print" + "able format\n"); + xprintf(" -w filename, --write filename\n"); + xprintf(" write solution to filename in plain" + " text format\n"); + xprintf(" --ranges filename\n"); + xprintf(" write sensitivity analysis report t" + "o filename in\n"); + xprintf(" printable format (simplex only)\n"); + xprintf(" --tmlim nnn limit solution time to nnn seconds " + "\n"); + xprintf(" --memlim nnn limit available memory to nnn megab" + "ytes\n"); + xprintf(" --check do not solve problem, check input d" + "ata only\n"); + xprintf(" --name probname change problem name to probname\n"); + xprintf(" --wmps filename write problem to filename in fixed " + "MPS format\n"); + xprintf(" --wfreemps filename\n"); + xprintf(" write problem to filename in free M" + "PS format\n"); + xprintf(" --wlp filename write problem to filename in CPLEX " + "LP format\n"); + xprintf(" --wglp filename write problem to filename in GLPK f" + "ormat\n"); +#if 0 + xprintf(" --wpb filename write problem to filename in OPB fo" + "rmat\n"); + xprintf(" --wnpb filename write problem to filename in normal" + "ized OPB format\n"); +#endif +#if 1 /* 06/VIII-2011 */ + xprintf(" --wcnf filename write problem to filename in DIMACS" + " CNF-SAT format\n"); +#endif + xprintf(" --log filename write copy of terminal output to fi" + "lename\n"); + xprintf(" -h, --help display this help information and e" + "xit\n"); + xprintf(" -v, --version display program version and exit\n") + ; + xprintf("\n"); + xprintf("LP basis factorization options:\n"); + xprintf(" --luf LU + Forrest-Tomlin update\n"); + xprintf(" (faster, less stable; default)\n"); + xprintf(" --cbg LU + Schur complement + Bartels-Gol" + "ub update\n"); + xprintf(" (slower, more stable)\n"); + xprintf(" --cgr LU + Schur complement + Givens rota" + "tion update\n"); + xprintf(" (slower, more stable)\n"); + xprintf("\n"); + xprintf("Options specific to simplex solver:\n"); + xprintf(" --primal use primal simplex (default)\n"); + xprintf(" --dual use dual simplex\n"); + xprintf(" --std use standard initial basis of all s" + "lacks\n"); + xprintf(" --adv use advanced initial basis (default" + ")\n"); + xprintf(" --bib use Bixby's initial basis\n"); + xprintf(" --ini filename use as initial basis previously sav" + "ed with -w\n"); + xprintf(" (disables LP presolver)\n"); + xprintf(" --steep use steepest edge technique (defaul" + "t)\n"); + xprintf(" --nosteep use standard \"textbook\" pricing\n" + ); + xprintf(" --relax use Harris' two-pass ratio test (de" + "fault)\n"); + xprintf(" --norelax use standard \"textbook\" ratio tes" + "t\n"); + xprintf(" --presol use presolver (default; assumes --s" + "cale and --adv)\n"); + xprintf(" --nopresol do not use presolver\n"); + xprintf(" --exact use simplex method based on exact a" + "rithmetic\n"); + xprintf(" --xcheck check final basis using exact arith" + "metic\n"); + xprintf("\n"); + xprintf("Options specific to interior-point solver:\n"); + xprintf(" --nord use natural (original) ordering\n"); + xprintf(" --qmd use quotient minimum degree orderin" + "g\n"); + xprintf(" --amd use approximate minimum degree orde" + "ring (default)\n"); + xprintf(" --symamd use approximate minimum degree orde" + "ring\n"); + xprintf("\n"); + xprintf("Options specific to MIP solver:\n"); + xprintf(" --nomip consider all integer variables as c" + "ontinuous\n"); + xprintf(" (allows solving MIP as pure LP)\n"); + xprintf(" --first branch on first integer variable\n") + ; + xprintf(" --last branch on last integer variable\n"); + xprintf(" --mostf branch on most fractional variable " + "\n"); + xprintf(" --drtom branch using heuristic by Driebeck " + "and Tomlin\n"); + xprintf(" (default)\n"); + xprintf(" --pcost branch using hybrid pseudocost heur" + "istic (may be\n"); + xprintf(" useful for hard instances)\n"); + xprintf(" --dfs backtrack using depth first search " + "\n"); + xprintf(" --bfs backtrack using breadth first searc" + "h\n"); + xprintf(" --bestp backtrack using the best projection" + " heuristic\n"); + xprintf(" --bestb backtrack using node with best loca" + "l bound\n"); + xprintf(" (default)\n"); + xprintf(" --intopt use MIP presolver (default)\n"); + xprintf(" --nointopt do not use MIP presolver\n"); + xprintf(" --binarize replace general integer variables b" + "y binary ones\n"); + xprintf(" (assumes --intopt)\n"); + xprintf(" --fpump apply feasibility pump heuristic\n") + ; +#if 1 /* 29/VI-2013 */ + xprintf(" --proxy [nnn] apply proximity search heuristic (n" + "nn is time limit\n"); + xprintf(" in seconds; default is 60)\n"); +#endif + xprintf(" --gomory generate Gomory's mixed integer cut" + "s\n"); + xprintf(" --mir generate MIR (mixed integer roundin" + "g) cuts\n"); + xprintf(" --cover generate mixed cover cuts\n"); + xprintf(" --clique generate clique cuts\n"); + xprintf(" --cuts generate all cuts above\n"); + xprintf(" --mipgap tol set relative mip gap tolerance to t" + "ol\n"); +#if 1 /* 15/VIII-2011 */ + xprintf(" --minisat translate integer feasibility probl" + "em to CNF-SAT\n"); + xprintf(" and solve it with MiniSat solver\n") + ; + xprintf(" --objbnd bound add inequality obj <= bound (minimi" + "zation) or\n"); + xprintf(" obj >= bound (maximization) to inte" + "ger feasibility\n"); + xprintf(" problem (assumes --minisat)\n"); +#endif + xprintf("\n"); + xprintf("For description of the MPS and CPLEX LP formats see Refe" + "rence Manual.\n"); + xprintf("For description of the modeling language see \"GLPK: Mod" + "eling Language\n"); + xprintf("GNU MathProg\". Both documents are included in the GLPK " + "distribution.\n"); + xprintf("\n"); + xprintf("See GLPK web page at <http://www.gnu.org/software/glpk/g" + "lpk.html>.\n"); + xprintf("\n"); + xprintf("Please report bugs to <bug-glpk@gnu.org>.\n"); + return; +} + +static void print_version(int briefly) +{ /* print version information */ + xprintf("GLPSOL: GLPK LP/MIP Solver, v%s\n", glp_version()); + if (briefly) goto done; + xprintf("\n"); + xprintf("Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, " + "2007, 2008,\n"); + xprintf("2009, 2010, 2011, 2013, 2014 Andrew Makhorin, Department" + " for Applied\n"); + xprintf("Informatics, Moscow Aviation Institute, Moscow, Russia. " + "All rights\n"); + xprintf("reserved. E-mail: <mao@gnu.org>.\n"); + xprintf("\n"); + xprintf("This program has ABSOLUTELY NO WARRANTY.\n"); + xprintf("\n"); + xprintf("This program is free software; you may re-distribute it " + "under the terms\n"); + xprintf("of the GNU General Public License version 3 or later.\n") + ; +done: return; +} + +static int parse_cmdline(struct csa *csa, int argc, const char *argv[]) +{ /* parse command-line parameters */ + int k; +#define p(str) (strcmp(argv[k], str) == 0) + for (k = 1; k < argc; k++) + { if (p("--mps")) + csa->format = FMT_MPS_DECK; + else if (p("--freemps")) + csa->format = FMT_MPS_FILE; + else if (p("--lp") || p("--cpxlp")) + csa->format = FMT_LP; + else if (p("--glp")) + csa->format = FMT_GLP; + else if (p("--math") || p("-m") || p("--model")) + csa->format = FMT_MATHPROG; + else if (p("-d") || p("--data")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No input data file specified\n"); + return 1; + } + if (csa->ndf == DATA_MAX) + { xprintf("Too many input data files\n"); + return 1; + } + csa->in_data[++(csa->ndf)] = argv[k]; + } + else if (p("-y") || p("--display")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No display output file specified\n"); + return 1; + } + if (csa->out_dpy != NULL) + { xprintf("Only one display output file allowed\n"); + return 1; + } + csa->out_dpy = argv[k]; + } + else if (p("--seed")) + { k++; + if (k == argc || argv[k][0] == '\0' || + argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1])) + { xprintf("No seed value specified\n"); + return 1; + } + if (strcmp(argv[k], "?") == 0) + csa->seed = 0x80000000; + else if (str2int(argv[k], &csa->seed)) + { xprintf("Invalid seed value '%s'\n", argv[k]); + return 1; + } + } + else if (p("--mincost")) + csa->format = FMT_MIN_COST; + else if (p("--maxflow")) + csa->format = FMT_MAX_FLOW; +#if 1 /* 06/VIII-2011 */ + else if (p("--cnf")) + csa->format = FMT_CNF; +#endif + else if (p("--simplex")) + csa->solution = SOL_BASIC; + else if (p("--interior")) + csa->solution = SOL_INTERIOR; +#if 1 /* 28/V-2010 */ + else if (p("--alien")) + csa->iocp.alien = GLP_ON; +#endif + else if (p("-r") || p("--read")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No input solution file specified\n"); + return 1; + } + if (csa->in_res != NULL) + { xprintf("Only one input solution file allowed\n"); + return 1; + } + csa->in_res = argv[k]; + } + else if (p("--min")) + csa->dir = GLP_MIN; + else if (p("--max")) + csa->dir = GLP_MAX; + else if (p("--scale")) + csa->scale = 1; + else if (p("--noscale")) + csa->scale = 0; + else if (p("-o") || p("--output")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No output solution file specified\n"); + return 1; + } + if (csa->out_sol != NULL) + { xprintf("Only one output solution file allowed\n"); + return 1; + } + csa->out_sol = argv[k]; + } + else if (p("-w") || p("--write")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No output solution file specified\n"); + return 1; + } + if (csa->out_res != NULL) + { xprintf("Only one output solution file allowed\n"); + return 1; + } + csa->out_res = argv[k]; + } + else if (p("--ranges") || p("--bounds")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No output file specified to write sensitivity a" + "nalysis report\n"); + return 1; + } + if (csa->out_ranges != NULL) + { xprintf("Only one output file allowed to write sensitivi" + "ty analysis report\n"); + return 1; + } + csa->out_ranges = argv[k]; + } + else if (p("--tmlim")) + { int tm_lim; + k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No time limit specified\n"); + return 1; + } + if (str2int(argv[k], &tm_lim) || tm_lim < 0) + { xprintf("Invalid time limit '%s'\n", argv[k]); + return 1; + } + if (tm_lim <= INT_MAX / 1000) + csa->smcp.tm_lim = csa->iocp.tm_lim = 1000 * tm_lim; + else + csa->smcp.tm_lim = csa->iocp.tm_lim = INT_MAX; + } + else if (p("--memlim")) + { int mem_lim; + k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No memory limit specified\n"); + return 1; + } + if (str2int(argv[k], &mem_lim) || mem_lim < 1) + { xprintf("Invalid memory limit '%s'\n", argv[k]); + return 1; + } + glp_mem_limit(mem_lim); + } + else if (p("--check")) + csa->check = 1; + else if (p("--name")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No problem name specified\n"); + return 1; + } + if (csa->new_name != NULL) + { xprintf("Only one problem name allowed\n"); + return 1; + } + csa->new_name = argv[k]; + } + else if (p("--wmps")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No fixed MPS output file specified\n"); + return 1; + } + if (csa->out_mps != NULL) + { xprintf("Only one fixed MPS output file allowed\n"); + return 1; + } + csa->out_mps = argv[k]; + } + else if (p("--wfreemps")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No free MPS output file specified\n"); + return 1; + } + if (csa->out_freemps != NULL) + { xprintf("Only one free MPS output file allowed\n"); + return 1; + } + csa->out_freemps = argv[k]; + } + else if (p("--wlp") || p("--wcpxlp") || p("--wlpt")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No CPLEX LP output file specified\n"); + return 1; + } + if (csa->out_cpxlp != NULL) + { xprintf("Only one CPLEX LP output file allowed\n"); + return 1; + } + csa->out_cpxlp = argv[k]; + } + else if (p("--wglp")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No GLPK LP/MIP output file specified\n"); + return 1; + } + if (csa->out_glp != NULL) + { xprintf("Only one GLPK LP/MIP output file allowed\n"); + return 1; + } + csa->out_glp = argv[k]; + } +#if 0 + else if (p("--wpb")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No problem output file specified\n"); + return 1; + } + if (csa->out_pb != NULL) + { xprintf("Only one OPB output file allowed\n"); + return 1; + } + csa->out_pb = argv[k]; + } + else if (p("--wnpb")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No problem output file specified\n"); + return 1; + } + if (csa->out_npb != NULL) + { xprintf("Only one normalized OPB output file allowed\n"); + return 1; + } + csa->out_npb = argv[k]; + } +#endif +#if 1 /* 06/VIII-2011 */ + else if (p("--wcnf")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No problem output file specified\n"); + return 1; + } + if (csa->out_cnf != NULL) + { xprintf("Only one output DIMACS CNF-SAT file allowed\n"); + return 1; + } + csa->out_cnf = argv[k]; + } +#endif + else if (p("--log")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No log file specified\n"); + return 1; + } + if (csa->log_file != NULL) + { xprintf("Only one log file allowed\n"); + return 1; + } + csa->log_file = argv[k]; + } + else if (p("-h") || p("--help")) + { print_help(argv[0]); + return -1; + } + else if (p("-v") || p("--version")) + { print_version(0); + return -1; + } + else if (p("--luf")) + csa->bfcp.type = GLP_BF_FT; + else if (p("--cbg")) + csa->bfcp.type = GLP_BF_BG; + else if (p("--cgr")) + csa->bfcp.type = GLP_BF_GR; + else if (p("--primal")) + csa->smcp.meth = GLP_PRIMAL; + else if (p("--dual")) + csa->smcp.meth = GLP_DUAL; + else if (p("--std")) + csa->crash = USE_STD_BASIS; + else if (p("--adv")) + csa->crash = USE_ADV_BASIS; + else if (p("--bib")) + csa->crash = USE_CPX_BASIS; + else if (p("--ini")) + { csa->crash = USE_INI_BASIS; + csa->smcp.presolve = GLP_OFF; + k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No initial basis file specified\n"); + return 1; + } + if (csa->ini_file != NULL) + { xprintf("Only one initial basis file allowed\n"); + return 1; + } + csa->ini_file = argv[k]; + } + else if (p("--steep")) + csa->smcp.pricing = GLP_PT_PSE; + else if (p("--nosteep")) + csa->smcp.pricing = GLP_PT_STD; + else if (p("--relax")) + csa->smcp.r_test = GLP_RT_HAR; + else if (p("--norelax")) + csa->smcp.r_test = GLP_RT_STD; + else if (p("--presol")) + csa->smcp.presolve = GLP_ON; + else if (p("--nopresol")) + csa->smcp.presolve = GLP_OFF; + else if (p("--exact")) + csa->exact = 1; + else if (p("--xcheck")) + csa->xcheck = 1; + else if (p("--nord")) + csa->iptcp.ord_alg = GLP_ORD_NONE; + else if (p("--qmd")) + csa->iptcp.ord_alg = GLP_ORD_QMD; + else if (p("--amd")) + csa->iptcp.ord_alg = GLP_ORD_AMD; + else if (p("--symamd")) + csa->iptcp.ord_alg = GLP_ORD_SYMAMD; + else if (p("--nomip")) + csa->nomip = 1; + else if (p("--first")) + csa->iocp.br_tech = GLP_BR_FFV; + else if (p("--last")) + csa->iocp.br_tech = GLP_BR_LFV; + else if (p("--drtom")) + csa->iocp.br_tech = GLP_BR_DTH; + else if (p("--mostf")) + csa->iocp.br_tech = GLP_BR_MFV; + else if (p("--pcost")) + csa->iocp.br_tech = GLP_BR_PCH; + else if (p("--dfs")) + csa->iocp.bt_tech = GLP_BT_DFS; + else if (p("--bfs")) + csa->iocp.bt_tech = GLP_BT_BFS; + else if (p("--bestp")) + csa->iocp.bt_tech = GLP_BT_BPH; + else if (p("--bestb")) + csa->iocp.bt_tech = GLP_BT_BLB; + else if (p("--intopt")) + csa->iocp.presolve = GLP_ON; + else if (p("--nointopt")) + csa->iocp.presolve = GLP_OFF; + else if (p("--binarize")) + csa->iocp.presolve = csa->iocp.binarize = GLP_ON; + else if (p("--fpump")) + csa->iocp.fp_heur = GLP_ON; +#if 1 /* 29/VI-2013 */ + else if (p("--proxy")) + { csa->iocp.ps_heur = GLP_ON; + if (argv[k+1] && isdigit((unsigned char)argv[k+1][0])) + { int nnn; + k++; + if (str2int(argv[k], &nnn) || nnn < 1) + { xprintf("Invalid proxy time limit '%s'\n", argv[k]); + return 1; + } + csa->iocp.ps_tm_lim = 1000 * nnn; + } + } +#endif + else if (p("--gomory")) + csa->iocp.gmi_cuts = GLP_ON; + else if (p("--mir")) + csa->iocp.mir_cuts = GLP_ON; + else if (p("--cover")) + csa->iocp.cov_cuts = GLP_ON; + else if (p("--clique")) + csa->iocp.clq_cuts = GLP_ON; + else if (p("--cuts")) + csa->iocp.gmi_cuts = csa->iocp.mir_cuts = + csa->iocp.cov_cuts = csa->iocp.clq_cuts = GLP_ON; + else if (p("--mipgap")) + { double mip_gap; + k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No relative gap tolerance specified\n"); + return 1; + } + if (str2num(argv[k], &mip_gap) || mip_gap < 0.0) + { xprintf("Invalid relative mip gap tolerance '%s'\n", + argv[k]); + return 1; + } + csa->iocp.mip_gap = mip_gap; + } +#if 1 /* 15/VIII-2011 */ + else if (p("--minisat")) + csa->minisat = 1; + else if (p("--objbnd")) + { k++; + if (k == argc || argv[k][0] == '\0' || + argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1])) + { xprintf("No objective bound specified\n"); + return 1; + } + csa->minisat = 1; + csa->use_bnd = 1; + if (str2int(argv[k], &csa->obj_bnd)) + { xprintf("Invalid objective bound '%s' (should be integer" + " value)\n", argv[k]); + return 1; + } + } +#endif +#if 1 /* 11/VII-2013 */ + else if (p("--use")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No input MIP solution file specified\n"); + return 1; + } + if (csa->use_sol != NULL) + { xprintf("Only one input MIP solution file allowed\n"); + return 1; + } + csa->use_sol = argv[k]; + } + else if (p("--save")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No output MIP solution file specified\n"); + return 1; + } + if (csa->iocp.save_sol != NULL) + { xprintf("Only one output MIP solution file allowed\n"); + return 1; + } + csa->iocp.save_sol = argv[k]; + } +#endif + else if (argv[k][0] == '-' || + (argv[k][0] == '-' && argv[k][1] == '-')) + { xprintf("Invalid option '%s'; try %s --help\n", + argv[k], argv[0]); + return 1; + } + else + { if (csa->in_file != NULL) + { xprintf("Only one input problem file allowed\n"); + return 1; + } + csa->in_file = argv[k]; + } + } +#undef p + return 0; +} + +typedef struct { double rhs, pi; } v_data; +typedef struct { double low, cap, cost, x; } a_data; + +int glp_main(int argc, const char *argv[]) +{ /* stand-alone LP/MIP solver */ + struct csa _csa, *csa = &_csa; + int ret; +#if 0 /* 10/VI-2013 */ + glp_long start; +#else + double start; +#endif + /* perform initialization */ + csa->prob = glp_create_prob(); + glp_get_bfcp(csa->prob, &csa->bfcp); + glp_init_smcp(&csa->smcp); + csa->smcp.presolve = GLP_ON; + glp_init_iptcp(&csa->iptcp); + glp_init_iocp(&csa->iocp); + csa->iocp.presolve = GLP_ON; + csa->tran = NULL; + csa->graph = NULL; + csa->format = FMT_MPS_FILE; + csa->in_file = NULL; + csa->ndf = 0; + csa->out_dpy = NULL; + csa->seed = 1; + csa->solution = SOL_BASIC; + csa->in_res = NULL; + csa->dir = 0; + csa->scale = 1; + csa->out_sol = NULL; + csa->out_res = NULL; + csa->out_ranges = NULL; + csa->check = 0; + csa->new_name = NULL; + csa->out_mps = NULL; + csa->out_freemps = NULL; + csa->out_cpxlp = NULL; + csa->out_glp = NULL; +#if 0 + csa->out_pb = NULL; + csa->out_npb = NULL; +#endif +#if 1 /* 06/VIII-2011 */ + csa->out_cnf = NULL; +#endif + csa->log_file = NULL; + csa->crash = USE_ADV_BASIS; + csa->ini_file = NULL; + csa->exact = 0; + csa->xcheck = 0; + csa->nomip = 0; +#if 1 /* 15/VIII-2011 */ + csa->minisat = 0; + csa->use_bnd = 0; + csa->obj_bnd = 0; +#endif +#if 1 /* 11/VII-2013 */ + csa->use_sol = NULL; +#endif + /* parse command-line parameters */ + ret = parse_cmdline(csa, argc, argv); + if (ret < 0) + { ret = EXIT_SUCCESS; + goto done; + } + if (ret > 0) + { ret = EXIT_FAILURE; + goto done; + } + /*--------------------------------------------------------------*/ + /* remove all output files specified in the command line */ + if (csa->out_dpy != NULL) remove(csa->out_dpy); + if (csa->out_sol != NULL) remove(csa->out_sol); + if (csa->out_res != NULL) remove(csa->out_res); + if (csa->out_ranges != NULL) remove(csa->out_ranges); + if (csa->out_mps != NULL) remove(csa->out_mps); + if (csa->out_freemps != NULL) remove(csa->out_freemps); + if (csa->out_cpxlp != NULL) remove(csa->out_cpxlp); + if (csa->out_glp != NULL) remove(csa->out_glp); +#if 0 + if (csa->out_pb != NULL) remove(csa->out_pb); + if (csa->out_npb != NULL) remove(csa->out_npb); +#endif +#if 1 /* 06/VIII-2011 */ + if (csa->out_cnf != NULL) remove(csa->out_cnf); +#endif + if (csa->log_file != NULL) remove(csa->log_file); + /*--------------------------------------------------------------*/ + /* open log file, if required */ + if (csa->log_file != NULL) + { if (glp_open_tee(csa->log_file)) + { xprintf("Unable to create log file\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /*--------------------------------------------------------------*/ + /* print version information */ + print_version(1); + /*--------------------------------------------------------------*/ + /* print parameters specified in the command line */ + if (argc > 1) + { int k, len = INT_MAX; + xprintf("Parameter(s) specified in the command line:"); + for (k = 1; k < argc; k++) + { if (len > 72) + xprintf("\n"), len = 0; + xprintf(" %s", argv[k]); + len += 1 + strlen(argv[k]); + } + xprintf("\n"); + } + /*--------------------------------------------------------------*/ + /* read problem data from the input file */ + if (csa->in_file == NULL) + { xprintf("No input problem file specified; try %s --help\n", + argv[0]); + ret = EXIT_FAILURE; + goto done; + } + if (csa->format == FMT_MPS_DECK) + { ret = glp_read_mps(csa->prob, GLP_MPS_DECK, NULL, + csa->in_file); + if (ret != 0) +err1: { xprintf("MPS file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + } + else if (csa->format == FMT_MPS_FILE) + { ret = glp_read_mps(csa->prob, GLP_MPS_FILE, NULL, + csa->in_file); + if (ret != 0) goto err1; + } + else if (csa->format == FMT_LP) + { ret = glp_read_lp(csa->prob, NULL, csa->in_file); + if (ret != 0) + { xprintf("CPLEX LP file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + } + else if (csa->format == FMT_GLP) + { ret = glp_read_prob(csa->prob, 0, csa->in_file); + if (ret != 0) + { xprintf("GLPK LP/MIP file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + } + else if (csa->format == FMT_MATHPROG) + { int k; + /* allocate the translator workspace */ + csa->tran = glp_mpl_alloc_wksp(); + /* set seed value */ + if (csa->seed == 0x80000000) +#if 0 /* 10/VI-2013 */ + { csa->seed = glp_time().lo; +#else + { csa->seed = (int)fmod(glp_time(), 1000000000.0); +#endif + xprintf("Seed value %d will be used\n", csa->seed); + } + _glp_mpl_init_rand(csa->tran, csa->seed); + /* read model section and optional data section */ + if (glp_mpl_read_model(csa->tran, csa->in_file, csa->ndf > 0)) +err2: { xprintf("MathProg model processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + /* read optional data section(s), if necessary */ + for (k = 1; k <= csa->ndf; k++) + { if (glp_mpl_read_data(csa->tran, csa->in_data[k])) + goto err2; + } + /* generate the model */ + if (glp_mpl_generate(csa->tran, csa->out_dpy)) goto err2; + /* build the problem instance from the model */ + glp_mpl_build_prob(csa->tran, csa->prob); + } + else if (csa->format == FMT_MIN_COST) + { csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); + ret = glp_read_mincost(csa->graph, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), csa->in_file); + if (ret != 0) + { xprintf("DIMACS file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + glp_mincost_lp(csa->prob, csa->graph, GLP_ON, + offsetof(v_data, rhs), offsetof(a_data, low), + offsetof(a_data, cap), offsetof(a_data, cost)); + glp_set_prob_name(csa->prob, csa->in_file); + } + else if (csa->format == FMT_MAX_FLOW) + { int s, t; + csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); + ret = glp_read_maxflow(csa->graph, &s, &t, + offsetof(a_data, cap), csa->in_file); + if (ret != 0) + { xprintf("DIMACS file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + glp_maxflow_lp(csa->prob, csa->graph, GLP_ON, s, t, + offsetof(a_data, cap)); + glp_set_prob_name(csa->prob, csa->in_file); + } +#if 1 /* 06/VIII-2011 */ + else if (csa->format == FMT_CNF) + { ret = glp_read_cnfsat(csa->prob, csa->in_file); + if (ret != 0) + { xprintf("DIMACS file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + glp_set_prob_name(csa->prob, csa->in_file); + } +#endif + else + xassert(csa != csa); + /*--------------------------------------------------------------*/ + /* change problem name, if required */ + if (csa->new_name != NULL) + glp_set_prob_name(csa->prob, csa->new_name); + /* change optimization direction, if required */ + if (csa->dir != 0) + glp_set_obj_dir(csa->prob, csa->dir); + /* sort elements of the constraint matrix */ + glp_sort_matrix(csa->prob); + /*--------------------------------------------------------------*/ + /* write problem data in fixed MPS format, if required */ + if (csa->out_mps != NULL) + { ret = glp_write_mps(csa->prob, GLP_MPS_DECK, NULL, + csa->out_mps); + if (ret != 0) + { xprintf("Unable to write problem in fixed MPS format\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write problem data in free MPS format, if required */ + if (csa->out_freemps != NULL) + { ret = glp_write_mps(csa->prob, GLP_MPS_FILE, NULL, + csa->out_freemps); + if (ret != 0) + { xprintf("Unable to write problem in free MPS format\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write problem data in CPLEX LP format, if required */ + if (csa->out_cpxlp != NULL) + { ret = glp_write_lp(csa->prob, NULL, csa->out_cpxlp); + if (ret != 0) + { xprintf("Unable to write problem in CPLEX LP format\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write problem data in GLPK format, if required */ + if (csa->out_glp != NULL) + { ret = glp_write_prob(csa->prob, 0, csa->out_glp); + if (ret != 0) + { xprintf("Unable to write problem in GLPK format\n"); + ret = EXIT_FAILURE; + goto done; + } + } +#if 0 + /* write problem data in OPB format, if required */ + if (csa->out_pb != NULL) + { ret = lpx_write_pb(csa->prob, csa->out_pb, 0, 0); + if (ret != 0) + { xprintf("Unable to write problem in OPB format\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write problem data in normalized OPB format, if required */ + if (csa->out_npb != NULL) + { ret = lpx_write_pb(csa->prob, csa->out_npb, 1, 1); + if (ret != 0) + { xprintf( + "Unable to write problem in normalized OPB format\n"); + ret = EXIT_FAILURE; + goto done; + } + } +#endif +#if 1 /* 06/VIII-2011 */ + /* write problem data in DIMACS CNF-SAT format, if required */ + if (csa->out_cnf != NULL) + { ret = glp_write_cnfsat(csa->prob, csa->out_cnf); + if (ret != 0) + { xprintf( + "Unable to write problem in DIMACS CNF-SAT format\n"); + ret = EXIT_FAILURE; + goto done; + } + } +#endif + /*--------------------------------------------------------------*/ + /* if only problem data check is required, skip computations */ + if (csa->check) + { ret = EXIT_SUCCESS; + goto done; + } + /*--------------------------------------------------------------*/ + /* determine the solution type */ + if (!csa->nomip && + glp_get_num_int(csa->prob) + glp_get_num_bin(csa->prob) > 0) + { if (csa->solution == SOL_INTERIOR) + { xprintf("Interior-point method is not able to solve MIP pro" + "blem; use --simplex\n"); + ret = EXIT_FAILURE; + goto done; + } + csa->solution = SOL_INTEGER; + } + /*--------------------------------------------------------------*/ + /* if solution is provided, read it and skip computations */ + if (csa->in_res != NULL) + { if (csa->solution == SOL_BASIC) + ret = glp_read_sol(csa->prob, csa->in_res); + else if (csa->solution == SOL_INTERIOR) + ret = glp_read_ipt(csa->prob, csa->in_res); + else if (csa->solution == SOL_INTEGER) + ret = glp_read_mip(csa->prob, csa->in_res); + else + xassert(csa != csa); + if (ret != 0) + { xprintf("Unable to read problem solution\n"); + ret = EXIT_FAILURE; + goto done; + } + goto skip; + } +#if 1 /* 11/VII-2013 */ + /*--------------------------------------------------------------*/ + /* if initial MIP solution is provided, read it */ + if (csa->solution == SOL_INTEGER && csa->use_sol != NULL) + { ret = glp_read_mip(csa->prob, csa->use_sol); + if (ret != 0) + { xprintf("Unable to read initial MIP solution\n"); + ret = EXIT_FAILURE; + goto done; + } + csa->iocp.use_sol = GLP_ON; + } +#endif + /*--------------------------------------------------------------*/ + /* scale the problem data, if required */ + if (csa->scale) + { if (csa->solution == SOL_BASIC && !csa->smcp.presolve || + csa->solution == SOL_INTERIOR || + csa->solution == SOL_INTEGER && !csa->iocp.presolve) + glp_scale_prob(csa->prob, GLP_SF_AUTO); + } + /*--------------------------------------------------------------*/ + /* construct starting LP basis */ + if (csa->solution == SOL_BASIC && !csa->smcp.presolve || + csa->solution == SOL_INTEGER && !csa->iocp.presolve) + { if (csa->crash == USE_STD_BASIS) + glp_std_basis(csa->prob); + else if (csa->crash == USE_ADV_BASIS) + glp_adv_basis(csa->prob, 0); + else if (csa->crash == USE_CPX_BASIS) + glp_cpx_basis(csa->prob); + else if (csa->crash == USE_INI_BASIS) + { ret = glp_read_sol(csa->prob, csa->ini_file); + if (ret != 0) + { xprintf("Unable to read initial basis\n"); + ret = EXIT_FAILURE; + goto done; + } + } + else + xassert(csa != csa); + } + /*--------------------------------------------------------------*/ + /* solve the problem */ + start = xtime(); + if (csa->solution == SOL_BASIC) + { if (!csa->exact) + { glp_set_bfcp(csa->prob, &csa->bfcp); + glp_simplex(csa->prob, &csa->smcp); + if (csa->xcheck) + { if (csa->smcp.presolve && + glp_get_status(csa->prob) != GLP_OPT) + xprintf("If you need to check final basis for non-opt" + "imal solution, use --nopresol\n"); + else + glp_exact(csa->prob, &csa->smcp); + } + if (csa->out_sol != NULL || csa->out_res != NULL) + { if (csa->smcp.presolve && + glp_get_status(csa->prob) != GLP_OPT) + xprintf("If you need actual output for non-optimal solut" + "ion, use --nopresol\n"); + } + } + else + glp_exact(csa->prob, &csa->smcp); + } + else if (csa->solution == SOL_INTERIOR) + glp_interior(csa->prob, &csa->iptcp); +#if 1 /* 15/VIII-2011 */ + else if (csa->solution == SOL_INTEGER && csa->minisat) + { if (glp_check_cnfsat(csa->prob) == 0) + glp_minisat1(csa->prob); + else + glp_intfeas1(csa->prob, csa->use_bnd, csa->obj_bnd); + } +#endif + else if (csa->solution == SOL_INTEGER) + { glp_set_bfcp(csa->prob, &csa->bfcp); + if (!csa->iocp.presolve) + glp_simplex(csa->prob, &csa->smcp); +#if 0 + csa->iocp.msg_lev = GLP_MSG_DBG; + csa->iocp.pp_tech = GLP_PP_NONE; +#endif + glp_intopt(csa->prob, &csa->iocp); + } + else + xassert(csa != csa); + /*--------------------------------------------------------------*/ + /* display statistics */ + xprintf("Time used: %.1f secs\n", xdifftime(xtime(), start)); +#if 0 /* 16/II-2012 */ + { glp_long tpeak; + char buf[50]; + glp_mem_usage(NULL, NULL, NULL, &tpeak); + xprintf("Memory used: %.1f Mb (%s bytes)\n", + xltod(tpeak) / 1048576.0, xltoa(tpeak, buf)); + } +#else + { size_t tpeak; + glp_mem_usage(NULL, NULL, NULL, &tpeak); + xprintf("Memory used: %.1f Mb (%.0f bytes)\n", + (double)tpeak / 1048576.0, (double)tpeak); + } +#endif + /*--------------------------------------------------------------*/ +skip: /* postsolve the model, if necessary */ + if (csa->tran != NULL) + { if (csa->solution == SOL_BASIC) + { if (!(glp_get_status(csa->prob) == GLP_OPT || + glp_get_status(csa->prob) == GLP_FEAS)) + ret = -1; + else + ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_SOL); + } + else if (csa->solution == SOL_INTERIOR) + { if (!(glp_ipt_status(csa->prob) == GLP_OPT || + glp_ipt_status(csa->prob) == GLP_FEAS)) + ret = -1; + else + ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_IPT); + } + else if (csa->solution == SOL_INTEGER) + { if (!(glp_mip_status(csa->prob) == GLP_OPT || + glp_mip_status(csa->prob) == GLP_FEAS)) + ret = -1; + else + ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_MIP); + } + else + xassert(csa != csa); + if (ret > 0) + { xprintf("Model postsolving error\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /*--------------------------------------------------------------*/ + /* write problem solution in printable format, if required */ + if (csa->out_sol != NULL) + { if (csa->solution == SOL_BASIC) + ret = glp_print_sol(csa->prob, csa->out_sol); + else if (csa->solution == SOL_INTERIOR) + ret = glp_print_ipt(csa->prob, csa->out_sol); + else if (csa->solution == SOL_INTEGER) + ret = glp_print_mip(csa->prob, csa->out_sol); + else + xassert(csa != csa); + if (ret != 0) + { xprintf("Unable to write problem solution\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write problem solution in printable format, if required */ + if (csa->out_res != NULL) + { if (csa->solution == SOL_BASIC) + ret = glp_write_sol(csa->prob, csa->out_res); + else if (csa->solution == SOL_INTERIOR) + ret = glp_write_ipt(csa->prob, csa->out_res); + else if (csa->solution == SOL_INTEGER) + ret = glp_write_mip(csa->prob, csa->out_res); + else + xassert(csa != csa); + if (ret != 0) + { xprintf("Unable to write problem solution\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write sensitivity analysis report, if required */ + if (csa->out_ranges != NULL) + { if (csa->solution == SOL_BASIC) + { if (glp_get_status(csa->prob) == GLP_OPT) + { if (glp_bf_exists(csa->prob)) +ranges: { ret = glp_print_ranges(csa->prob, 0, NULL, 0, + csa->out_ranges); + if (ret != 0) + { xprintf("Unable to write sensitivity analysis repo" + "rt\n"); + ret = EXIT_FAILURE; + goto done; + } + } + else + { ret = glp_factorize(csa->prob); + if (ret == 0) goto ranges; + xprintf("Cannot produce sensitivity analysis report d" + "ue to error in basis factorization (glp_factorize" + " returned %d); try --nopresol\n", ret); + } + } + else + xprintf("Cannot produce sensitivity analysis report for " + "non-optimal basic solution\n"); + } + else + xprintf("Cannot produce sensitivity analysis report for int" + "erior-point or MIP solution\n"); + } + /*--------------------------------------------------------------*/ + /* all seems to be ok */ + ret = EXIT_SUCCESS; + /*--------------------------------------------------------------*/ +done: /* delete the LP/MIP problem object */ + if (csa->prob != NULL) + glp_delete_prob(csa->prob); + /* free the translator workspace, if necessary */ + if (csa->tran != NULL) + glp_mpl_free_wksp(csa->tran); + /* delete the network problem object, if necessary */ + if (csa->graph != NULL) + glp_delete_graph(csa->graph); + xassert(gmp_pool_count() == 0); + gmp_free_mem(); + /* close log file, if necessary */ + if (csa->log_file != NULL) glp_close_tee(); + /* check that no memory blocks are still allocated */ +#if 0 /* 16/II-2012 */ + { int count; + glp_long total; + glp_mem_usage(&count, NULL, &total, NULL); + if (count != 0) + xerror("Error: %d memory block(s) were lost\n", count); + xassert(count == 0); + xassert(total.lo == 0 && total.hi == 0); + } +#else + { int count; + size_t total; + glp_mem_usage(&count, NULL, &total, NULL); + if (count != 0) + xerror("Error: %d memory block(s) were lost\n", count); + xassert(total == 0); + } +#endif + /* free the GLPK environment */ + glp_free_env(); + /* return to the control program */ + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpcpx.c b/resources/3rdparty/glpk-4.53/src/glpcpx.c new file mode 100644 index 000000000..1aa3f346b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpcpx.c @@ -0,0 +1,1262 @@ +/* glpcpx.c (CPLEX LP format routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "misc.h" +#include "prob.h" + +#define xfprintf glp_format + +/*********************************************************************** +* NAME +* +* glp_init_cpxcp - initialize CPLEX LP format control parameters +* +* SYNOPSIS +* +* void glp_init_cpxcp(glp_cpxcp *parm): +* +* The routine glp_init_cpxcp initializes control parameters used by +* the CPLEX LP input/output routines glp_read_lp and glp_write_lp with +* default values. +* +* Default values of the control parameters are stored in the glp_cpxcp +* structure, which the parameter parm points to. */ + +void glp_init_cpxcp(glp_cpxcp *parm) +{ xassert(parm != NULL); + return; +} + +static void check_parm(const char *func, const glp_cpxcp *parm) +{ /* check control parameters */ + xassert(func != NULL); + xassert(parm != NULL); + return; +} + +/*********************************************************************** +* NAME +* +* glp_read_lp - read problem data in CPLEX LP format +* +* SYNOPSIS +* +* int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char +* *fname); +* +* DESCRIPTION +* +* The routine glp_read_lp reads problem data in CPLEX LP format from +* a text file. +* +* The parameter parm is a pointer to the structure glp_cpxcp, which +* specifies control parameters used by the routine. If parm is NULL, +* the routine uses default settings. +* +* The character string fname specifies a name of the text file to be +* read. +* +* Note that before reading data the current content of the problem +* object is completely erased with the routine glp_erase_prob. +* +* RETURNS +* +* If the operation was successful, the routine glp_read_lp returns +* zero. Otherwise, it prints an error message and returns non-zero. */ + +struct csa +{ /* common storage area */ + glp_prob *P; + /* LP/MIP problem object */ + const glp_cpxcp *parm; + /* pointer to control parameters */ + const char *fname; + /* name of input CPLEX LP file */ + glp_file *fp; + /* stream assigned to input CPLEX LP file */ + jmp_buf jump; + /* label for go to in case of error */ + int count; + /* line count */ + int c; + /* current character or EOF */ + int token; + /* current token: */ +#define T_EOF 0x00 /* end of file */ +#define T_MINIMIZE 0x01 /* keyword 'minimize' */ +#define T_MAXIMIZE 0x02 /* keyword 'maximize' */ +#define T_SUBJECT_TO 0x03 /* keyword 'subject to' */ +#define T_BOUNDS 0x04 /* keyword 'bounds' */ +#define T_GENERAL 0x05 /* keyword 'general' */ +#define T_INTEGER 0x06 /* keyword 'integer' */ +#define T_BINARY 0x07 /* keyword 'binary' */ +#define T_END 0x08 /* keyword 'end' */ +#define T_NAME 0x09 /* symbolic name */ +#define T_NUMBER 0x0A /* numeric constant */ +#define T_PLUS 0x0B /* delimiter '+' */ +#define T_MINUS 0x0C /* delimiter '-' */ +#define T_COLON 0x0D /* delimiter ':' */ +#define T_LE 0x0E /* delimiter '<=' */ +#define T_GE 0x0F /* delimiter '>=' */ +#define T_EQ 0x10 /* delimiter '=' */ + char image[255+1]; + /* image of current token */ + int imlen; + /* length of token image */ + double value; + /* value of numeric constant */ + int n_max; + /* length of the following five arrays (enlarged automatically, + if necessary) */ + int *ind; /* int ind[1+n_max]; */ + double *val; /* double val[1+n_max]; */ + char *flag; /* char flag[1+n_max]; */ + /* working arrays used to construct linear forms */ + double *lb; /* double lb[1+n_max]; */ + double *ub; /* double ub[1+n_max]; */ + /* lower and upper bounds of variables (columns) */ +#if 1 /* 27/VII-2013 */ + int lb_warn, ub_warn; + /* warning 'lower/upper bound redefined' already issued */ +#endif +}; + +#define CHAR_SET "!\"#$%&()/,.;?@_`'{}|~" +/* characters, which may appear in symbolic names */ + +static void error(struct csa *csa, const char *fmt, ...) +{ /* print error message and terminate processing */ + va_list arg; + xprintf("%s:%d: ", csa->fname, csa->count); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + longjmp(csa->jump, 1); + /* no return */ +} + +static void warning(struct csa *csa, const char *fmt, ...) +{ /* print warning message and continue processing */ + va_list arg; + xprintf("%s:%d: warning: ", csa->fname, csa->count); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + return; +} + +static void read_char(struct csa *csa) +{ /* read next character from input file */ + int c; + xassert(csa->c != EOF); + if (csa->c == '\n') csa->count++; + c = glp_getc(csa->fp); + if (c < 0) + { if (glp_ioerr(csa->fp)) + error(csa, "read error - %s\n", get_err_msg()); + else if (csa->c == '\n') + { csa->count--; + c = EOF; + } + else + { warning(csa, "missing final end of line\n"); + c = '\n'; + } + } + else if (c == '\n') + ; + else if (isspace(c)) + c = ' '; + else if (iscntrl(c)) + error(csa, "invalid control character 0x%02X\n", c); + csa->c = c; + return; +} + +static void add_char(struct csa *csa) +{ /* append current character to current token */ + if (csa->imlen == sizeof(csa->image)-1) + error(csa, "token '%.15s...' too long\n", csa->image); + csa->image[csa->imlen++] = (char)csa->c; + csa->image[csa->imlen] = '\0'; + read_char(csa); + return; +} + +static int the_same(char *s1, char *s2) +{ /* compare two character strings ignoring case sensitivity */ + for (; *s1 != '\0'; s1++, s2++) + { if (tolower((unsigned char)*s1) != tolower((unsigned char)*s2)) + return 0; + } + return 1; +} + +static void scan_token(struct csa *csa) +{ /* scan next token */ + int flag; + csa->token = -1; + csa->image[0] = '\0'; + csa->imlen = 0; + csa->value = 0.0; +loop: flag = 0; + /* skip non-significant characters */ + while (csa->c == ' ') read_char(csa); + /* recognize and scan current token */ + if (csa->c == EOF) + csa->token = T_EOF; + else if (csa->c == '\n') + { read_char(csa); + /* if the next character is letter, it may begin a keyword */ + if (isalpha(csa->c)) + { flag = 1; + goto name; + } + goto loop; + } + else if (csa->c == '\\') + { /* comment; ignore everything until end-of-line */ + while (csa->c != '\n') read_char(csa); + goto loop; + } + else if (isalpha(csa->c) || csa->c != '.' && strchr(CHAR_SET, + csa->c) != NULL) +name: { /* symbolic name */ + csa->token = T_NAME; + while (isalnum(csa->c) || strchr(CHAR_SET, csa->c) != NULL) + add_char(csa); + if (flag) + { /* check for keyword */ + if (the_same(csa->image, "minimize")) + csa->token = T_MINIMIZE; + else if (the_same(csa->image, "minimum")) + csa->token = T_MINIMIZE; + else if (the_same(csa->image, "min")) + csa->token = T_MINIMIZE; + else if (the_same(csa->image, "maximize")) + csa->token = T_MAXIMIZE; + else if (the_same(csa->image, "maximum")) + csa->token = T_MAXIMIZE; + else if (the_same(csa->image, "max")) + csa->token = T_MAXIMIZE; + else if (the_same(csa->image, "subject")) + { if (csa->c == ' ') + { read_char(csa); + if (tolower(csa->c) == 't') + { csa->token = T_SUBJECT_TO; + csa->image[csa->imlen++] = ' '; + csa->image[csa->imlen] = '\0'; + add_char(csa); + if (tolower(csa->c) != 'o') + error(csa, "keyword 'subject to' incomplete\n"); + add_char(csa); + if (isalpha(csa->c)) + error(csa, "keyword '%s%c...' not recognized\n", + csa->image, csa->c); + } + } + } + else if (the_same(csa->image, "such")) + { if (csa->c == ' ') + { read_char(csa); + if (tolower(csa->c) == 't') + { csa->token = T_SUBJECT_TO; + csa->image[csa->imlen++] = ' '; + csa->image[csa->imlen] = '\0'; + add_char(csa); + if (tolower(csa->c) != 'h') +err: error(csa, "keyword 'such that' incomplete\n"); + add_char(csa); + if (tolower(csa->c) != 'a') goto err; + add_char(csa); + if (tolower(csa->c) != 't') goto err; + add_char(csa); + if (isalpha(csa->c)) + error(csa, "keyword '%s%c...' not recognized\n", + csa->image, csa->c); + } + } + } + else if (the_same(csa->image, "st")) + csa->token = T_SUBJECT_TO; + else if (the_same(csa->image, "s.t.")) + csa->token = T_SUBJECT_TO; + else if (the_same(csa->image, "st.")) + csa->token = T_SUBJECT_TO; + else if (the_same(csa->image, "bounds")) + csa->token = T_BOUNDS; + else if (the_same(csa->image, "bound")) + csa->token = T_BOUNDS; + else if (the_same(csa->image, "general")) + csa->token = T_GENERAL; + else if (the_same(csa->image, "generals")) + csa->token = T_GENERAL; + else if (the_same(csa->image, "gen")) + csa->token = T_GENERAL; + else if (the_same(csa->image, "integer")) + csa->token = T_INTEGER; + else if (the_same(csa->image, "integers")) + csa->token = T_INTEGER; + else if (the_same(csa->image, "int")) + csa->token = T_INTEGER; + else if (the_same(csa->image, "binary")) + csa->token = T_BINARY; + else if (the_same(csa->image, "binaries")) + csa->token = T_BINARY; + else if (the_same(csa->image, "bin")) + csa->token = T_BINARY; + else if (the_same(csa->image, "end")) + csa->token = T_END; + } + } + else if (isdigit(csa->c) || csa->c == '.') + { /* numeric constant */ + csa->token = T_NUMBER; + /* scan integer part */ + while (isdigit(csa->c)) add_char(csa); + /* scan optional fractional part (it is mandatory, if there is + no integer part) */ + if (csa->c == '.') + { add_char(csa); + if (csa->imlen == 1 && !isdigit(csa->c)) + error(csa, "invalid use of decimal point\n"); + while (isdigit(csa->c)) add_char(csa); + } + /* scan optional decimal exponent */ + if (csa->c == 'e' || csa->c == 'E') + { add_char(csa); + if (csa->c == '+' || csa->c == '-') add_char(csa); + if (!isdigit(csa->c)) + error(csa, "numeric constant '%s' incomplete\n", + csa->image); + while (isdigit(csa->c)) add_char(csa); + } + /* convert the numeric constant to floating-point */ + if (str2num(csa->image, &csa->value)) + error(csa, "numeric constant '%s' out of range\n", + csa->image); + } + else if (csa->c == '+') + csa->token = T_PLUS, add_char(csa); + else if (csa->c == '-') + csa->token = T_MINUS, add_char(csa); + else if (csa->c == ':') + csa->token = T_COLON, add_char(csa); + else if (csa->c == '<') + { csa->token = T_LE, add_char(csa); + if (csa->c == '=') add_char(csa); + } + else if (csa->c == '>') + { csa->token = T_GE, add_char(csa); + if (csa->c == '=') add_char(csa); + } + else if (csa->c == '=') + { csa->token = T_EQ, add_char(csa); + if (csa->c == '<') + csa->token = T_LE, add_char(csa); + else if (csa->c == '>') + csa->token = T_GE, add_char(csa); + } + else + error(csa, "character '%c' not recognized\n", csa->c); + /* skip non-significant characters */ + while (csa->c == ' ') read_char(csa); + return; +} + +static int find_col(struct csa *csa, char *name) +{ /* find column by its symbolic name */ + int j; + j = glp_find_col(csa->P, name); + if (j == 0) + { /* not found; create new column */ + j = glp_add_cols(csa->P, 1); + glp_set_col_name(csa->P, j, name); + /* enlarge working arrays, if necessary */ + if (csa->n_max < j) + { int n_max = csa->n_max; + int *ind = csa->ind; + double *val = csa->val; + char *flag = csa->flag; + double *lb = csa->lb; + double *ub = csa->ub; + csa->n_max += csa->n_max; + csa->ind = xcalloc(1+csa->n_max, sizeof(int)); + memcpy(&csa->ind[1], &ind[1], n_max * sizeof(int)); + xfree(ind); + csa->val = xcalloc(1+csa->n_max, sizeof(double)); + memcpy(&csa->val[1], &val[1], n_max * sizeof(double)); + xfree(val); + csa->flag = xcalloc(1+csa->n_max, sizeof(char)); + memset(&csa->flag[1], 0, csa->n_max * sizeof(char)); + memcpy(&csa->flag[1], &flag[1], n_max * sizeof(char)); + xfree(flag); + csa->lb = xcalloc(1+csa->n_max, sizeof(double)); + memcpy(&csa->lb[1], &lb[1], n_max * sizeof(double)); + xfree(lb); + csa->ub = xcalloc(1+csa->n_max, sizeof(double)); + memcpy(&csa->ub[1], &ub[1], n_max * sizeof(double)); + xfree(ub); + } + csa->lb[j] = +DBL_MAX, csa->ub[j] = -DBL_MAX; + } + return j; +} + +/*********************************************************************** +* parse_linear_form - parse linear form +* +* This routine parses the linear form using the following syntax: +* +* <variable> ::= <symbolic name> +* <coefficient> ::= <numeric constant> +* <term> ::= <variable> | <numeric constant> <variable> +* <linear form> ::= <term> | + <term> | - <term> | +* <linear form> + <term> | <linear form> - <term> +* +* The routine returns the number of terms in the linear form. */ + +static int parse_linear_form(struct csa *csa) +{ int j, k, len = 0, newlen; + double s, coef; +loop: /* parse an optional sign */ + if (csa->token == T_PLUS) + s = +1.0, scan_token(csa); + else if (csa->token == T_MINUS) + s = -1.0, scan_token(csa); + else + s = +1.0; + /* parse an optional coefficient */ + if (csa->token == T_NUMBER) + coef = csa->value, scan_token(csa); + else + coef = 1.0; + /* parse a variable name */ + if (csa->token != T_NAME) + error(csa, "missing variable name\n"); + /* find the corresponding column */ + j = find_col(csa, csa->image); + /* check if the variable is already used in the linear form */ + if (csa->flag[j]) + error(csa, "multiple use of variable '%s' not allowed\n", + csa->image); + /* add new term to the linear form */ + len++, csa->ind[len] = j, csa->val[len] = s * coef; + /* and mark that the variable is used in the linear form */ + csa->flag[j] = 1; + scan_token(csa); + /* if the next token is a sign, there is another term */ + if (csa->token == T_PLUS || csa->token == T_MINUS) goto loop; + /* clear marks of the variables used in the linear form */ + for (k = 1; k <= len; k++) csa->flag[csa->ind[k]] = 0; + /* remove zero coefficients */ + newlen = 0; + for (k = 1; k <= len; k++) + { if (csa->val[k] != 0.0) + { newlen++; + csa->ind[newlen] = csa->ind[k]; + csa->val[newlen] = csa->val[k]; + } + } + return newlen; +} + +/*********************************************************************** +* parse_objective - parse objective function +* +* This routine parses definition of the objective function using the +* following syntax: +* +* <obj sense> ::= minimize | minimum | min | maximize | maximum | max +* <obj name> ::= <empty> | <symbolic name> : +* <obj function> ::= <obj sense> <obj name> <linear form> */ + +static void parse_objective(struct csa *csa) +{ /* parse objective sense */ + int k, len; + /* parse the keyword 'minimize' or 'maximize' */ + if (csa->token == T_MINIMIZE) + glp_set_obj_dir(csa->P, GLP_MIN); + else if (csa->token == T_MAXIMIZE) + glp_set_obj_dir(csa->P, GLP_MAX); + else + xassert(csa != csa); + scan_token(csa); + /* parse objective name */ + if (csa->token == T_NAME && csa->c == ':') + { /* objective name is followed by a colon */ + glp_set_obj_name(csa->P, csa->image); + scan_token(csa); + xassert(csa->token == T_COLON); + scan_token(csa); + } + else + { /* objective name is not specified; use default */ + glp_set_obj_name(csa->P, "obj"); + } + /* parse linear form */ + len = parse_linear_form(csa); + for (k = 1; k <= len; k++) + glp_set_obj_coef(csa->P, csa->ind[k], csa->val[k]); + return; +} + +/*********************************************************************** +* parse_constraints - parse constraints section +* +* This routine parses the constraints section using the following +* syntax: +* +* <row name> ::= <empty> | <symbolic name> : +* <row sense> ::= < | <= | =< | > | >= | => | = +* <right-hand side> ::= <numeric constant> | + <numeric constant> | +* - <numeric constant> +* <constraint> ::= <row name> <linear form> <row sense> +* <right-hand side> +* <subject to> ::= subject to | such that | st | s.t. | st. +* <constraints section> ::= <subject to> <constraint> | +* <constraints section> <constraint> */ + +static void parse_constraints(struct csa *csa) +{ int i, len, type; + double s; + /* parse the keyword 'subject to' */ + xassert(csa->token == T_SUBJECT_TO); + scan_token(csa); +loop: /* create new row (constraint) */ + i = glp_add_rows(csa->P, 1); + /* parse row name */ + if (csa->token == T_NAME && csa->c == ':') + { /* row name is followed by a colon */ + if (glp_find_row(csa->P, csa->image) != 0) + error(csa, "constraint '%s' multiply defined\n", + csa->image); + glp_set_row_name(csa->P, i, csa->image); + scan_token(csa); + xassert(csa->token == T_COLON); + scan_token(csa); + } + else + { /* row name is not specified; use default */ + char name[50]; + sprintf(name, "r.%d", csa->count); + glp_set_row_name(csa->P, i, name); + } + /* parse linear form */ + len = parse_linear_form(csa); + glp_set_mat_row(csa->P, i, len, csa->ind, csa->val); + /* parse constraint sense */ + if (csa->token == T_LE) + type = GLP_UP, scan_token(csa); + else if (csa->token == T_GE) + type = GLP_LO, scan_token(csa); + else if (csa->token == T_EQ) + type = GLP_FX, scan_token(csa); + else + error(csa, "missing constraint sense\n"); + /* parse right-hand side */ + if (csa->token == T_PLUS) + s = +1.0, scan_token(csa); + else if (csa->token == T_MINUS) + s = -1.0, scan_token(csa); + else + s = +1.0; + if (csa->token != T_NUMBER) + error(csa, "missing right-hand side\n"); + glp_set_row_bnds(csa->P, i, type, s * csa->value, s * csa->value); + /* the rest of the current line must be empty */ + if (!(csa->c == '\n' || csa->c == EOF)) + error(csa, "invalid symbol(s) beyond right-hand side\n"); + scan_token(csa); + /* if the next token is a sign, numeric constant, or a symbolic + name, here is another constraint */ + if (csa->token == T_PLUS || csa->token == T_MINUS || + csa->token == T_NUMBER || csa->token == T_NAME) goto loop; + return; +} + +static void set_lower_bound(struct csa *csa, int j, double lb) +{ /* set lower bound of j-th variable */ + if (csa->lb[j] != +DBL_MAX && !csa->lb_warn) + { warning(csa, "lower bound of variable '%s' redefined\n", + glp_get_col_name(csa->P, j)); + csa->lb_warn = 1; + } + csa->lb[j] = lb; + return; +} + +static void set_upper_bound(struct csa *csa, int j, double ub) +{ /* set upper bound of j-th variable */ + if (csa->ub[j] != -DBL_MAX && !csa->ub_warn) + { warning(csa, "upper bound of variable '%s' redefined\n", + glp_get_col_name(csa->P, j)); + csa->ub_warn = 1; + } + csa->ub[j] = ub; + return; +} + +/*********************************************************************** +* parse_bounds - parse bounds section +* +* This routine parses the bounds section using the following syntax: +* +* <variable> ::= <symbolic name> +* <infinity> ::= infinity | inf +* <bound> ::= <numeric constant> | + <numeric constant> | +* - <numeric constant> | + <infinity> | - <infinity> +* <lt> ::= < | <= | =< +* <gt> ::= > | >= | => +* <bound definition> ::= <bound> <lt> <variable> <lt> <bound> | +* <bound> <lt> <variable> | <variable> <lt> <bound> | +* <variable> <gt> <bound> | <variable> = <bound> | <variable> free +* <bounds> ::= bounds | bound +* <bounds section> ::= <bounds> | +* <bounds section> <bound definition> */ + +static void parse_bounds(struct csa *csa) +{ int j, lb_flag; + double lb, s; + /* parse the keyword 'bounds' */ + xassert(csa->token == T_BOUNDS); + scan_token(csa); +loop: /* bound definition can start with a sign, numeric constant, or + a symbolic name */ + if (!(csa->token == T_PLUS || csa->token == T_MINUS || + csa->token == T_NUMBER || csa->token == T_NAME)) goto done; + /* parse bound definition */ + if (csa->token == T_PLUS || csa->token == T_MINUS) + { /* parse signed lower bound */ + lb_flag = 1; + s = (csa->token == T_PLUS ? +1.0 : -1.0); + scan_token(csa); + if (csa->token == T_NUMBER) + lb = s * csa->value, scan_token(csa); + else if (the_same(csa->image, "infinity") || + the_same(csa->image, "inf")) + { if (s > 0.0) + error(csa, "invalid use of '+inf' as lower bound\n"); + lb = -DBL_MAX, scan_token(csa); + } + else + error(csa, "missing lower bound\n"); + } + else if (csa->token == T_NUMBER) + { /* parse unsigned lower bound */ + lb_flag = 1; + lb = csa->value, scan_token(csa); + } + else + { /* lower bound is not specified */ + lb_flag = 0; + } + /* parse the token that should follow the lower bound */ + if (lb_flag) + { if (csa->token != T_LE) + error(csa, "missing '<', '<=', or '=<' after lower bound\n") + ; + scan_token(csa); + } + /* parse variable name */ + if (csa->token != T_NAME) + error(csa, "missing variable name\n"); + j = find_col(csa, csa->image); + /* set lower bound */ + if (lb_flag) set_lower_bound(csa, j, lb); + scan_token(csa); + /* parse the context that follows the variable name */ + if (csa->token == T_LE) + { /* parse upper bound */ + scan_token(csa); + if (csa->token == T_PLUS || csa->token == T_MINUS) + { /* parse signed upper bound */ + s = (csa->token == T_PLUS ? +1.0 : -1.0); + scan_token(csa); + if (csa->token == T_NUMBER) + { set_upper_bound(csa, j, s * csa->value); + scan_token(csa); + } + else if (the_same(csa->image, "infinity") || + the_same(csa->image, "inf")) + { if (s < 0.0) + error(csa, "invalid use of '-inf' as upper bound\n"); + set_upper_bound(csa, j, +DBL_MAX); + scan_token(csa); + } + else + error(csa, "missing upper bound\n"); + } + else if (csa->token == T_NUMBER) + { /* parse unsigned upper bound */ + set_upper_bound(csa, j, csa->value); + scan_token(csa); + } + else + error(csa, "missing upper bound\n"); + } + else if (csa->token == T_GE) + { /* parse lower bound */ + if (lb_flag) + { /* the context '... <= x >= ...' is invalid */ + error(csa, "invalid bound definition\n"); + } + scan_token(csa); + if (csa->token == T_PLUS || csa->token == T_MINUS) + { /* parse signed lower bound */ + s = (csa->token == T_PLUS ? +1.0 : -1.0); + scan_token(csa); + if (csa->token == T_NUMBER) + { set_lower_bound(csa, j, s * csa->value); + scan_token(csa); + } + else if (the_same(csa->image, "infinity") || + the_same(csa->image, "inf") == 0) + { if (s > 0.0) + error(csa, "invalid use of '+inf' as lower bound\n"); + set_lower_bound(csa, j, -DBL_MAX); + scan_token(csa); + } + else + error(csa, "missing lower bound\n"); + } + else if (csa->token == T_NUMBER) + { /* parse unsigned lower bound */ + set_lower_bound(csa, j, csa->value); + scan_token(csa); + } + else + error(csa, "missing lower bound\n"); + } + else if (csa->token == T_EQ) + { /* parse fixed value */ + if (lb_flag) + { /* the context '... <= x = ...' is invalid */ + error(csa, "invalid bound definition\n"); + } + scan_token(csa); + if (csa->token == T_PLUS || csa->token == T_MINUS) + { /* parse signed fixed value */ + s = (csa->token == T_PLUS ? +1.0 : -1.0); + scan_token(csa); + if (csa->token == T_NUMBER) + { set_lower_bound(csa, j, s * csa->value); + set_upper_bound(csa, j, s * csa->value); + scan_token(csa); + } + else + error(csa, "missing fixed value\n"); + } + else if (csa->token == T_NUMBER) + { /* parse unsigned fixed value */ + set_lower_bound(csa, j, csa->value); + set_upper_bound(csa, j, csa->value); + scan_token(csa); + } + else + error(csa, "missing fixed value\n"); + } + else if (the_same(csa->image, "free")) + { /* parse the keyword 'free' */ + if (lb_flag) + { /* the context '... <= x free ...' is invalid */ + error(csa, "invalid bound definition\n"); + } + set_lower_bound(csa, j, -DBL_MAX); + set_upper_bound(csa, j, +DBL_MAX); + scan_token(csa); + } + else if (!lb_flag) + { /* neither lower nor upper bounds are specified */ + error(csa, "invalid bound definition\n"); + } + goto loop; +done: return; +} + +/*********************************************************************** +* parse_integer - parse general, integer, or binary section +* +* <variable> ::= <symbolic name> +* <general> ::= general | generals | gen +* <integer> ::= integer | integers | int +* <binary> ::= binary | binaries | bin +* <section head> ::= <general> <integer> <binary> +* <additional section> ::= <section head> | +* <additional section> <variable> */ + +static void parse_integer(struct csa *csa) +{ int j, binary; + /* parse the keyword 'general', 'integer', or 'binary' */ + if (csa->token == T_GENERAL) + binary = 0, scan_token(csa); + else if (csa->token == T_INTEGER) + binary = 0, scan_token(csa); + else if (csa->token == T_BINARY) + binary = 1, scan_token(csa); + else + xassert(csa != csa); + /* parse list of variables (may be empty) */ + while (csa->token == T_NAME) + { /* find the corresponding column */ + j = find_col(csa, csa->image); + /* change kind of the variable */ + glp_set_col_kind(csa->P, j, GLP_IV); + /* set bounds for the binary variable */ + if (binary) +#if 0 /* 07/VIII-2013 */ + { set_lower_bound(csa, j, 0.0); + set_upper_bound(csa, j, 1.0); + } +#else + { set_lower_bound(csa, j, + csa->lb[j] == +DBL_MAX ? 0.0 : csa->lb[j]); + set_upper_bound(csa, j, + csa->ub[j] == -DBL_MAX ? 1.0 : csa->ub[j]); + } +#endif + scan_token(csa); + } + return; +} + +int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname) +{ /* read problem data in CPLEX LP format */ + glp_cpxcp _parm; + struct csa _csa, *csa = &_csa; + int ret; + xprintf("Reading problem data from '%s'...\n", fname); + if (parm == NULL) + glp_init_cpxcp(&_parm), parm = &_parm; + /* check control parameters */ + check_parm("glp_read_lp", parm); + /* initialize common storage area */ + csa->P = P; + csa->parm = parm; + csa->fname = fname; + csa->fp = NULL; + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->count = 0; + csa->c = '\n'; + csa->token = T_EOF; + csa->image[0] = '\0'; + csa->imlen = 0; + csa->value = 0.0; + csa->n_max = 100; + csa->ind = xcalloc(1+csa->n_max, sizeof(int)); + csa->val = xcalloc(1+csa->n_max, sizeof(double)); + csa->flag = xcalloc(1+csa->n_max, sizeof(char)); + memset(&csa->flag[1], 0, csa->n_max * sizeof(char)); + csa->lb = xcalloc(1+csa->n_max, sizeof(double)); + csa->ub = xcalloc(1+csa->n_max, sizeof(double)); +#if 1 /* 27/VII-2013 */ + csa->lb_warn = csa->ub_warn = 0; +#endif + /* erase problem object */ + glp_erase_prob(P); + glp_create_index(P); + /* open input CPLEX LP file */ + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* scan very first token */ + scan_token(csa); + /* parse definition of the objective function */ + if (!(csa->token == T_MINIMIZE || csa->token == T_MAXIMIZE)) + error(csa, "'minimize' or 'maximize' keyword missing\n"); + parse_objective(csa); + /* parse constraints section */ + if (csa->token != T_SUBJECT_TO) + error(csa, "constraints section missing\n"); + parse_constraints(csa); + /* parse optional bounds section */ + if (csa->token == T_BOUNDS) parse_bounds(csa); + /* parse optional general, integer, and binary sections */ + while (csa->token == T_GENERAL || + csa->token == T_INTEGER || + csa->token == T_BINARY) parse_integer(csa); + /* check for the keyword 'end' */ + if (csa->token == T_END) + scan_token(csa); + else if (csa->token == T_EOF) + warning(csa, "keyword 'end' missing\n"); + else + error(csa, "symbol '%s' in wrong position\n", csa->image); + /* nothing must follow the keyword 'end' (except comments) */ + if (csa->token != T_EOF) + error(csa, "extra symbol(s) detected beyond 'end'\n"); + /* set bounds of variables */ + { int j, type; + double lb, ub; + for (j = 1; j <= P->n; j++) + { lb = csa->lb[j]; + ub = csa->ub[j]; + if (lb == +DBL_MAX) lb = 0.0; /* default lb */ + if (ub == -DBL_MAX) ub = +DBL_MAX; /* default ub */ + if (lb == -DBL_MAX && ub == +DBL_MAX) + type = GLP_FR; + else if (ub == +DBL_MAX) + type = GLP_LO; + else if (lb == -DBL_MAX) + type = GLP_UP; + else if (lb != ub) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(csa->P, j, type, lb, ub); + } + } + /* print some statistics */ + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", + P->nnz, P->nnz == 1 ? "" : "s"); + if (glp_get_num_int(P) > 0) + { int ni = glp_get_num_int(P); + int nb = glp_get_num_bin(P); + if (ni == 1) + { if (nb == 0) + xprintf("One variable is integer\n"); + else + xprintf("One variable is binary\n"); + } + else + { xprintf("%d integer variables, ", ni); + if (nb == 0) + xprintf("none"); + else if (nb == 1) + xprintf("one"); + else if (nb == ni) + xprintf("all"); + else + xprintf("%d", nb); + xprintf(" of which %s binary\n", nb == 1 ? "is" : "are"); + } + } + xprintf("%d lines were read\n", csa->count); + /* problem data has been successfully read */ + glp_delete_index(P); + glp_sort_matrix(P); + ret = 0; +done: if (csa->fp != NULL) glp_close(csa->fp); + xfree(csa->ind); + xfree(csa->val); + xfree(csa->flag); + xfree(csa->lb); + xfree(csa->ub); + if (ret != 0) glp_erase_prob(P); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_lp - write problem data in CPLEX LP format +* +* SYNOPSIS +* +* int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char +* *fname); +* +* DESCRIPTION +* +* The routine glp_write_lp writes problem data in CPLEX LP format to +* a text file. +* +* The parameter parm is a pointer to the structure glp_cpxcp, which +* specifies control parameters used by the routine. If parm is NULL, +* the routine uses default settings. +* +* The character string fname specifies a name of the text file to be +* written. +* +* RETURNS +* +* If the operation was successful, the routine glp_write_lp returns +* zero. Otherwise, it prints an error message and returns non-zero. */ + +#define csa csa1 + +struct csa +{ /* common storage area */ + glp_prob *P; + /* pointer to problem object */ + const glp_cpxcp *parm; + /* pointer to control parameters */ +}; + +static int check_name(char *name) +{ /* check if specified name is valid for CPLEX LP format */ + if (*name == '.') return 1; + if (isdigit((unsigned char)*name)) return 1; + for (; *name; name++) + { if (!isalnum((unsigned char)*name) && + strchr(CHAR_SET, (unsigned char)*name) == NULL) return 1; + } + return 0; /* name is ok */ +} + +static void adjust_name(char *name) +{ /* attempt to adjust specified name to make it valid for CPLEX LP + format */ + for (; *name; name++) + { if (*name == ' ') + *name = '_'; + else if (*name == '-') + *name = '~'; + else if (*name == '[') + *name = '('; + else if (*name == ']') + *name = ')'; + } + return; +} + +static char *row_name(struct csa *csa, int i, char rname[255+1]) +{ /* construct symbolic name of i-th row (constraint) */ + const char *name; + if (i == 0) + name = glp_get_obj_name(csa->P); + else + name = glp_get_row_name(csa->P, i); + if (name == NULL) goto fake; + strcpy(rname, name); + adjust_name(rname); + if (check_name(rname)) goto fake; + return rname; +fake: if (i == 0) + strcpy(rname, "obj"); + else + sprintf(rname, "r_%d", i); + return rname; +} + +static char *col_name(struct csa *csa, int j, char cname[255+1]) +{ /* construct symbolic name of j-th column (variable) */ + const char *name; + name = glp_get_col_name(csa->P, j); + if (name == NULL) goto fake; + strcpy(cname, name); + adjust_name(cname); + if (check_name(cname)) goto fake; + return cname; +fake: sprintf(cname, "x_%d", j); + return cname; +} + +int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname) +{ /* write problem data in CPLEX LP format */ + glp_cpxcp _parm; + struct csa _csa, *csa = &_csa; + glp_file *fp; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, j, len, flag, count, ret; + char line[1000+1], term[500+1], name[255+1]; + xprintf("Writing problem data to '%s'...\n", fname); + if (parm == NULL) + glp_init_cpxcp(&_parm), parm = &_parm; + /* check control parameters */ + check_parm("glp_write_lp", parm); + /* initialize common storage area */ + csa->P = P; + csa->parm = parm; + /* create output CPLEX LP file */ + fp = glp_open(fname, "w"), count = 0; + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* write problem name */ + xfprintf(fp, "\\* Problem: %s *\\\n", + P->name == NULL ? "Unknown" : P->name), count++; + xfprintf(fp, "\n"), count++; + /* the problem should contain at least one row and one column */ + if (!(P->m > 0 && P->n > 0)) + { xprintf("Warning: problem has no rows/columns\n"); + xfprintf(fp, "\\* WARNING: PROBLEM HAS NO ROWS/COLUMNS *\\\n"), + count++; + xfprintf(fp, "\n"), count++; + goto skip; + } + /* write the objective function definition */ + if (P->dir == GLP_MIN) + xfprintf(fp, "Minimize\n"), count++; + else if (P->dir == GLP_MAX) + xfprintf(fp, "Maximize\n"), count++; + else + xassert(P != P); + row_name(csa, 0, name); + sprintf(line, " %s:", name); + len = 0; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->coef != 0.0 || col->ptr == NULL) + { len++; + col_name(csa, j, name); + if (col->coef == 0.0) + sprintf(term, " + 0 %s", name); /* empty column */ + else if (col->coef == +1.0) + sprintf(term, " + %s", name); + else if (col->coef == -1.0) + sprintf(term, " - %s", name); + else if (col->coef > 0.0) + sprintf(term, " + %.*g %s", DBL_DIG, +col->coef, name); + else + sprintf(term, " - %.*g %s", DBL_DIG, -col->coef, name); + if (strlen(line) + strlen(term) > 72) + xfprintf(fp, "%s\n", line), line[0] = '\0', count++; + strcat(line, term); + } + } + if (len == 0) + { /* empty objective */ + sprintf(term, " 0 %s", col_name(csa, 1, name)); + strcat(line, term); + } + xfprintf(fp, "%s\n", line), count++; + if (P->c0 != 0.0) + xfprintf(fp, "\\* constant term = %.*g *\\\n", DBL_DIG, P->c0), + count++; + xfprintf(fp, "\n"), count++; + /* write the constraints section */ + xfprintf(fp, "Subject To\n"), count++; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->type == GLP_FR) continue; /* skip free row */ + row_name(csa, i, name); + sprintf(line, " %s:", name); + /* linear form */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col_name(csa, aij->col->j, name); + if (aij->val == +1.0) + sprintf(term, " + %s", name); + else if (aij->val == -1.0) + sprintf(term, " - %s", name); + else if (aij->val > 0.0) + sprintf(term, " + %.*g %s", DBL_DIG, +aij->val, name); + else + sprintf(term, " - %.*g %s", DBL_DIG, -aij->val, name); + if (strlen(line) + strlen(term) > 72) + xfprintf(fp, "%s\n", line), line[0] = '\0', count++; + strcat(line, term); + } + if (row->type == GLP_DB) + { /* double-bounded (ranged) constraint */ + sprintf(term, " - ~r_%d", i); + if (strlen(line) + strlen(term) > 72) + xfprintf(fp, "%s\n", line), line[0] = '\0', count++; + strcat(line, term); + } + else if (row->ptr == NULL) + { /* empty constraint */ + sprintf(term, " 0 %s", col_name(csa, 1, name)); + strcat(line, term); + } + /* right hand-side */ + if (row->type == GLP_LO) + sprintf(term, " >= %.*g", DBL_DIG, row->lb); + else if (row->type == GLP_UP) + sprintf(term, " <= %.*g", DBL_DIG, row->ub); + else if (row->type == GLP_DB || row->type == GLP_FX) + sprintf(term, " = %.*g", DBL_DIG, row->lb); + else + xassert(row != row); + if (strlen(line) + strlen(term) > 72) + xfprintf(fp, "%s\n", line), line[0] = '\0', count++; + strcat(line, term); + xfprintf(fp, "%s\n", line), count++; + } + xfprintf(fp, "\n"), count++; + /* write the bounds section */ + flag = 0; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->type != GLP_DB) continue; + if (!flag) + xfprintf(fp, "Bounds\n"), flag = 1, count++; + xfprintf(fp, " 0 <= ~r_%d <= %.*g\n", + i, DBL_DIG, row->ub - row->lb), count++; + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->type == GLP_LO && col->lb == 0.0) continue; + if (!flag) + xfprintf(fp, "Bounds\n"), flag = 1, count++; + col_name(csa, j, name); + if (col->type == GLP_FR) + xfprintf(fp, " %s free\n", name), count++; + else if (col->type == GLP_LO) + xfprintf(fp, " %s >= %.*g\n", + name, DBL_DIG, col->lb), count++; + else if (col->type == GLP_UP) + xfprintf(fp, " -Inf <= %s <= %.*g\n", + name, DBL_DIG, col->ub), count++; + else if (col->type == GLP_DB) + xfprintf(fp, " %.*g <= %s <= %.*g\n", + DBL_DIG, col->lb, name, DBL_DIG, col->ub), count++; + else if (col->type == GLP_FX) + xfprintf(fp, " %s = %.*g\n", + name, DBL_DIG, col->lb), count++; + else + xassert(col != col); + } + if (flag) xfprintf(fp, "\n"), count++; + /* write the integer section */ + flag = 0; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->kind == GLP_CV) continue; + xassert(col->kind == GLP_IV); + if (!flag) + xfprintf(fp, "Generals\n"), flag = 1, count++; + xfprintf(fp, " %s\n", col_name(csa, j, name)), count++; + } + if (flag) xfprintf(fp, "\n"), count++; +skip: /* write the end keyword */ + xfprintf(fp, "End\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* problem data has been successfully written */ + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpdmx.c b/resources/3rdparty/glpk-4.53/src/glpdmx.c new file mode 100644 index 000000000..329baaf69 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpdmx.c @@ -0,0 +1,1693 @@ +/* glpdmx.c (reading/writing data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "misc.h" +#include "prob.h" + +#define xfprintf glp_format + +struct csa +{ /* common storage area */ + jmp_buf jump; + /* label for go to in case of error */ + const char *fname; + /* name of input text file */ + glp_file *fp; + /* stream assigned to input text file */ + int count; + /* line count */ + int c; + /* current character */ + char field[255+1]; + /* data field */ + int empty; + /* warning 'empty line ignored' was printed */ + int nonint; + /* warning 'non-integer data detected' was printed */ +}; + +static void error(struct csa *csa, const char *fmt, ...) +{ /* print error message and terminate processing */ + va_list arg; + xprintf("%s:%d: error: ", csa->fname, csa->count); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + xprintf("\n"); + longjmp(csa->jump, 1); + /* no return */ +} + +static void warning(struct csa *csa, const char *fmt, ...) +{ /* print warning message and continue processing */ + va_list arg; + xprintf("%s:%d: warning: ", csa->fname, csa->count); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + xprintf("\n"); + return; +} + +static void read_char(struct csa *csa) +{ /* read character from input text file */ + int c; + if (csa->c == '\n') csa->count++; + c = glp_getc(csa->fp); + if (c < 0) + { if (glp_ioerr(csa->fp)) + error(csa, "read error - %s", get_err_msg()); + else if (csa->c == '\n') + error(csa, "unexpected end of file"); + else + { warning(csa, "missing final end of line"); + c = '\n'; + } + } + else if (c == '\n') + ; + else if (isspace(c)) + c = ' '; + else if (iscntrl(c)) + error(csa, "invalid control character 0x%02X", c); + csa->c = c; + return; +} + +static void read_designator(struct csa *csa) +{ /* read one-character line designator */ + xassert(csa->c == '\n'); + read_char(csa); + for (;;) + { /* skip preceding white-space characters */ + while (csa->c == ' ') + read_char(csa); + if (csa->c == '\n') + { /* ignore empty line */ + if (!csa->empty) + { warning(csa, "empty line ignored"); + csa->empty = 1; + } + read_char(csa); + } + else if (csa->c == 'c') + { /* skip comment line */ + while (csa->c != '\n') + read_char(csa); + read_char(csa); + } + else + { /* hmm... looks like a line designator */ + csa->field[0] = (char)csa->c, csa->field[1] = '\0'; + /* check that it is followed by a white-space character */ + read_char(csa); + if (!(csa->c == ' ' || csa->c == '\n')) + error(csa, "line designator missing or invalid"); + break; + } + } + return; +} + +static void read_field(struct csa *csa) +{ /* read data field */ + int len = 0; + /* skip preceding white-space characters */ + while (csa->c == ' ') + read_char(csa); + /* scan data field */ + if (csa->c == '\n') + error(csa, "unexpected end of line"); + while (!(csa->c == ' ' || csa->c == '\n')) + { if (len == sizeof(csa->field)-1) + error(csa, "data field `%.15s...' too long", csa->field); + csa->field[len++] = (char)csa->c; + read_char(csa); + } + csa->field[len] = '\0'; + return; +} + +static void end_of_line(struct csa *csa) +{ /* skip white-space characters until end of line */ + while (csa->c == ' ') + read_char(csa); + if (csa->c != '\n') + error(csa, "too many data fields specified"); + return; +} + +static void check_int(struct csa *csa, double num) +{ /* print a warning if non-integer data are detected */ + if (!csa->nonint && num != floor(num)) + { warning(csa, "non-integer data detected"); + csa->nonint = 1; + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_read_mincost - read min-cost flow problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, +* int a_cost, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_mincost reads minimum cost flow problem data in +* DIMACS format from a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname) +{ struct csa _csa, *csa = &_csa; + glp_vertex *v; + glp_arc *a; + int i, j, k, nv, na, ret = 0; + double rhs, low, cap, cost; + char *flag = NULL; + if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_read_mincost: v_rhs = %d; invalid offset\n", + v_rhs); + if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) + xerror("glp_read_mincost: a_low = %d; invalid offset\n", + a_low); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_read_mincost: a_cap = %d; invalid offset\n", + a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_read_mincost: a_cost = %d; invalid offset\n", + a_cost); + glp_erase_graph(G, G->v_size, G->a_size); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading min-cost flow problem data from `%s'...\n", + fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "min") != 0) + error(csa, "wrong problem designator; `min' expected"); + read_field(csa); + if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) + error(csa, "number of nodes missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &na) == 0 && na >= 0)) + error(csa, "number of arcs missing or invalid"); + xprintf("Flow network has %d node%s and %d arc%s\n", + nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s"); + if (nv > 0) glp_add_vertices(G, nv); + end_of_line(csa); + /* read node descriptor lines */ + flag = xcalloc(1+nv, sizeof(char)); + memset(&flag[1], 0, nv * sizeof(char)); + if (v_rhs >= 0) + { rhs = 0.0; + for (i = 1; i <= nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_rhs, &rhs, sizeof(double)); + } + } + for (;;) + { read_designator(csa); + if (strcmp(csa->field, "n") != 0) break; + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "node number %d out of range", i); + if (flag[i]) + error(csa, "duplicate descriptor of node %d", i); + read_field(csa); + if (str2num(csa->field, &rhs) != 0) + error(csa, "node supply/demand missing or invalid"); + check_int(csa, rhs); + if (v_rhs >= 0) + { v = G->v[i]; + memcpy((char *)v->data + v_rhs, &rhs, sizeof(double)); + } + flag[i] = 1; + end_of_line(csa); + } + xfree(flag), flag = NULL; + /* read arc descriptor lines */ + for (k = 1; k <= na; k++) + { if (k > 1) read_designator(csa); + if (strcmp(csa->field, "a") != 0) + error(csa, "wrong line designator; `a' expected"); + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "starting node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "starting node number %d out of range", i); + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "ending node number missing or invalid"); + if (!(1 <= j && j <= nv)) + error(csa, "ending node number %d out of range", j); + read_field(csa); + if (!(str2num(csa->field, &low) == 0 && low >= 0.0)) + error(csa, "lower bound of arc flow missing or invalid"); + check_int(csa, low); + read_field(csa); + if (!(str2num(csa->field, &cap) == 0 && cap >= low)) + error(csa, "upper bound of arc flow missing or invalid"); + check_int(csa, cap); + read_field(csa); + if (str2num(csa->field, &cost) != 0) + error(csa, "per-unit cost of arc flow missing or invalid"); + check_int(csa, cost); + a = glp_add_arc(G, i, j); + if (a_low >= 0) + memcpy((char *)a->data + a_low, &low, sizeof(double)); + if (a_cap >= 0) + memcpy((char *)a->data + a_cap, &cap, sizeof(double)); + if (a_cost >= 0) + memcpy((char *)a->data + a_cost, &cost, sizeof(double)); + end_of_line(csa); + } + xprintf("%d lines were read\n", csa->count); +done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); + if (csa->fp != NULL) glp_close(csa->fp); + if (flag != NULL) xfree(flag); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_mincost - write min-cost flow problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, +* int a_cost, const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_mincost writes minimum cost flow problem data +* in DIMACS format to a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname) +{ glp_file *fp; + glp_vertex *v; + glp_arc *a; + int i, count = 0, ret; + double rhs, low, cap, cost; + if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_write_mincost: v_rhs = %d; invalid offset\n", + v_rhs); + if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) + xerror("glp_write_mincost: a_low = %d; invalid offset\n", + a_low); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_write_mincost: a_cap = %d; invalid offset\n", + a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_write_mincost: a_cost = %d; invalid offset\n", + a_cost); + xprintf("Writing min-cost flow problem data to `%s'...\n", + fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "c %s\n", + G->name == NULL ? "unknown" : G->name), count++; + xfprintf(fp, "p min %d %d\n", G->nv, G->na), count++; + if (v_rhs >= 0) + { for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double)); + if (rhs != 0.0) + xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, rhs), count++; + } + } + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { if (a_low >= 0) + memcpy(&low, (char *)a->data + a_low, sizeof(double)); + else + low = 0.0; + if (a_cap >= 0) + memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); + else + cap = 1.0; + if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 0.0; + xfprintf(fp, "a %d %d %.*g %.*g %.*g\n", + a->tail->i, a->head->i, DBL_DIG, low, DBL_DIG, cap, + DBL_DIG, cost), count++; + } + } + xfprintf(fp, "c eof\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_read_maxflow - read maximum flow problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_maxflow reads maximum flow problem data in +* DIMACS format from a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap, + const char *fname) +{ struct csa _csa, *csa = &_csa; + glp_arc *a; + int i, j, k, s, t, nv, na, ret = 0; + double cap; + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_read_maxflow: a_cap = %d; invalid offset\n", + a_cap); + glp_erase_graph(G, G->v_size, G->a_size); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading maximum flow problem data from `%s'...\n", + fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "max") != 0) + error(csa, "wrong problem designator; `max' expected"); + read_field(csa); + if (!(str2int(csa->field, &nv) == 0 && nv >= 2)) + error(csa, "number of nodes missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &na) == 0 && na >= 0)) + error(csa, "number of arcs missing or invalid"); + xprintf("Flow network has %d node%s and %d arc%s\n", + nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s"); + if (nv > 0) glp_add_vertices(G, nv); + end_of_line(csa); + /* read node descriptor lines */ + s = t = 0; + for (;;) + { read_designator(csa); + if (strcmp(csa->field, "n") != 0) break; + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "node number %d out of range", i); + read_field(csa); + if (strcmp(csa->field, "s") == 0) + { if (s > 0) + error(csa, "only one source node allowed"); + s = i; + } + else if (strcmp(csa->field, "t") == 0) + { if (t > 0) + error(csa, "only one sink node allowed"); + t = i; + } + else + error(csa, "wrong node designator; `s' or `t' expected"); + if (s > 0 && s == t) + error(csa, "source and sink nodes must be distinct"); + end_of_line(csa); + } + if (s == 0) + error(csa, "source node descriptor missing\n"); + if (t == 0) + error(csa, "sink node descriptor missing\n"); + if (_s != NULL) *_s = s; + if (_t != NULL) *_t = t; + /* read arc descriptor lines */ + for (k = 1; k <= na; k++) + { if (k > 1) read_designator(csa); + if (strcmp(csa->field, "a") != 0) + error(csa, "wrong line designator; `a' expected"); + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "starting node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "starting node number %d out of range", i); + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "ending node number missing or invalid"); + if (!(1 <= j && j <= nv)) + error(csa, "ending node number %d out of range", j); + read_field(csa); + if (!(str2num(csa->field, &cap) == 0 && cap >= 0.0)) + error(csa, "arc capacity missing or invalid"); + check_int(csa, cap); + a = glp_add_arc(G, i, j); + if (a_cap >= 0) + memcpy((char *)a->data + a_cap, &cap, sizeof(double)); + end_of_line(csa); + } + xprintf("%d lines were read\n", csa->count); +done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); + if (csa->fp != NULL) glp_close(csa->fp); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_maxflow - write maximum flow problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_maxflow writes maximum flow problem data in +* DIMACS format to a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, + const char *fname) +{ glp_file *fp; + glp_vertex *v; + glp_arc *a; + int i, count = 0, ret; + double cap; + if (!(1 <= s && s <= G->nv)) + xerror("glp_write_maxflow: s = %d; source node number out of r" + "ange\n", s); + if (!(1 <= t && t <= G->nv)) + xerror("glp_write_maxflow: t = %d: sink node number out of ran" + "ge\n", t); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_write_mincost: a_cap = %d; invalid offset\n", + a_cap); + xprintf("Writing maximum flow problem data to `%s'...\n", + fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "c %s\n", + G->name == NULL ? "unknown" : G->name), count++; + xfprintf(fp, "p max %d %d\n", G->nv, G->na), count++; + xfprintf(fp, "n %d s\n", s), count++; + xfprintf(fp, "n %d t\n", t), count++; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { if (a_cap >= 0) + memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); + else + cap = 1.0; + xfprintf(fp, "a %d %d %.*g\n", + a->tail->i, a->head->i, DBL_DIG, cap), count++; + } + } + xfprintf(fp, "c eof\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_read_asnprob - read assignment problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_asnprob reads assignment problem data in DIMACS +* format from a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char + *fname) +{ struct csa _csa, *csa = &_csa; + glp_vertex *v; + glp_arc *a; + int nv, na, n1, i, j, k, ret = 0; + double cost; + char *flag = NULL; + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_read_asnprob: v_set = %d; invalid offset\n", + v_set); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_read_asnprob: a_cost = %d; invalid offset\n", + a_cost); + glp_erase_graph(G, G->v_size, G->a_size); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading assignment problem data from `%s'...\n", fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "asn") != 0) + error(csa, "wrong problem designator; `asn' expected"); + read_field(csa); + if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) + error(csa, "number of nodes missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &na) == 0 && na >= 0)) + error(csa, "number of arcs missing or invalid"); + if (nv > 0) glp_add_vertices(G, nv); + end_of_line(csa); + /* read node descriptor lines */ + flag = xcalloc(1+nv, sizeof(char)); + memset(&flag[1], 0, nv * sizeof(char)); + n1 = 0; + for (;;) + { read_designator(csa); + if (strcmp(csa->field, "n") != 0) break; + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "node number %d out of range", i); + if (flag[i]) + error(csa, "duplicate descriptor of node %d", i); + flag[i] = 1, n1++; + end_of_line(csa); + } + xprintf( + "Assignment problem has %d + %d = %d node%s and %d arc%s\n", + n1, nv - n1, nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s"); + if (v_set >= 0) + { for (i = 1; i <= nv; i++) + { v = G->v[i]; + k = (flag[i] ? 0 : 1); + memcpy((char *)v->data + v_set, &k, sizeof(int)); + } + } + /* read arc descriptor lines */ + for (k = 1; k <= na; k++) + { if (k > 1) read_designator(csa); + if (strcmp(csa->field, "a") != 0) + error(csa, "wrong line designator; `a' expected"); + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "starting node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "starting node number %d out of range", i); + if (!flag[i]) + error(csa, "node %d cannot be a starting node", i); + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "ending node number missing or invalid"); + if (!(1 <= j && j <= nv)) + error(csa, "ending node number %d out of range", j); + if (flag[j]) + error(csa, "node %d cannot be an ending node", j); + read_field(csa); + if (str2num(csa->field, &cost) != 0) + error(csa, "arc cost missing or invalid"); + check_int(csa, cost); + a = glp_add_arc(G, i, j); + if (a_cost >= 0) + memcpy((char *)a->data + a_cost, &cost, sizeof(double)); + end_of_line(csa); + } + xprintf("%d lines were read\n", csa->count); +done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); + if (csa->fp != NULL) glp_close(csa->fp); + if (flag != NULL) xfree(flag); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_asnprob - write assignment problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_asnprob writes assignment problem data in +* DIMACS format to a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char + *fname) +{ glp_file *fp; + glp_vertex *v; + glp_arc *a; + int i, k, count = 0, ret; + double cost; + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_write_asnprob: v_set = %d; invalid offset\n", + v_set); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_write_asnprob: a_cost = %d; invalid offset\n", + a_cost); + xprintf("Writing assignment problem data to `%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "c %s\n", + G->name == NULL ? "unknown" : G->name), count++; + xfprintf(fp, "p asn %d %d\n", G->nv, G->na), count++; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (v_set >= 0) + memcpy(&k, (char *)v->data + v_set, sizeof(int)); + else + k = (v->out != NULL ? 0 : 1); + if (k == 0) + xfprintf(fp, "n %d\n", i), count++; + } + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 1.0; + xfprintf(fp, "a %d %d %.*g\n", + a->tail->i, a->head->i, DBL_DIG, cost), count++; + } + } + xfprintf(fp, "c eof\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_read_ccdata - read graph in DIMACS clique/coloring format +* +* SYNOPSIS +* +* int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_ccdata reads an (undirected) graph in DIMACS +* clique/coloring format from a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname) +{ struct csa _csa, *csa = &_csa; + glp_vertex *v; + int i, j, k, nv, ne, ret = 0; + double w; + char *flag = NULL; + if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) + xerror("glp_read_ccdata: v_wgt = %d; invalid offset\n", + v_wgt); + glp_erase_graph(G, G->v_size, G->a_size); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading graph from `%s'...\n", fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "edge") != 0) + error(csa, "wrong problem designator; `edge' expected"); + read_field(csa); + if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) + error(csa, "number of vertices missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &ne) == 0 && ne >= 0)) + error(csa, "number of edges missing or invalid"); + xprintf("Graph has %d vert%s and %d edge%s\n", + nv, nv == 1 ? "ex" : "ices", ne, ne == 1 ? "" : "s"); + if (nv > 0) glp_add_vertices(G, nv); + end_of_line(csa); + /* read node descriptor lines */ + flag = xcalloc(1+nv, sizeof(char)); + memset(&flag[1], 0, nv * sizeof(char)); + if (v_wgt >= 0) + { w = 1.0; + for (i = 1; i <= nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_wgt, &w, sizeof(double)); + } + } + for (;;) + { read_designator(csa); + if (strcmp(csa->field, "n") != 0) break; + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "vertex number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "vertex number %d out of range", i); + if (flag[i]) + error(csa, "duplicate descriptor of vertex %d", i); + read_field(csa); + if (str2num(csa->field, &w) != 0) + error(csa, "vertex weight missing or invalid"); + check_int(csa, w); + if (v_wgt >= 0) + { v = G->v[i]; + memcpy((char *)v->data + v_wgt, &w, sizeof(double)); + } + flag[i] = 1; + end_of_line(csa); + } + xfree(flag), flag = NULL; + /* read edge descriptor lines */ + for (k = 1; k <= ne; k++) + { if (k > 1) read_designator(csa); + if (strcmp(csa->field, "e") != 0) + error(csa, "wrong line designator; `e' expected"); + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "first vertex number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "first vertex number %d out of range", i); + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "second vertex number missing or invalid"); + if (!(1 <= j && j <= nv)) + error(csa, "second vertex number %d out of range", j); + glp_add_arc(G, i, j); + end_of_line(csa); + } + xprintf("%d lines were read\n", csa->count); +done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); + if (csa->fp != NULL) glp_close(csa->fp); + if (flag != NULL) xfree(flag); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_ccdata - write graph in DIMACS clique/coloring format +* +* SYNOPSIS +* +* int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_ccdata writes the specified graph in DIMACS +* clique/coloring format to a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname) +{ glp_file *fp; + glp_vertex *v; + glp_arc *e; + int i, count = 0, ret; + double w; + if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) + xerror("glp_write_ccdata: v_wgt = %d; invalid offset\n", + v_wgt); + xprintf("Writing graph to `%s'\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "c %s\n", + G->name == NULL ? "unknown" : G->name), count++; + xfprintf(fp, "p edge %d %d\n", G->nv, G->na), count++; + if (v_wgt >= 0) + { for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + memcpy(&w, (char *)v->data + v_wgt, sizeof(double)); + if (w != 1.0) + xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, w), count++; + } + } + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (e = v->out; e != NULL; e = e->t_next) + xfprintf(fp, "e %d %d\n", e->tail->i, e->head->i), count++; + } + xfprintf(fp, "c eof\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_read_prob - read problem data in GLPK format +* +* SYNOPSIS +* +* int glp_read_prob(glp_prob *P, int flags, const char *fname); +* +* The routine glp_read_prob reads problem data in GLPK LP/MIP format +* from a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_prob(glp_prob *P, int flags, const char *fname) +{ struct csa _csa, *csa = &_csa; + int mip, m, n, nnz, ne, i, j, k, type, kind, ret, *ln = NULL, + *ia = NULL, *ja = NULL; + double lb, ub, temp, *ar = NULL; + char *rf = NULL, *cf = NULL; + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_read_prob: P = %p; invalid problem object\n", + P); + if (flags != 0) + xerror("glp_read_prob: flags = %d; invalid parameter\n", + flags); + if (fname == NULL) + xerror("glp_read_prob: fname = %d; invalid parameter\n", + fname); + glp_erase_prob(P); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading problem data from `%s'...\n", fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "lp") == 0) + mip = 0; + else if (strcmp(csa->field, "mip") == 0) + mip = 1; + else + error(csa, "wrong problem designator; `lp' or `mip' expected\n" + ); + read_field(csa); + if (strcmp(csa->field, "min") == 0) + glp_set_obj_dir(P, GLP_MIN); + else if (strcmp(csa->field, "max") == 0) + glp_set_obj_dir(P, GLP_MAX); + else + error(csa, "objective sense missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &m) == 0 && m >= 0)) + error(csa, "number of rows missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &n) == 0 && n >= 0)) + error(csa, "number of columns missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &nnz) == 0 && nnz >= 0)) + error(csa, "number of constraint coefficients missing or inval" + "id"); + if (m > 0) + { glp_add_rows(P, m); + for (i = 1; i <= m; i++) + glp_set_row_bnds(P, i, GLP_FX, 0.0, 0.0); + } + if (n > 0) + { glp_add_cols(P, n); + for (j = 1; j <= n; j++) + { if (!mip) + glp_set_col_bnds(P, j, GLP_LO, 0.0, 0.0); + else + glp_set_col_kind(P, j, GLP_BV); + } + } + end_of_line(csa); + /* allocate working arrays */ + rf = xcalloc(1+m, sizeof(char)); + memset(rf, 0, 1+m); + cf = xcalloc(1+n, sizeof(char)); + memset(cf, 0, 1+n); + ln = xcalloc(1+nnz, sizeof(int)); + ia = xcalloc(1+nnz, sizeof(int)); + ja = xcalloc(1+nnz, sizeof(int)); + ar = xcalloc(1+nnz, sizeof(double)); + /* read descriptor lines */ + ne = 0; + for (;;) + { read_designator(csa); + if (strcmp(csa->field, "i") == 0) + { /* row descriptor */ + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "row number missing or invalid"); + if (!(1 <= i && i <= m)) + error(csa, "row number out of range"); + read_field(csa); + if (strcmp(csa->field, "f") == 0) + type = GLP_FR; + else if (strcmp(csa->field, "l") == 0) + type = GLP_LO; + else if (strcmp(csa->field, "u") == 0) + type = GLP_UP; + else if (strcmp(csa->field, "d") == 0) + type = GLP_DB; + else if (strcmp(csa->field, "s") == 0) + type = GLP_FX; + else + error(csa, "row type missing or invalid"); + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { read_field(csa); + if (str2num(csa->field, &lb) != 0) + error(csa, "row lower bound/fixed value missing or in" + "valid"); + } + else + lb = 0.0; + if (type == GLP_UP || type == GLP_DB) + { read_field(csa); + if (str2num(csa->field, &ub) != 0) + error(csa, "row upper bound missing or invalid"); + } + else + ub = 0.0; + if (rf[i] & 0x01) + error(csa, "duplicate row descriptor"); + glp_set_row_bnds(P, i, type, lb, ub), rf[i] |= 0x01; + } + else if (strcmp(csa->field, "j") == 0) + { /* column descriptor */ + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "column number missing or invalid"); + if (!(1 <= j && j <= n)) + error(csa, "column number out of range"); + if (!mip) + kind = GLP_CV; + else + { read_field(csa); + if (strcmp(csa->field, "c") == 0) + kind = GLP_CV; + else if (strcmp(csa->field, "i") == 0) + kind = GLP_IV; + else if (strcmp(csa->field, "b") == 0) + { kind = GLP_IV; + type = GLP_DB, lb = 0.0, ub = 1.0; + goto skip; + } + else + error(csa, "column kind missing or invalid"); + } + read_field(csa); + if (strcmp(csa->field, "f") == 0) + type = GLP_FR; + else if (strcmp(csa->field, "l") == 0) + type = GLP_LO; + else if (strcmp(csa->field, "u") == 0) + type = GLP_UP; + else if (strcmp(csa->field, "d") == 0) + type = GLP_DB; + else if (strcmp(csa->field, "s") == 0) + type = GLP_FX; + else + error(csa, "column type missing or invalid"); + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { read_field(csa); + if (str2num(csa->field, &lb) != 0) + error(csa, "column lower bound/fixed value missing or" + " invalid"); + } + else + lb = 0.0; + if (type == GLP_UP || type == GLP_DB) + { read_field(csa); + if (str2num(csa->field, &ub) != 0) + error(csa, "column upper bound missing or invalid"); + } + else + ub = 0.0; +skip: if (cf[j] & 0x01) + error(csa, "duplicate column descriptor"); + glp_set_col_kind(P, j, kind); + glp_set_col_bnds(P, j, type, lb, ub), cf[j] |= 0x01; + } + else if (strcmp(csa->field, "a") == 0) + { /* coefficient descriptor */ + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "row number missing or invalid"); + if (!(0 <= i && i <= m)) + error(csa, "row number out of range"); + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "column number missing or invalid"); + if (!((i == 0 ? 0 : 1) <= j && j <= n)) + error(csa, "column number out of range"); + read_field(csa); + if (i == 0) + { if (str2num(csa->field, &temp) != 0) + error(csa, "objective %s missing or invalid", + j == 0 ? "constant term" : "coefficient"); + if (cf[j] & 0x10) + error(csa, "duplicate objective %s", + j == 0 ? "constant term" : "coefficient"); + glp_set_obj_coef(P, j, temp), cf[j] |= 0x10; + } + else + { if (str2num(csa->field, &temp) != 0) + error(csa, "constraint coefficient missing or invalid" + ); + if (ne == nnz) + error(csa, "too many constraint coefficient descripto" + "rs"); + ln[++ne] = csa->count; + ia[ne] = i, ja[ne] = j, ar[ne] = temp; + } + } + else if (strcmp(csa->field, "n") == 0) + { /* symbolic name descriptor */ + read_field(csa); + if (strcmp(csa->field, "p") == 0) + { /* problem name */ + read_field(csa); + if (P->name != NULL) + error(csa, "duplicate problem name"); + glp_set_prob_name(P, csa->field); + } + else if (strcmp(csa->field, "z") == 0) + { /* objective name */ + read_field(csa); + if (P->obj != NULL) + error(csa, "duplicate objective name"); + glp_set_obj_name(P, csa->field); + } + else if (strcmp(csa->field, "i") == 0) + { /* row name */ + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "row number missing or invalid"); + if (!(1 <= i && i <= m)) + error(csa, "row number out of range"); + read_field(csa); + if (P->row[i]->name != NULL) + error(csa, "duplicate row name"); + glp_set_row_name(P, i, csa->field); + } + else if (strcmp(csa->field, "j") == 0) + { /* column name */ + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "column number missing or invalid"); + if (!(1 <= j && j <= n)) + error(csa, "column number out of range"); + read_field(csa); + if (P->col[j]->name != NULL) + error(csa, "duplicate column name"); + glp_set_col_name(P, j, csa->field); + } + else + error(csa, "object designator missing or invalid"); + } + else if (strcmp(csa->field, "e") == 0) + break; + else + error(csa, "line designator missing or invalid"); + end_of_line(csa); + } + if (ne < nnz) + error(csa, "too few constraint coefficient descriptors"); + xassert(ne == nnz); + k = glp_check_dup(m, n, ne, ia, ja); + xassert(0 <= k && k <= nnz); + if (k > 0) + { csa->count = ln[k]; + error(csa, "duplicate constraint coefficient"); + } + glp_load_matrix(P, ne, ia, ja, ar); + /* print some statistics */ + if (P->name != NULL) + xprintf("Problem: %s\n", P->name); + if (P->obj != NULL) + xprintf("Objective: %s\n", P->obj); + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ? + "" : "s"); + if (glp_get_num_int(P) > 0) + { int ni = glp_get_num_int(P); + int nb = glp_get_num_bin(P); + if (ni == 1) + { if (nb == 0) + xprintf("One variable is integer\n"); + else + xprintf("One variable is binary\n"); + } + else + { xprintf("%d integer variables, ", ni); + if (nb == 0) + xprintf("none"); + else if (nb == 1) + xprintf("one"); + else if (nb == ni) + xprintf("all"); + else + xprintf("%d", nb); + xprintf(" of which %s binary\n", nb == 1 ? "is" : "are"); + } + } + xprintf("%d lines were read\n", csa->count); + /* problem data has been successfully read */ + glp_sort_matrix(P); + ret = 0; +done: if (csa->fp != NULL) glp_close(csa->fp); + if (rf != NULL) xfree(rf); + if (cf != NULL) xfree(cf); + if (ln != NULL) xfree(ln); + if (ia != NULL) xfree(ia); + if (ja != NULL) xfree(ja); + if (ar != NULL) xfree(ar); + if (ret) glp_erase_prob(P); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_prob - write problem data in GLPK format +* +* SYNOPSIS +* +* int glp_write_prob(glp_prob *P, int flags, const char *fname); +* +* The routine glp_write_prob writes problem data in GLPK LP/MIP format +* to a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_prob(glp_prob *P, int flags, const char *fname) +{ glp_file *fp; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int mip, i, j, count, ret; + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_write_prob: P = %p; invalid problem object\n", + P); + if (flags != 0) + xerror("glp_write_prob: flags = %d; invalid parameter\n", + flags); + if (fname == NULL) + xerror("glp_write_prob: fname = %d; invalid parameter\n", + fname); + xprintf("Writing problem data to `%s'...\n", fname); + fp = glp_open(fname, "w"), count = 0; + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* write problem line */ + mip = (glp_get_num_int(P) > 0); + xfprintf(fp, "p %s %s %d %d %d\n", !mip ? "lp" : "mip", + P->dir == GLP_MIN ? "min" : P->dir == GLP_MAX ? "max" : "???", + P->m, P->n, P->nnz), count++; + if (P->name != NULL) + xfprintf(fp, "n p %s\n", P->name), count++; + if (P->obj != NULL) + xfprintf(fp, "n z %s\n", P->obj), count++; + /* write row descriptors */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->type == GLP_FX && row->lb == 0.0) + goto skip1; + xfprintf(fp, "i %d ", i), count++; + if (row->type == GLP_FR) + xfprintf(fp, "f\n"); + else if (row->type == GLP_LO) + xfprintf(fp, "l %.*g\n", DBL_DIG, row->lb); + else if (row->type == GLP_UP) + xfprintf(fp, "u %.*g\n", DBL_DIG, row->ub); + else if (row->type == GLP_DB) + xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, row->lb, DBL_DIG, + row->ub); + else if (row->type == GLP_FX) + xfprintf(fp, "s %.*g\n", DBL_DIG, row->lb); + else + xassert(row != row); +skip1: if (row->name != NULL) + xfprintf(fp, "n i %d %s\n", i, row->name), count++; + } + /* write column descriptors */ + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (!mip && col->type == GLP_LO && col->lb == 0.0) + goto skip2; + if (mip && col->kind == GLP_IV && col->type == GLP_DB && + col->lb == 0.0 && col->ub == 1.0) + goto skip2; + xfprintf(fp, "j %d ", j), count++; + if (mip) + { if (col->kind == GLP_CV) + xfprintf(fp, "c "); + else if (col->kind == GLP_IV) + xfprintf(fp, "i "); + else + xassert(col != col); + } + if (col->type == GLP_FR) + xfprintf(fp, "f\n"); + else if (col->type == GLP_LO) + xfprintf(fp, "l %.*g\n", DBL_DIG, col->lb); + else if (col->type == GLP_UP) + xfprintf(fp, "u %.*g\n", DBL_DIG, col->ub); + else if (col->type == GLP_DB) + xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, col->lb, DBL_DIG, + col->ub); + else if (col->type == GLP_FX) + xfprintf(fp, "s %.*g\n", DBL_DIG, col->lb); + else + xassert(col != col); +skip2: if (col->name != NULL) + xfprintf(fp, "n j %d %s\n", j, col->name), count++; + } + /* write objective coefficient descriptors */ + if (P->c0 != 0.0) + xfprintf(fp, "a 0 0 %.*g\n", DBL_DIG, P->c0), count++; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->coef != 0.0) + xfprintf(fp, "a 0 %d %.*g\n", j, DBL_DIG, col->coef), + count++; + } + /* write constraint coefficient descriptors */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + xfprintf(fp, "a %d %d %.*g\n", i, aij->col->j, DBL_DIG, + aij->val), count++; + } + /* write end line */ + xfprintf(fp, "e o f\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/**********************************************************************/ + +int glp_read_cnfsat(glp_prob *P, const char *fname) +{ /* read CNF-SAT problem data in DIMACS format */ + struct csa _csa, *csa = &_csa; + int m, n, i, j, len, neg, rhs, ret = 0, *ind = NULL; + double *val = NULL; + char *map = NULL; + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_read_cnfsat: P = %p; invalid problem object\n", + P); + if (fname == NULL) + xerror("glp_read_cnfsat: fname = %p; invalid parameter\n", + fname); + glp_erase_prob(P); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading CNF-SAT problem data from `%s'...\n", fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "cnf") != 0) + error(csa, "wrong problem designator; `cnf' expected\n"); + read_field(csa); + if (!(str2int(csa->field, &n) == 0 && n >= 0)) + error(csa, "number of variables missing or invalid\n"); + read_field(csa); + if (!(str2int(csa->field, &m) == 0 && m >= 0)) + error(csa, "number of clauses missing or invalid\n"); + xprintf("Instance has %d variable%s and %d clause%s\n", + n, n == 1 ? "" : "s", m, m == 1 ? "" : "s"); + end_of_line(csa); + if (m > 0) + glp_add_rows(P, m); + if (n > 0) + { glp_add_cols(P, n); + for (j = 1; j <= n; j++) + glp_set_col_kind(P, j, GLP_BV); + } + /* allocate working arrays */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + map = xcalloc(1+n, sizeof(char)); + for (j = 1; j <= n; j++) map[j] = 0; + /* read clauses */ + for (i = 1; i <= m; i++) + { /* read i-th clause */ + len = 0, rhs = 1; + for (;;) + { /* skip white-space characters */ + while (csa->c == ' ' || csa->c == '\n') + read_char(csa); + /* read term */ + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "variable number missing or invalid\n"); + if (j > 0) + neg = 0; + else if (j < 0) + neg = 1, j = -j, rhs--; + else + break; + if (!(1 <= j && j <= n)) + error(csa, "variable number out of range\n"); + if (map[j]) + error(csa, "duplicate variable number\n"); + len++, ind[len] = j, val[len] = (neg ? -1.0 : +1.0); + map[j] = 1; + } + glp_set_row_bnds(P, i, GLP_LO, (double)rhs, 0.0); + glp_set_mat_row(P, i, len, ind, val); + while (len > 0) map[ind[len--]] = 0; + } + xprintf("%d lines were read\n", csa->count); + /* problem data has been successfully read */ + glp_sort_matrix(P); +done: if (csa->fp != NULL) glp_close(csa->fp); + if (ind != NULL) xfree(ind); + if (val != NULL) xfree(val); + if (map != NULL) xfree(map); + if (ret) glp_erase_prob(P); + return ret; +} + +/**********************************************************************/ + +int glp_check_cnfsat(glp_prob *P) +{ /* check for CNF-SAT problem instance */ + int m = P->m; + int n = P->n; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, j, neg; + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_check_cnfsat: P = %p; invalid problem object\n", + P); + /* check columns */ + for (j = 1; j <= n; j++) + { col = P->col[j]; + /* the variable should be binary */ + if (!(col->kind == GLP_IV && col->type == GLP_DB && + col->lb == 0.0 && col->ub == 1.0)) + return 1; + } + /* objective function should be zero */ + if (P->c0 != 0.0) + return 2; + for (j = 1; j <= n; j++) + { col = P->col[j]; + if (col->coef != 0.0) + return 3; + } + /* check rows */ + for (i = 1; i <= m; i++) + { row = P->row[i]; + /* the row should be of ">=" type */ + if (row->type != GLP_LO) + return 4; + /* check constraint coefficients */ + neg = 0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { /* the constraint coefficient should be +1 or -1 */ + if (aij->val == +1.0) + ; + else if (aij->val == -1.0) + neg++; + else + return 5; + } + /* the right-hand side should be (1 - neg), where neg is the + number of negative constraint coefficients in the row */ + if (row->lb != (double)(1 - neg)) + return 6; + } + /* congratulations; this is CNF-SAT */ + return 0; +} + +/**********************************************************************/ + +int glp_write_cnfsat(glp_prob *P, const char *fname) +{ /* write CNF-SAT problem data in DIMACS format */ + glp_file *fp = NULL; + GLPAIJ *aij; + int i, j, len, count = 0, ret; + char s[50]; + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_write_cnfsat: P = %p; invalid problem object\n", + P); + if (glp_check_cnfsat(P) != 0) + { xprintf("glp_write_cnfsat: problem object does not encode CNF-" + "SAT instance\n"); + ret = 1; + goto done; + } + xprintf("Writing CNF-SAT problem data to `%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "c %s\n", + P->name == NULL ? "unknown" : P->name), count++; + xfprintf(fp, "p cnf %d %d\n", P->n, P->m), count++; + for (i = 1; i <= P->m; i++) + { len = 0; + for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) + { j = aij->col->j; + if (aij->val < 0.0) j = -j; + sprintf(s, "%d", j); + if (len > 0 && len + 1 + strlen(s) > 72) + xfprintf(fp, "\n"), count++, len = 0; + xfprintf(fp, "%s%s", len == 0 ? "" : " ", s); + if (len > 0) len++; + len += strlen(s); + } + if (len > 0 && len + 1 + 1 > 72) + xfprintf(fp, "\n"), count++, len = 0; + xfprintf(fp, "%s0\n", len == 0 ? "" : " "), count++; + } + xfprintf(fp, "c eof\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpgmp.c b/resources/3rdparty/glpk-4.53/src/glpgmp.c new file mode 100644 index 000000000..95c5159bd --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpgmp.c @@ -0,0 +1,1116 @@ +/* glpgmp.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#define _GLPSTD_STDIO +#if 1 /* 11/VI-2013 */ +#include "bignum.h" +#endif +#include "dmp.h" +#include "glpgmp.h" +#include "env.h" +#define xfault xerror + +#ifdef HAVE_GMP /* use GNU MP bignum library */ + +int gmp_pool_count(void) { return 0; } + +void gmp_free_mem(void) { return; } + +#else /* use GLPK bignum module */ + +static DMP *gmp_pool = NULL; +static int gmp_size = 0; +static unsigned short *gmp_work = NULL; + +void *gmp_get_atom(int size) +{ if (gmp_pool == NULL) + gmp_pool = dmp_create_pool(); + return dmp_get_atom(gmp_pool, size); +} + +void gmp_free_atom(void *ptr, int size) +{ xassert(gmp_pool != NULL); + dmp_free_atom(gmp_pool, ptr, size); + return; +} + +int gmp_pool_count(void) +{ if (gmp_pool == NULL) + return 0; + else +#if 0 /* 10/VI-2013 */ + return dmp_in_use(gmp_pool).lo; +#else + return dmp_in_use(gmp_pool); +#endif +} + +unsigned short *gmp_get_work(int size) +{ xassert(size > 0); + if (gmp_size < size) + { if (gmp_size == 0) + { xassert(gmp_work == NULL); + gmp_size = 100; + } + else + { xassert(gmp_work != NULL); + xfree(gmp_work); + } + while (gmp_size < size) gmp_size += gmp_size; + gmp_work = xcalloc(gmp_size, sizeof(unsigned short)); + } + return gmp_work; +} + +void gmp_free_mem(void) +{ if (gmp_pool != NULL) dmp_delete_pool(gmp_pool); + if (gmp_work != NULL) xfree(gmp_work); + gmp_pool = NULL; + gmp_size = 0; + gmp_work = NULL; + return; +} + +/*====================================================================*/ + +mpz_t _mpz_init(void) +{ /* initialize x, and set its value to 0 */ + mpz_t x; + x = gmp_get_atom(sizeof(struct mpz)); + x->val = 0; + x->ptr = NULL; + return x; +} + +void mpz_clear(mpz_t x) +{ /* free the space occupied by x */ + mpz_set_si(x, 0); + xassert(x->ptr == NULL); + /* free the number descriptor */ + gmp_free_atom(x, sizeof(struct mpz)); + return; +} + +void mpz_set(mpz_t z, mpz_t x) +{ /* set the value of z from x */ + struct mpz_seg *e, *ee, *es; + if (z != x) + { mpz_set_si(z, 0); + z->val = x->val; + xassert(z->ptr == NULL); + for (e = x->ptr, es = NULL; e != NULL; e = e->next) + { ee = gmp_get_atom(sizeof(struct mpz_seg)); + memcpy(ee->d, e->d, 12); + ee->next = NULL; + if (z->ptr == NULL) + z->ptr = ee; + else + es->next = ee; + es = ee; + } + } + return; +} + +void mpz_set_si(mpz_t x, int val) +{ /* set the value of x to val */ + struct mpz_seg *e; + /* free existing segments, if any */ + while (x->ptr != NULL) + { e = x->ptr; + x->ptr = e->next; + gmp_free_atom(e, sizeof(struct mpz_seg)); + } + /* assign new value */ + if (val == 0x80000000) + { /* long format is needed */ + x->val = -1; + x->ptr = e = gmp_get_atom(sizeof(struct mpz_seg)); + memset(e->d, 0, 12); + e->d[1] = 0x8000; + e->next = NULL; + } + else + { /* short format is enough */ + x->val = val; + } + return; +} + +double mpz_get_d(mpz_t x) +{ /* convert x to a double, truncating if necessary */ + struct mpz_seg *e; + int j; + double val, deg; + if (x->ptr == NULL) + val = (double)x->val; + else + { xassert(x->val != 0); + val = 0.0; + deg = 1.0; + for (e = x->ptr; e != NULL; e = e->next) + { for (j = 0; j <= 5; j++) + { val += deg * (double)((int)e->d[j]); + deg *= 65536.0; + } + } + if (x->val < 0) val = - val; + } + return val; +} + +double mpz_get_d_2exp(int *exp, mpz_t x) +{ /* convert x to a double, truncating if necessary (i.e. rounding + towards zero), and returning the exponent separately; + the return value is in the range 0.5 <= |d| < 1 and the + exponent is stored to *exp; d*2^exp is the (truncated) x value; + if x is zero, the return is 0.0 and 0 is stored to *exp; + this is similar to the standard C frexp function */ + struct mpz_seg *e; + int j, n, n1; + double val; + if (x->ptr == NULL) + val = (double)x->val, n = 0; + else + { xassert(x->val != 0); + val = 0.0, n = 0; + for (e = x->ptr; e != NULL; e = e->next) + { for (j = 0; j <= 5; j++) + { val += (double)((int)e->d[j]); + val /= 65536.0, n += 16; + } + } + if (x->val < 0) val = - val; + } + val = frexp(val, &n1); + *exp = n + n1; + return val; +} + +void mpz_swap(mpz_t x, mpz_t y) +{ /* swap the values x and y efficiently */ + int val; + void *ptr; + val = x->val, ptr = x->ptr; + x->val = y->val, x->ptr = y->ptr; + y->val = val, y->ptr = ptr; + return; +} + +static void normalize(mpz_t x) +{ /* normalize integer x that includes removing non-significant + (leading) zeros and converting to short format, if possible */ + struct mpz_seg *es, *e; + /* if the integer is in short format, it remains unchanged */ + if (x->ptr == NULL) + { xassert(x->val != 0x80000000); + goto done; + } + xassert(x->val == +1 || x->val == -1); + /* find the last (most significant) non-zero segment */ + es = NULL; + for (e = x->ptr; e != NULL; e = e->next) + { if (e->d[0] || e->d[1] || e->d[2] || + e->d[3] || e->d[4] || e->d[5]) es = e; + } + /* if all segments contain zeros, the integer is zero */ + if (es == NULL) + { mpz_set_si(x, 0); + goto done; + } + /* remove non-significant (leading) zero segments */ + while (es->next != NULL) + { e = es->next; + es->next = e->next; + gmp_free_atom(e, sizeof(struct mpz_seg)); + } + /* convert the integer to short format, if possible */ + e = x->ptr; + if (e->next == NULL && e->d[1] <= 0x7FFF && + !e->d[2] && !e->d[3] && !e->d[4] && !e->d[5]) + { int val; + val = (int)e->d[0] + ((int)e->d[1] << 16); + if (x->val < 0) val = - val; + mpz_set_si(x, val); + } +done: return; +} + +void mpz_add(mpz_t z, mpz_t x, mpz_t y) +{ /* set z to x + y */ + static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL }; + struct mpz_seg dumx, dumy, *ex, *ey, *ez, *es, *ee; + int k, sx, sy, sz; + unsigned int t; + /* if [x] = 0 then [z] = [y] */ + if (x->val == 0) + { xassert(x->ptr == NULL); + mpz_set(z, y); + goto done; + } + /* if [y] = 0 then [z] = [x] */ + if (y->val == 0) + { xassert(y->ptr == NULL); + mpz_set(z, x); + goto done; + } + /* special case when both [x] and [y] are in short format */ + if (x->ptr == NULL && y->ptr == NULL) + { int xval = x->val, yval = y->val, zval = x->val + y->val; + xassert(xval != 0x80000000 && yval != 0x80000000); + if (!(xval > 0 && yval > 0 && zval <= 0 || + xval < 0 && yval < 0 && zval >= 0)) + { mpz_set_si(z, zval); + goto done; + } + } + /* convert [x] to long format, if necessary */ + if (x->ptr == NULL) + { xassert(x->val != 0x80000000); + if (x->val >= 0) + { sx = +1; + t = (unsigned int)(+ x->val); + } + else + { sx = -1; + t = (unsigned int)(- x->val); + } + ex = &dumx; + ex->d[0] = (unsigned short)t; + ex->d[1] = (unsigned short)(t >> 16); + ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; + ex->next = NULL; + } + else + { sx = x->val; + xassert(sx == +1 || sx == -1); + ex = x->ptr; + } + /* convert [y] to long format, if necessary */ + if (y->ptr == NULL) + { xassert(y->val != 0x80000000); + if (y->val >= 0) + { sy = +1; + t = (unsigned int)(+ y->val); + } + else + { sy = -1; + t = (unsigned int)(- y->val); + } + ey = &dumy; + ey->d[0] = (unsigned short)t; + ey->d[1] = (unsigned short)(t >> 16); + ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; + ey->next = NULL; + } + else + { sy = y->val; + xassert(sy == +1 || sy == -1); + ey = y->ptr; + } + /* main fragment */ + sz = sx; + ez = es = NULL; + if (sx > 0 && sy > 0 || sx < 0 && sy < 0) + { /* [x] and [y] have identical signs -- addition */ + t = 0; + for (; ex || ey; ex = ex->next, ey = ey->next) + { if (ex == NULL) ex = &zero; + if (ey == NULL) ey = &zero; + ee = gmp_get_atom(sizeof(struct mpz_seg)); + for (k = 0; k <= 5; k++) + { t += (unsigned int)ex->d[k]; + t += (unsigned int)ey->d[k]; + ee->d[k] = (unsigned short)t; + t >>= 16; + } + ee->next = NULL; + if (ez == NULL) + ez = ee; + else + es->next = ee; + es = ee; + } + if (t) + { /* overflow -- one extra digit is needed */ + ee = gmp_get_atom(sizeof(struct mpz_seg)); + ee->d[0] = 1; + ee->d[1] = ee->d[2] = ee->d[3] = ee->d[4] = ee->d[5] = 0; + ee->next = NULL; + xassert(es != NULL); + es->next = ee; + } + } + else + { /* [x] and [y] have different signs -- subtraction */ + t = 1; + for (; ex || ey; ex = ex->next, ey = ey->next) + { if (ex == NULL) ex = &zero; + if (ey == NULL) ey = &zero; + ee = gmp_get_atom(sizeof(struct mpz_seg)); + for (k = 0; k <= 5; k++) + { t += (unsigned int)ex->d[k]; + t += (0xFFFF - (unsigned int)ey->d[k]); + ee->d[k] = (unsigned short)t; + t >>= 16; + } + ee->next = NULL; + if (ez == NULL) + ez = ee; + else + es->next = ee; + es = ee; + } + if (!t) + { /* |[x]| < |[y]| -- result in complement coding */ + sz = - sz; + t = 1; + for (ee = ez; ee != NULL; ee = ee->next) + for (k = 0; k <= 5; k++) + { t += (0xFFFF - (unsigned int)ee->d[k]); + ee->d[k] = (unsigned short)t; + t >>= 16; + } + } + } + /* contruct and normalize result */ + mpz_set_si(z, 0); + z->val = sz; + z->ptr = ez; + normalize(z); +done: return; +} + +void mpz_sub(mpz_t z, mpz_t x, mpz_t y) +{ /* set z to x - y */ + if (x == y) + mpz_set_si(z, 0); + else + { y->val = - y->val; + mpz_add(z, x, y); + if (y != z) y->val = - y->val; + } + return; +} + +void mpz_mul(mpz_t z, mpz_t x, mpz_t y) +{ /* set z to x * y */ + struct mpz_seg dumx, dumy, *ex, *ey, *es, *e; + int sx, sy, k, nx, ny, n; + unsigned int t; + unsigned short *work, *wx, *wy; + /* if [x] = 0 then [z] = 0 */ + if (x->val == 0) + { xassert(x->ptr == NULL); + mpz_set_si(z, 0); + goto done; + } + /* if [y] = 0 then [z] = 0 */ + if (y->val == 0) + { xassert(y->ptr == NULL); + mpz_set_si(z, 0); + goto done; + } + /* special case when both [x] and [y] are in short format */ + if (x->ptr == NULL && y->ptr == NULL) + { int xval = x->val, yval = y->val, sz = +1; + xassert(xval != 0x80000000 && yval != 0x80000000); + if (xval < 0) xval = - xval, sz = - sz; + if (yval < 0) yval = - yval, sz = - sz; + if (xval <= 0x7FFFFFFF / yval) + { mpz_set_si(z, sz * (xval * yval)); + goto done; + } + } + /* convert [x] to long format, if necessary */ + if (x->ptr == NULL) + { xassert(x->val != 0x80000000); + if (x->val >= 0) + { sx = +1; + t = (unsigned int)(+ x->val); + } + else + { sx = -1; + t = (unsigned int)(- x->val); + } + ex = &dumx; + ex->d[0] = (unsigned short)t; + ex->d[1] = (unsigned short)(t >> 16); + ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; + ex->next = NULL; + } + else + { sx = x->val; + xassert(sx == +1 || sx == -1); + ex = x->ptr; + } + /* convert [y] to long format, if necessary */ + if (y->ptr == NULL) + { xassert(y->val != 0x80000000); + if (y->val >= 0) + { sy = +1; + t = (unsigned int)(+ y->val); + } + else + { sy = -1; + t = (unsigned int)(- y->val); + } + ey = &dumy; + ey->d[0] = (unsigned short)t; + ey->d[1] = (unsigned short)(t >> 16); + ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; + ey->next = NULL; + } + else + { sy = y->val; + xassert(sy == +1 || sy == -1); + ey = y->ptr; + } + /* determine the number of digits of [x] */ + nx = n = 0; + for (e = ex; e != NULL; e = e->next) + for (k = 0; k <= 5; k++) + { n++; + if (e->d[k]) nx = n; + } + xassert(nx > 0); + /* determine the number of digits of [y] */ + ny = n = 0; + for (e = ey; e != NULL; e = e->next) + for (k = 0; k <= 5; k++) + { n++; + if (e->d[k]) ny = n; + } + xassert(ny > 0); + /* we need working array containing at least nx+ny+ny places */ + work = gmp_get_work(nx+ny+ny); + /* load digits of [x] */ + wx = &work[0]; + for (n = 0; n < nx; n++) wx[ny+n] = 0; + for (n = 0, e = ex; e != NULL; e = e->next) + for (k = 0; k <= 5; k++, n++) + if (e->d[k]) wx[ny+n] = e->d[k]; + /* load digits of [y] */ + wy = &work[nx+ny]; + for (n = 0; n < ny; n++) wy[n] = 0; + for (n = 0, e = ey; e != NULL; e = e->next) + for (k = 0; k <= 5; k++, n++) + if (e->d[k]) wy[n] = e->d[k]; + /* compute [x] * [y] */ + bigmul(nx, ny, wx, wy); + /* construct and normalize result */ + mpz_set_si(z, 0); + z->val = sx * sy; + es = NULL; + k = 6; + for (n = 0; n < nx+ny; n++) + { if (k > 5) + { e = gmp_get_atom(sizeof(struct mpz_seg)); + e->d[0] = e->d[1] = e->d[2] = 0; + e->d[3] = e->d[4] = e->d[5] = 0; + e->next = NULL; + if (z->ptr == NULL) + z->ptr = e; + else + es->next = e; + es = e; + k = 0; + } + es->d[k++] = wx[n]; + } + normalize(z); +done: return; +} + +void mpz_neg(mpz_t z, mpz_t x) +{ /* set z to 0 - x */ + mpz_set(z, x); + z->val = - z->val; + return; +} + +void mpz_abs(mpz_t z, mpz_t x) +{ /* set z to the absolute value of x */ + mpz_set(z, x); + if (z->val < 0) z->val = - z->val; + return; +} + +void mpz_div(mpz_t q, mpz_t r, mpz_t x, mpz_t y) +{ /* divide x by y, forming quotient q and/or remainder r + if q = NULL then quotient is not stored; if r = NULL then + remainder is not stored + the sign of quotient is determined as in algebra while the + sign of remainder is the same as the sign of dividend: + +26 : +7 = +3, remainder is +5 + -26 : +7 = -3, remainder is -5 + +26 : -7 = -3, remainder is +5 + -26 : -7 = +3, remainder is -5 */ + struct mpz_seg dumx, dumy, *ex, *ey, *es, *e; + int sx, sy, k, nx, ny, n; + unsigned int t; + unsigned short *work, *wx, *wy; + /* divide by zero is not allowed */ + if (y->val == 0) + { xassert(y->ptr == NULL); + xfault("mpz_div: divide by zero not allowed\n"); + } + /* if [x] = 0 then [q] = [r] = 0 */ + if (x->val == 0) + { xassert(x->ptr == NULL); + if (q != NULL) mpz_set_si(q, 0); + if (r != NULL) mpz_set_si(r, 0); + goto done; + } + /* special case when both [x] and [y] are in short format */ + if (x->ptr == NULL && y->ptr == NULL) + { int xval = x->val, yval = y->val; + xassert(xval != 0x80000000 && yval != 0x80000000); + if (q != NULL) mpz_set_si(q, xval / yval); + if (r != NULL) mpz_set_si(r, xval % yval); + goto done; + } + /* convert [x] to long format, if necessary */ + if (x->ptr == NULL) + { xassert(x->val != 0x80000000); + if (x->val >= 0) + { sx = +1; + t = (unsigned int)(+ x->val); + } + else + { sx = -1; + t = (unsigned int)(- x->val); + } + ex = &dumx; + ex->d[0] = (unsigned short)t; + ex->d[1] = (unsigned short)(t >> 16); + ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; + ex->next = NULL; + } + else + { sx = x->val; + xassert(sx == +1 || sx == -1); + ex = x->ptr; + } + /* convert [y] to long format, if necessary */ + if (y->ptr == NULL) + { xassert(y->val != 0x80000000); + if (y->val >= 0) + { sy = +1; + t = (unsigned int)(+ y->val); + } + else + { sy = -1; + t = (unsigned int)(- y->val); + } + ey = &dumy; + ey->d[0] = (unsigned short)t; + ey->d[1] = (unsigned short)(t >> 16); + ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; + ey->next = NULL; + } + else + { sy = y->val; + xassert(sy == +1 || sy == -1); + ey = y->ptr; + } + /* determine the number of digits of [x] */ + nx = n = 0; + for (e = ex; e != NULL; e = e->next) + for (k = 0; k <= 5; k++) + { n++; + if (e->d[k]) nx = n; + } + xassert(nx > 0); + /* determine the number of digits of [y] */ + ny = n = 0; + for (e = ey; e != NULL; e = e->next) + for (k = 0; k <= 5; k++) + { n++; + if (e->d[k]) ny = n; + } + xassert(ny > 0); + /* if nx < ny then [q] = 0 and [r] = [x] */ + if (nx < ny) + { if (r != NULL) mpz_set(r, x); + if (q != NULL) mpz_set_si(q, 0); + goto done; + } + /* we need working array containing at least nx+ny+1 places */ + work = gmp_get_work(nx+ny+1); + /* load digits of [x] */ + wx = &work[0]; + for (n = 0; n < nx; n++) wx[n] = 0; + for (n = 0, e = ex; e != NULL; e = e->next) + for (k = 0; k <= 5; k++, n++) + if (e->d[k]) wx[n] = e->d[k]; + /* load digits of [y] */ + wy = &work[nx+1]; + for (n = 0; n < ny; n++) wy[n] = 0; + for (n = 0, e = ey; e != NULL; e = e->next) + for (k = 0; k <= 5; k++, n++) + if (e->d[k]) wy[n] = e->d[k]; + /* compute quotient and remainder */ + xassert(wy[ny-1] != 0); + bigdiv(nx-ny, ny, wx, wy); + /* construct and normalize quotient */ + if (q != NULL) + { mpz_set_si(q, 0); + q->val = sx * sy; + es = NULL; + k = 6; + for (n = ny; n <= nx; n++) + { if (k > 5) + { e = gmp_get_atom(sizeof(struct mpz_seg)); + e->d[0] = e->d[1] = e->d[2] = 0; + e->d[3] = e->d[4] = e->d[5] = 0; + e->next = NULL; + if (q->ptr == NULL) + q->ptr = e; + else + es->next = e; + es = e; + k = 0; + } + es->d[k++] = wx[n]; + } + normalize(q); + } + /* construct and normalize remainder */ + if (r != NULL) + { mpz_set_si(r, 0); + r->val = sx; + es = NULL; + k = 6; + for (n = 0; n < ny; n++) + { if (k > 5) + { e = gmp_get_atom(sizeof(struct mpz_seg)); + e->d[0] = e->d[1] = e->d[2] = 0; + e->d[3] = e->d[4] = e->d[5] = 0; + e->next = NULL; + if (r->ptr == NULL) + r->ptr = e; + else + es->next = e; + es = e; + k = 0; + } + es->d[k++] = wx[n]; + } + normalize(r); + } +done: return; +} + +void mpz_gcd(mpz_t z, mpz_t x, mpz_t y) +{ /* set z to the greatest common divisor of x and y */ + /* in case of arbitrary integers GCD(x, y) = GCD(|x|, |y|), and, + in particular, GCD(0, 0) = 0 */ + mpz_t u, v, r; + mpz_init(u); + mpz_init(v); + mpz_init(r); + mpz_abs(u, x); + mpz_abs(v, y); + while (mpz_sgn(v)) + { mpz_div(NULL, r, u, v); + mpz_set(u, v); + mpz_set(v, r); + } + mpz_set(z, u); + mpz_clear(u); + mpz_clear(v); + mpz_clear(r); + return; +} + +int mpz_cmp(mpz_t x, mpz_t y) +{ /* compare x and y; return a positive value if x > y, zero if + x = y, or a nefative value if x < y */ + static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL }; + struct mpz_seg dumx, dumy, *ex, *ey; + int cc, sx, sy, k; + unsigned int t; + if (x == y) + { cc = 0; + goto done; + } + /* special case when both [x] and [y] are in short format */ + if (x->ptr == NULL && y->ptr == NULL) + { int xval = x->val, yval = y->val; + xassert(xval != 0x80000000 && yval != 0x80000000); + cc = (xval > yval ? +1 : xval < yval ? -1 : 0); + goto done; + } + /* special case when [x] and [y] have different signs */ + if (x->val > 0 && y->val <= 0 || x->val == 0 && y->val < 0) + { cc = +1; + goto done; + } + if (x->val < 0 && y->val >= 0 || x->val == 0 && y->val > 0) + { cc = -1; + goto done; + } + /* convert [x] to long format, if necessary */ + if (x->ptr == NULL) + { xassert(x->val != 0x80000000); + if (x->val >= 0) + { sx = +1; + t = (unsigned int)(+ x->val); + } + else + { sx = -1; + t = (unsigned int)(- x->val); + } + ex = &dumx; + ex->d[0] = (unsigned short)t; + ex->d[1] = (unsigned short)(t >> 16); + ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; + ex->next = NULL; + } + else + { sx = x->val; + xassert(sx == +1 || sx == -1); + ex = x->ptr; + } + /* convert [y] to long format, if necessary */ + if (y->ptr == NULL) + { xassert(y->val != 0x80000000); + if (y->val >= 0) + { sy = +1; + t = (unsigned int)(+ y->val); + } + else + { sy = -1; + t = (unsigned int)(- y->val); + } + ey = &dumy; + ey->d[0] = (unsigned short)t; + ey->d[1] = (unsigned short)(t >> 16); + ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; + ey->next = NULL; + } + else + { sy = y->val; + xassert(sy == +1 || sy == -1); + ey = y->ptr; + } + /* main fragment */ + xassert(sx > 0 && sy > 0 || sx < 0 && sy < 0); + cc = 0; + for (; ex || ey; ex = ex->next, ey = ey->next) + { if (ex == NULL) ex = &zero; + if (ey == NULL) ey = &zero; + for (k = 0; k <= 5; k++) + { if (ex->d[k] > ey->d[k]) cc = +1; + if (ex->d[k] < ey->d[k]) cc = -1; + } + } + if (sx < 0) cc = - cc; +done: return cc; +} + +int mpz_sgn(mpz_t x) +{ /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */ + int s; + s = (x->val > 0 ? +1 : x->val < 0 ? -1 : 0); + return s; +} + +int mpz_out_str(void *_fp, int base, mpz_t x) +{ /* output x on stream fp, as a string in given base; the base + may vary from 2 to 36; + return the number of bytes written, or if an error occurred, + return 0 */ + FILE *fp = _fp; + mpz_t b, y, r; + int n, j, nwr = 0; + unsigned char *d; + static char *set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (!(2 <= base && base <= 36)) + xfault("mpz_out_str: base = %d; invalid base\n", base); + mpz_init(b); + mpz_set_si(b, base); + mpz_init(y); + mpz_init(r); + /* determine the number of digits */ + mpz_abs(y, x); + for (n = 0; mpz_sgn(y) != 0; n++) + mpz_div(y, NULL, y, b); + if (n == 0) n = 1; + /* compute the digits */ + d = xmalloc(n); + mpz_abs(y, x); + for (j = 0; j < n; j++) + { mpz_div(y, r, y, b); + xassert(0 <= r->val && r->val < base && r->ptr == NULL); + d[j] = (unsigned char)r->val; + } + /* output the integer to the stream */ + if (fp == NULL) fp = stdout; + if (mpz_sgn(x) < 0) + fputc('-', fp), nwr++; + for (j = n-1; j >= 0; j--) + fputc(set[d[j]], fp), nwr++; + if (ferror(fp)) nwr = 0; + mpz_clear(b); + mpz_clear(y); + mpz_clear(r); + xfree(d); + return nwr; +} + +/*====================================================================*/ + +mpq_t _mpq_init(void) +{ /* initialize x, and set its value to 0/1 */ + mpq_t x; + x = gmp_get_atom(sizeof(struct mpq)); + x->p.val = 0; + x->p.ptr = NULL; + x->q.val = 1; + x->q.ptr = NULL; + return x; +} + +void mpq_clear(mpq_t x) +{ /* free the space occupied by x */ + mpz_set_si(&x->p, 0); + xassert(x->p.ptr == NULL); + mpz_set_si(&x->q, 0); + xassert(x->q.ptr == NULL); + /* free the number descriptor */ + gmp_free_atom(x, sizeof(struct mpq)); + return; +} + +void mpq_canonicalize(mpq_t x) +{ /* remove any factors that are common to the numerator and + denominator of x, and make the denominator positive */ + mpz_t f; + xassert(x->q.val != 0); + if (x->q.val < 0) + { mpz_neg(&x->p, &x->p); + mpz_neg(&x->q, &x->q); + } + mpz_init(f); + mpz_gcd(f, &x->p, &x->q); + if (!(f->val == 1 && f->ptr == NULL)) + { mpz_div(&x->p, NULL, &x->p, f); + mpz_div(&x->q, NULL, &x->q, f); + } + mpz_clear(f); + return; +} + +void mpq_set(mpq_t z, mpq_t x) +{ /* set the value of z from x */ + if (z != x) + { mpz_set(&z->p, &x->p); + mpz_set(&z->q, &x->q); + } + return; +} + +void mpq_set_si(mpq_t x, int p, unsigned int q) +{ /* set the value of x to p/q */ + if (q == 0) + xfault("mpq_set_si: zero denominator not allowed\n"); + mpz_set_si(&x->p, p); + xassert(q <= 0x7FFFFFFF); + mpz_set_si(&x->q, q); + return; +} + +double mpq_get_d(mpq_t x) +{ /* convert x to a double, truncating if necessary */ + int np, nq; + double p, q; + p = mpz_get_d_2exp(&np, &x->p); + q = mpz_get_d_2exp(&nq, &x->q); + return ldexp(p / q, np - nq); +} + +void mpq_set_d(mpq_t x, double val) +{ /* set x to val; there is no rounding, the conversion is exact */ + int s, n, d, j; + double f; + mpz_t temp; + xassert(-DBL_MAX <= val && val <= +DBL_MAX); + mpq_set_si(x, 0, 1); + if (val > 0.0) + s = +1; + else if (val < 0.0) + s = -1; + else + goto done; + f = frexp(fabs(val), &n); + /* |val| = f * 2^n, where 0.5 <= f < 1.0 */ + mpz_init(temp); + while (f != 0.0) + { f *= 16.0, n -= 4; + d = (int)f; + xassert(0 <= d && d <= 15); + f -= (double)d; + /* x := 16 * x + d */ + mpz_set_si(temp, 16); + mpz_mul(&x->p, &x->p, temp); + mpz_set_si(temp, d); + mpz_add(&x->p, &x->p, temp); + } + mpz_clear(temp); + /* x := x * 2^n */ + if (n > 0) + { for (j = 1; j <= n; j++) + mpz_add(&x->p, &x->p, &x->p); + } + else if (n < 0) + { for (j = 1; j <= -n; j++) + mpz_add(&x->q, &x->q, &x->q); + mpq_canonicalize(x); + } + if (s < 0) mpq_neg(x, x); +done: return; +} + +void mpq_add(mpq_t z, mpq_t x, mpq_t y) +{ /* set z to x + y */ + mpz_t p, q; + mpz_init(p); + mpz_init(q); + mpz_mul(p, &x->p, &y->q); + mpz_mul(q, &x->q, &y->p); + mpz_add(p, p, q); + mpz_mul(q, &x->q, &y->q); + mpz_set(&z->p, p); + mpz_set(&z->q, q); + mpz_clear(p); + mpz_clear(q); + mpq_canonicalize(z); + return; +} + +void mpq_sub(mpq_t z, mpq_t x, mpq_t y) +{ /* set z to x - y */ + mpz_t p, q; + mpz_init(p); + mpz_init(q); + mpz_mul(p, &x->p, &y->q); + mpz_mul(q, &x->q, &y->p); + mpz_sub(p, p, q); + mpz_mul(q, &x->q, &y->q); + mpz_set(&z->p, p); + mpz_set(&z->q, q); + mpz_clear(p); + mpz_clear(q); + mpq_canonicalize(z); + return; +} + +void mpq_mul(mpq_t z, mpq_t x, mpq_t y) +{ /* set z to x * y */ + mpz_mul(&z->p, &x->p, &y->p); + mpz_mul(&z->q, &x->q, &y->q); + mpq_canonicalize(z); + return; +} + +void mpq_div(mpq_t z, mpq_t x, mpq_t y) +{ /* set z to x / y */ + mpz_t p, q; + if (mpq_sgn(y) == 0) + xfault("mpq_div: zero divisor not allowed\n"); + mpz_init(p); + mpz_init(q); + mpz_mul(p, &x->p, &y->q); + mpz_mul(q, &x->q, &y->p); + mpz_set(&z->p, p); + mpz_set(&z->q, q); + mpz_clear(p); + mpz_clear(q); + mpq_canonicalize(z); + return; +} + +void mpq_neg(mpq_t z, mpq_t x) +{ /* set z to 0 - x */ + mpq_set(z, x); + mpz_neg(&z->p, &z->p); + return; +} + +void mpq_abs(mpq_t z, mpq_t x) +{ /* set z to the absolute value of x */ + mpq_set(z, x); + mpz_abs(&z->p, &z->p); + xassert(mpz_sgn(&x->q) > 0); + return; +} + +int mpq_cmp(mpq_t x, mpq_t y) +{ /* compare x and y; return a positive value if x > y, zero if + x = y, or a nefative value if x < y */ + mpq_t temp; + int s; + mpq_init(temp); + mpq_sub(temp, x, y); + s = mpq_sgn(temp); + mpq_clear(temp); + return s; +} + +int mpq_sgn(mpq_t x) +{ /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */ + int s; + s = mpz_sgn(&x->p); + xassert(mpz_sgn(&x->q) > 0); + return s; +} + +int mpq_out_str(void *_fp, int base, mpq_t x) +{ /* output x on stream fp, as a string in given base; the base + may vary from 2 to 36; output is in the form 'num/den' or if + the denominator is 1 then just 'num'; + if the parameter fp is a null pointer, stdout is assumed; + return the number of bytes written, or if an error occurred, + return 0 */ + FILE *fp = _fp; + int nwr; + if (!(2 <= base && base <= 36)) + xfault("mpq_out_str: base = %d; invalid base\n", base); + if (fp == NULL) fp = stdout; + nwr = mpz_out_str(fp, base, &x->p); + if (x->q.val == 1 && x->q.ptr == NULL) + ; + else + { fputc('/', fp), nwr++; + nwr += mpz_out_str(fp, base, &x->q); + } + if (ferror(fp)) nwr = 0; + return nwr; +} + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpgmp.h b/resources/3rdparty/glpk-4.53/src/glpgmp.h new file mode 100644 index 000000000..e1615ae27 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpgmp.h @@ -0,0 +1,190 @@ +/* glpgmp.h (bignum arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPGMP_H +#define GLPGMP_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_GMP /* use GNU MP bignum library */ + +#include <gmp.h> + +#define gmp_pool_count _glp_gmp_pool_count +#define gmp_free_mem _glp_gmp_free_mem + +int gmp_pool_count(void); +void gmp_free_mem(void); + +#else /* use GLPK bignum module */ + +/*---------------------------------------------------------------------- +// INTEGER NUMBERS +// +// Depending on its magnitude an integer number of arbitrary precision +// is represented either in short format or in long format. +// +// Short format corresponds to the int type and allows representing +// integer numbers in the range [-(2^31-1), +(2^31-1)]. Note that for +// the most negative number of int type the short format is not used. +// +// In long format integer numbers are represented using the positional +// system with the base (radix) 2^16 = 65536: +// +// x = (-1)^s sum{j in 0..n-1} d[j] * 65536^j, +// +// where x is the integer to be represented, s is its sign (+1 or -1), +// d[j] are its digits (0 <= d[j] <= 65535). +// +// RATIONAL NUMBERS +// +// A rational number is represented as an irreducible fraction: +// +// p / q, +// +// where p (numerator) and q (denominator) are integer numbers (q > 0) +// having no common divisors. */ + +struct mpz +{ /* integer number */ + int val; + /* if ptr is a null pointer, the number is in short format, and + val is its value; otherwise, the number is in long format, and + val is its sign (+1 or -1) */ + struct mpz_seg *ptr; + /* pointer to the linked list of the number segments ordered in + ascending of powers of the base */ +}; + +struct mpz_seg +{ /* integer number segment */ + unsigned short d[6]; + /* six digits of the number ordered in ascending of powers of the + base */ + struct mpz_seg *next; + /* pointer to the next number segment */ +}; + +struct mpq +{ /* rational number (p / q) */ + struct mpz p; + /* numerator */ + struct mpz q; + /* denominator */ +}; + +typedef struct mpz *mpz_t; +typedef struct mpq *mpq_t; + +#define gmp_get_atom _glp_gmp_get_atom +#define gmp_free_atom _glp_gmp_free_atom +#define gmp_pool_count _glp_gmp_pool_count +#define gmp_get_work _glp_gmp_get_work +#define gmp_free_mem _glp_gmp_free_mem + +#define _mpz_init _glp_mpz_init +#define mpz_clear _glp_mpz_clear +#define mpz_set _glp_mpz_set +#define mpz_set_si _glp_mpz_set_si +#define mpz_get_d _glp_mpz_get_d +#define mpz_get_d_2exp _glp_mpz_get_d_2exp +#define mpz_swap _glp_mpz_swap +#define mpz_add _glp_mpz_add +#define mpz_sub _glp_mpz_sub +#define mpz_mul _glp_mpz_mul +#define mpz_neg _glp_mpz_neg +#define mpz_abs _glp_mpz_abs +#define mpz_div _glp_mpz_div +#define mpz_gcd _glp_mpz_gcd +#define mpz_cmp _glp_mpz_cmp +#define mpz_sgn _glp_mpz_sgn +#define mpz_out_str _glp_mpz_out_str + +#define _mpq_init _glp_mpq_init +#define mpq_clear _glp_mpq_clear +#define mpq_canonicalize _glp_mpq_canonicalize +#define mpq_set _glp_mpq_set +#define mpq_set_si _glp_mpq_set_si +#define mpq_get_d _glp_mpq_get_d +#define mpq_set_d _glp_mpq_set_d +#define mpq_add _glp_mpq_add +#define mpq_sub _glp_mpq_sub +#define mpq_mul _glp_mpq_mul +#define mpq_div _glp_mpq_div +#define mpq_neg _glp_mpq_neg +#define mpq_abs _glp_mpq_abs +#define mpq_cmp _glp_mpq_cmp +#define mpq_sgn _glp_mpq_sgn +#define mpq_out_str _glp_mpq_out_str + +void *gmp_get_atom(int size); +void gmp_free_atom(void *ptr, int size); +int gmp_pool_count(void); +unsigned short *gmp_get_work(int size); +void gmp_free_mem(void); + +mpz_t _mpz_init(void); +#define mpz_init(x) (void)((x) = _mpz_init()) +void mpz_clear(mpz_t x); +void mpz_set(mpz_t z, mpz_t x); +void mpz_set_si(mpz_t x, int val); +double mpz_get_d(mpz_t x); +double mpz_get_d_2exp(int *exp, mpz_t x); +void mpz_swap(mpz_t x, mpz_t y); +void mpz_add(mpz_t, mpz_t, mpz_t); +void mpz_sub(mpz_t, mpz_t, mpz_t); +void mpz_mul(mpz_t, mpz_t, mpz_t); +void mpz_neg(mpz_t z, mpz_t x); +void mpz_abs(mpz_t z, mpz_t x); +void mpz_div(mpz_t q, mpz_t r, mpz_t x, mpz_t y); +void mpz_gcd(mpz_t z, mpz_t x, mpz_t y); +int mpz_cmp(mpz_t x, mpz_t y); +int mpz_sgn(mpz_t x); +int mpz_out_str(void *fp, int base, mpz_t x); + +mpq_t _mpq_init(void); +#define mpq_init(x) (void)((x) = _mpq_init()) +void mpq_clear(mpq_t x); +void mpq_canonicalize(mpq_t x); +void mpq_set(mpq_t z, mpq_t x); +void mpq_set_si(mpq_t x, int p, unsigned int q); +double mpq_get_d(mpq_t x); +void mpq_set_d(mpq_t x, double val); +void mpq_add(mpq_t z, mpq_t x, mpq_t y); +void mpq_sub(mpq_t z, mpq_t x, mpq_t y); +void mpq_mul(mpq_t z, mpq_t x, mpq_t y); +void mpq_div(mpq_t z, mpq_t x, mpq_t y); +void mpq_neg(mpq_t z, mpq_t x); +void mpq_abs(mpq_t z, mpq_t x); +int mpq_cmp(mpq_t x, mpq_t y); +int mpq_sgn(mpq_t x); +int mpq_out_str(void *fp, int base, mpq_t x); + +#endif + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glphbm.c b/resources/3rdparty/glpk-4.53/src/glphbm.c new file mode 100644 index 000000000..07f4107d9 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glphbm.c @@ -0,0 +1,529 @@ +/* glphbm.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glphbm.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* hbm_read_mat - read sparse matrix in Harwell-Boeing format +* +* SYNOPSIS +* +* #include "glphbm.h" +* HBM *hbm_read_mat(const char *fname); +* +* DESCRIPTION +* +* The routine hbm_read_mat reads a sparse matrix in the Harwell-Boeing +* format from a text file whose name is the character string fname. +* +* Detailed description of the Harwell-Boeing format recognised by this +* routine is given in the following report: +* +* I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the Harwell-Boeing +* Sparse Matrix Collection (Release I), TR/PA/92/86, October 1992. +* +* RETURNS +* +* If no error occured, the routine hbm_read_mat returns a pointer to +* a data structure containing the matrix. In case of error the routine +* prints an appropriate error message and returns NULL. */ + +struct dsa +{ /* working area used by routine hbm_read_mat */ + const char *fname; + /* name of input text file */ + FILE *fp; + /* stream assigned to input text file */ + int seqn; + /* card sequential number */ + char card[80+1]; + /* card image buffer */ + int fmt_p; + /* scale factor */ + int fmt_k; + /* iterator */ + int fmt_f; + /* format code */ + int fmt_w; + /* field width */ + int fmt_d; + /* number of decimal places after point */ +}; + +/*********************************************************************** +* read_card - read next data card +* +* This routine reads the next 80-column card from the input text file +* and stores its image into the character string card. If the card was +* read successfully, the routine returns zero, otherwise non-zero. */ + +#if 1 /* 11/III-2012 */ +static int read_card(struct dsa *dsa) +{ int c, len = 0; + char buf[255+1]; + dsa->seqn++; + for (;;) + { c = fgetc(dsa->fp); + if (c == EOF) + { if (ferror(dsa->fp)) + xprintf("%s:%d: read error\n", + dsa->fname, dsa->seqn); + else + xprintf("%s:%d: unexpected end-of-file\n", + dsa->fname, dsa->seqn); + return 1; + } + else if (c == '\r') + /* nop */; + else if (c == '\n') + break; + else if (iscntrl(c)) + { xprintf("%s:%d: invalid control character\n", + dsa->fname, dsa->seqn, c); + return 1; + } + else + { if (len == sizeof(buf)-1) + goto err; + buf[len++] = (char)c; + } + } + /* remove trailing spaces */ + while (len > 80 && buf[len-1] == ' ') + len--; + buf[len] = '\0'; + /* line should not be longer than 80 chars */ + if (len > 80) +err: { xerror("%s:%d: card image too long\n", + dsa->fname, dsa->seqn); + return 1; + } + /* padd by spaces to 80-column card image */ + strcpy(dsa->card, buf); + memset(&dsa->card[len], ' ', 80 - len); + dsa->card[80] = '\0'; + return 0; +} +#endif + +/*********************************************************************** +* scan_int - scan integer value from the current card +* +* This routine scans an integer value from the current card, where fld +* is the name of the field, pos is the position of the field, width is +* the width of the field, val points to a location to which the scanned +* value should be stored. If the value was scanned successfully, the +* routine returns zero, otherwise non-zero. */ + +static int scan_int(struct dsa *dsa, char *fld, int pos, int width, + int *val) +{ char str[80+1]; + xassert(1 <= width && width <= 80); + memcpy(str, dsa->card + pos, width), str[width] = '\0'; + if (str2int(strspx(str), val)) + { xprintf("%s:%d: field `%s' contains invalid value `%s'\n", + dsa->fname, dsa->seqn, fld, str); + return 1; + } + return 0; +} + +/*********************************************************************** +* parse_fmt - parse Fortran format specification +* +* This routine parses the Fortran format specification represented as +* character string which fmt points to and stores format elements into +* appropriate static locations. Should note that not all valid Fortran +* format specifications may be recognised. If the format specification +* was recognised, the routine returns zero, otherwise non-zero. */ + +static int parse_fmt(struct dsa *dsa, char *fmt) +{ int k, s, val; + char str[80+1]; + /* first character should be left parenthesis */ + if (fmt[0] != '(') +fail: { xprintf("hbm_read_mat: format `%s' not recognised\n", fmt); + return 1; + } + k = 1; + /* optional scale factor */ + dsa->fmt_p = 0; + if (isdigit((unsigned char)fmt[k])) + { s = 0; + while (isdigit((unsigned char)fmt[k])) + { if (s == 80) goto fail; + str[s++] = fmt[k++]; + } + str[s] = '\0'; + if (str2int(str, &val)) goto fail; + if (toupper((unsigned char)fmt[k]) != 'P') goto iter; + dsa->fmt_p = val, k++; + if (!(0 <= dsa->fmt_p && dsa->fmt_p <= 255)) goto fail; + /* optional comma may follow scale factor */ + if (fmt[k] == ',') k++; + } + /* optional iterator */ + dsa->fmt_k = 1; + if (isdigit((unsigned char)fmt[k])) + { s = 0; + while (isdigit((unsigned char)fmt[k])) + { if (s == 80) goto fail; + str[s++] = fmt[k++]; + } + str[s] = '\0'; + if (str2int(str, &val)) goto fail; +iter: dsa->fmt_k = val; + if (!(1 <= dsa->fmt_k && dsa->fmt_k <= 255)) goto fail; + } + /* format code */ + dsa->fmt_f = toupper((unsigned char)fmt[k++]); + if (!(dsa->fmt_f == 'D' || dsa->fmt_f == 'E' || + dsa->fmt_f == 'F' || dsa->fmt_f == 'G' || + dsa->fmt_f == 'I')) goto fail; + /* field width */ + if (!isdigit((unsigned char)fmt[k])) goto fail; + s = 0; + while (isdigit((unsigned char)fmt[k])) + { if (s == 80) goto fail; + str[s++] = fmt[k++]; + } + str[s] = '\0'; + if (str2int(str, &dsa->fmt_w)) goto fail; + if (!(1 <= dsa->fmt_w && dsa->fmt_w <= 255)) goto fail; + /* optional number of decimal places after point */ + dsa->fmt_d = 0; + if (fmt[k] == '.') + { k++; + if (!isdigit((unsigned char)fmt[k])) goto fail; + s = 0; + while (isdigit((unsigned char)fmt[k])) + { if (s == 80) goto fail; + str[s++] = fmt[k++]; + } + str[s] = '\0'; + if (str2int(str, &dsa->fmt_d)) goto fail; + if (!(0 <= dsa->fmt_d && dsa->fmt_d <= 255)) goto fail; + } + /* last character should be right parenthesis */ + if (!(fmt[k] == ')' && fmt[k+1] == '\0')) goto fail; + return 0; +} + +/*********************************************************************** +* read_int_array - read array of integer type +* +* This routine reads an integer array from the input text file, where +* name is array name, fmt is Fortran format specification that controls +* reading, n is number of array elements, val is array of integer type. +* If the array was read successful, the routine returns zero, otherwise +* non-zero. */ + +static int read_int_array(struct dsa *dsa, char *name, char *fmt, + int n, int val[]) +{ int k, pos; + char str[80+1]; + if (parse_fmt(dsa, fmt)) return 1; + if (!(dsa->fmt_f == 'I' && dsa->fmt_w <= 80 && + dsa->fmt_k * dsa->fmt_w <= 80)) + { xprintf( + "%s:%d: can't read array `%s' - invalid format `%s'\n", + dsa->fname, dsa->seqn, name, fmt); + return 1; + } + for (k = 1, pos = INT_MAX; k <= n; k++, pos++) + { if (pos >= dsa->fmt_k) + { if (read_card(dsa)) return 1; + pos = 0; + } + memcpy(str, dsa->card + dsa->fmt_w * pos, dsa->fmt_w); + str[dsa->fmt_w] = '\0'; + strspx(str); + if (str2int(str, &val[k])) + { xprintf( + "%s:%d: can't read array `%s' - invalid value `%s'\n", + dsa->fname, dsa->seqn, name, str); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* read_real_array - read array of real type +* +* This routine reads a real array from the input text file, where name +* is array name, fmt is Fortran format specification that controls +* reading, n is number of array elements, val is array of real type. +* If the array was read successful, the routine returns zero, otherwise +* non-zero. */ + +static int read_real_array(struct dsa *dsa, char *name, char *fmt, + int n, double val[]) +{ int k, pos; + char str[80+1], *ptr; + if (parse_fmt(dsa, fmt)) return 1; + if (!(dsa->fmt_f != 'I' && dsa->fmt_w <= 80 && + dsa->fmt_k * dsa->fmt_w <= 80)) + { xprintf( + "%s:%d: can't read array `%s' - invalid format `%s'\n", + dsa->fname, dsa->seqn, name, fmt); + return 1; + } + for (k = 1, pos = INT_MAX; k <= n; k++, pos++) + { if (pos >= dsa->fmt_k) + { if (read_card(dsa)) return 1; + pos = 0; + } + memcpy(str, dsa->card + dsa->fmt_w * pos, dsa->fmt_w); + str[dsa->fmt_w] = '\0'; + strspx(str); + if (strchr(str, '.') == NULL && strcmp(str, "0")) + { xprintf("%s(%d): can't read array `%s' - value `%s' has no " + "decimal point\n", dsa->fname, dsa->seqn, name, str); + return 1; + } + /* sometimes lower case letters appear */ + for (ptr = str; *ptr; ptr++) + *ptr = (char)toupper((unsigned char)*ptr); + ptr = strchr(str, 'D'); + if (ptr != NULL) *ptr = 'E'; + /* value may appear with decimal exponent but without letters + E or D (for example, -123.456-012), so missing letter should + be inserted */ + ptr = strchr(str+1, '+'); + if (ptr == NULL) ptr = strchr(str+1, '-'); + if (ptr != NULL && *(ptr-1) != 'E') + { xassert(strlen(str) < 80); + memmove(ptr+1, ptr, strlen(ptr)+1); + *ptr = 'E'; + } + if (str2num(str, &val[k])) + { xprintf( + "%s:%d: can't read array `%s' - invalid value `%s'\n", + dsa->fname, dsa->seqn, name, str); + return 1; + } + } + return 0; +} + +HBM *hbm_read_mat(const char *fname) +{ struct dsa _dsa, *dsa = &_dsa; + HBM *hbm = NULL; + dsa->fname = fname; + xprintf("hbm_read_mat: reading matrix from `%s'...\n", + dsa->fname); + dsa->fp = fopen(dsa->fname, "r"); + if (dsa->fp == NULL) + { xprintf("hbm_read_mat: unable to open `%s' - %s\n", + dsa->fname, strerror(errno)); + goto fail; + } + dsa->seqn = 0; + hbm = xmalloc(sizeof(HBM)); + memset(hbm, 0, sizeof(HBM)); + /* read the first heading card */ + if (read_card(dsa)) goto fail; + memcpy(hbm->title, dsa->card, 72), hbm->title[72] = '\0'; + strtrim(hbm->title); + xprintf("%s\n", hbm->title); + memcpy(hbm->key, dsa->card+72, 8), hbm->key[8] = '\0'; + strspx(hbm->key); + xprintf("key = %s\n", hbm->key); + /* read the second heading card */ + if (read_card(dsa)) goto fail; + if (scan_int(dsa, "totcrd", 0, 14, &hbm->totcrd)) goto fail; + if (scan_int(dsa, "ptrcrd", 14, 14, &hbm->ptrcrd)) goto fail; + if (scan_int(dsa, "indcrd", 28, 14, &hbm->indcrd)) goto fail; + if (scan_int(dsa, "valcrd", 42, 14, &hbm->valcrd)) goto fail; + if (scan_int(dsa, "rhscrd", 56, 14, &hbm->rhscrd)) goto fail; + xprintf("totcrd = %d; ptrcrd = %d; indcrd = %d; valcrd = %d; rhsc" + "rd = %d\n", hbm->totcrd, hbm->ptrcrd, hbm->indcrd, + hbm->valcrd, hbm->rhscrd); + /* read the third heading card */ + if (read_card(dsa)) goto fail; + memcpy(hbm->mxtype, dsa->card, 3), hbm->mxtype[3] = '\0'; + if (strchr("RCP", hbm->mxtype[0]) == NULL || + strchr("SUHZR", hbm->mxtype[1]) == NULL || + strchr("AE", hbm->mxtype[2]) == NULL) + { xprintf("%s:%d: matrix type `%s' not recognised\n", + dsa->fname, dsa->seqn, hbm->mxtype); + goto fail; + } + if (scan_int(dsa, "nrow", 14, 14, &hbm->nrow)) goto fail; + if (scan_int(dsa, "ncol", 28, 14, &hbm->ncol)) goto fail; + if (scan_int(dsa, "nnzero", 42, 14, &hbm->nnzero)) goto fail; + if (scan_int(dsa, "neltvl", 56, 14, &hbm->neltvl)) goto fail; + xprintf("mxtype = %s; nrow = %d; ncol = %d; nnzero = %d; neltvl =" + " %d\n", hbm->mxtype, hbm->nrow, hbm->ncol, hbm->nnzero, + hbm->neltvl); + /* read the fourth heading card */ + if (read_card(dsa)) goto fail; + memcpy(hbm->ptrfmt, dsa->card, 16), hbm->ptrfmt[16] = '\0'; + strspx(hbm->ptrfmt); + memcpy(hbm->indfmt, dsa->card+16, 16), hbm->indfmt[16] = '\0'; + strspx(hbm->indfmt); + memcpy(hbm->valfmt, dsa->card+32, 20), hbm->valfmt[20] = '\0'; + strspx(hbm->valfmt); + memcpy(hbm->rhsfmt, dsa->card+52, 20), hbm->rhsfmt[20] = '\0'; + strspx(hbm->rhsfmt); + xprintf("ptrfmt = %s; indfmt = %s; valfmt = %s; rhsfmt = %s\n", + hbm->ptrfmt, hbm->indfmt, hbm->valfmt, hbm->rhsfmt); + /* read the fifth heading card (optional) */ + if (hbm->rhscrd <= 0) + { strcpy(hbm->rhstyp, "???"); + hbm->nrhs = 0; + hbm->nrhsix = 0; + } + else + { if (read_card(dsa)) goto fail; + memcpy(hbm->rhstyp, dsa->card, 3), hbm->rhstyp[3] = '\0'; + if (scan_int(dsa, "nrhs", 14, 14, &hbm->nrhs)) goto fail; + if (scan_int(dsa, "nrhsix", 28, 14, &hbm->nrhsix)) goto fail; + xprintf("rhstyp = `%s'; nrhs = %d; nrhsix = %d\n", + hbm->rhstyp, hbm->nrhs, hbm->nrhsix); + } + /* read matrix structure */ + hbm->colptr = xcalloc(1+hbm->ncol+1, sizeof(int)); + if (read_int_array(dsa, "colptr", hbm->ptrfmt, hbm->ncol+1, + hbm->colptr)) goto fail; + hbm->rowind = xcalloc(1+hbm->nnzero, sizeof(int)); + if (read_int_array(dsa, "rowind", hbm->indfmt, hbm->nnzero, + hbm->rowind)) goto fail; + /* read matrix values */ + if (hbm->valcrd <= 0) goto done; + if (hbm->mxtype[2] == 'A') + { /* assembled matrix */ + hbm->values = xcalloc(1+hbm->nnzero, sizeof(double)); + if (read_real_array(dsa, "values", hbm->valfmt, hbm->nnzero, + hbm->values)) goto fail; + } + else + { /* elemental (unassembled) matrix */ + hbm->values = xcalloc(1+hbm->neltvl, sizeof(double)); + if (read_real_array(dsa, "values", hbm->valfmt, hbm->neltvl, + hbm->values)) goto fail; + } + /* read right-hand sides */ + if (hbm->nrhs <= 0) goto done; + if (hbm->rhstyp[0] == 'F') + { /* dense format */ + hbm->nrhsvl = hbm->nrow * hbm->nrhs; + hbm->rhsval = xcalloc(1+hbm->nrhsvl, sizeof(double)); + if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsvl, + hbm->rhsval)) goto fail; + } + else if (hbm->rhstyp[0] == 'M' && hbm->mxtype[2] == 'A') + { /* sparse format */ + /* read pointers */ + hbm->rhsptr = xcalloc(1+hbm->nrhs+1, sizeof(int)); + if (read_int_array(dsa, "rhsptr", hbm->ptrfmt, hbm->nrhs+1, + hbm->rhsptr)) goto fail; + /* read sparsity pattern */ + hbm->rhsind = xcalloc(1+hbm->nrhsix, sizeof(int)); + if (read_int_array(dsa, "rhsind", hbm->indfmt, hbm->nrhsix, + hbm->rhsind)) goto fail; + /* read values */ + hbm->rhsval = xcalloc(1+hbm->nrhsix, sizeof(double)); + if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsix, + hbm->rhsval)) goto fail; + } + else if (hbm->rhstyp[0] == 'M' && hbm->mxtype[2] == 'E') + { /* elemental format */ + hbm->rhsval = xcalloc(1+hbm->nrhsvl, sizeof(double)); + if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsvl, + hbm->rhsval)) goto fail; + } + else + { xprintf("%s:%d: right-hand side type `%c' not recognised\n", + dsa->fname, dsa->seqn, hbm->rhstyp[0]); + goto fail; + } + /* read starting guesses */ + if (hbm->rhstyp[1] == 'G') + { hbm->nguess = hbm->nrow * hbm->nrhs; + hbm->sguess = xcalloc(1+hbm->nguess, sizeof(double)); + if (read_real_array(dsa, "sguess", hbm->rhsfmt, hbm->nguess, + hbm->sguess)) goto fail; + } + /* read solution vectors */ + if (hbm->rhstyp[2] == 'X') + { hbm->nexact = hbm->nrow * hbm->nrhs; + hbm->xexact = xcalloc(1+hbm->nexact, sizeof(double)); + if (read_real_array(dsa, "xexact", hbm->rhsfmt, hbm->nexact, + hbm->xexact)) goto fail; + } +done: /* reading has been completed */ + xprintf("hbm_read_mat: %d cards were read\n", dsa->seqn); + fclose(dsa->fp); + return hbm; +fail: /* something wrong in Danish kingdom */ + if (hbm != NULL) + { if (hbm->colptr != NULL) xfree(hbm->colptr); + if (hbm->rowind != NULL) xfree(hbm->rowind); + if (hbm->rhsptr != NULL) xfree(hbm->rhsptr); + if (hbm->rhsind != NULL) xfree(hbm->rhsind); + if (hbm->values != NULL) xfree(hbm->values); + if (hbm->rhsval != NULL) xfree(hbm->rhsval); + if (hbm->sguess != NULL) xfree(hbm->sguess); + if (hbm->xexact != NULL) xfree(hbm->xexact); + xfree(hbm); + } + if (dsa->fp != NULL) fclose(dsa->fp); + return NULL; +} + +/*********************************************************************** +* NAME +* +* hbm_free_mat - free sparse matrix in Harwell-Boeing format +* +* SYNOPSIS +* +* #include "glphbm.h" +* void hbm_free_mat(HBM *hbm); +* +* DESCRIPTION +* +* The hbm_free_mat routine frees all the memory allocated to the data +* structure containing a sparse matrix in the Harwell-Boeing format. */ + +void hbm_free_mat(HBM *hbm) +{ if (hbm->colptr != NULL) xfree(hbm->colptr); + if (hbm->rowind != NULL) xfree(hbm->rowind); + if (hbm->rhsptr != NULL) xfree(hbm->rhsptr); + if (hbm->rhsind != NULL) xfree(hbm->rhsind); + if (hbm->values != NULL) xfree(hbm->values); + if (hbm->rhsval != NULL) xfree(hbm->rhsval); + if (hbm->sguess != NULL) xfree(hbm->sguess); + if (hbm->xexact != NULL) xfree(hbm->xexact); + xfree(hbm); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glphbm.h b/resources/3rdparty/glpk-4.53/src/glphbm.h new file mode 100644 index 000000000..688a78ec1 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glphbm.h @@ -0,0 +1,127 @@ +/* glphbm.h (Harwell-Boeing sparse matrix format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPHBM_H +#define GLPHBM_H + +typedef struct HBM HBM; + +struct HBM +{ /* sparse matrix in Harwell-Boeing format; for details see the + report: I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the + Harwell-Boeing Sparse Matrix Collection (Release I), 1992 */ + char title[72+1]; + /* matrix title (informative) */ + char key[8+1]; + /* matrix key (informative) */ + char mxtype[3+1]; + /* matrix type: + R.. real matrix + C.. complex matrix + P.. pattern only (no numerical values supplied) + .S. symmetric (lower triangle + main diagonal) + .U. unsymmetric + .H. hermitian (lower triangle + main diagonal) + .Z. skew symmetric (lower triangle only) + .R. rectangular + ..A assembled + ..E elemental (unassembled) */ + char rhstyp[3+1]; + /* optional types: + F.. right-hand sides in dense format + M.. right-hand sides in same format as matrix + .G. starting vector(s) (guess) is supplied + ..X exact solution vector(s) is supplied */ + char ptrfmt[16+1]; + /* format for pointers */ + char indfmt[16+1]; + /* format for row (or variable) indices */ + char valfmt[20+1]; + /* format for numerical values of coefficient matrix */ + char rhsfmt[20+1]; + /* format for numerical values of right-hand sides */ + int totcrd; + /* total number of cards excluding header */ + int ptrcrd; + /* number of cards for ponters */ + int indcrd; + /* number of cards for row (or variable) indices */ + int valcrd; + /* number of cards for numerical values */ + int rhscrd; + /* number of lines for right-hand sides; + including starting guesses and solution vectors if present; + zero indicates no right-hand side data is present */ + int nrow; + /* number of rows (or variables) */ + int ncol; + /* number of columns (or elements) */ + int nnzero; + /* number of row (or variable) indices; + equal to number of entries for assembled matrix */ + int neltvl; + /* number of elemental matrix entries; + zero in case of assembled matrix */ + int nrhs; + /* number of right-hand sides */ + int nrhsix; + /* number of row indices; + ignored in case of unassembled matrix */ + int nrhsvl; + /* total number of entries in all right-hand sides */ + int nguess; + /* total number of entries in all starting guesses */ + int nexact; + /* total number of entries in all solution vectors */ + int *colptr; /* alias: eltptr */ + /* column pointers (in case of assembled matrix); + elemental matrix pointers (in case of unassembled matrix) */ + int *rowind; /* alias: varind */ + /* row indices (in case of assembled matrix); + variable indices (in case of unassembled matrix) */ + int *rhsptr; + /* right-hand side pointers */ + int *rhsind; + /* right-hand side indices */ + double *values; + /* matrix values */ + double *rhsval; + /* right-hand side values */ + double *sguess; + /* starting guess values */ + double *xexact; + /* solution vector values */ +}; + +#define hbm_read_mat _glp_hbm_read_mat +HBM *hbm_read_mat(const char *fname); +/* read sparse matrix in Harwell-Boeing format */ + +#define hbm_free_mat _glp_hbm_free_mat +void hbm_free_mat(HBM *hbm); +/* free sparse matrix in Harwell-Boeing format */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpini01.c b/resources/3rdparty/glpk-4.53/src/glpini01.c new file mode 100644 index 000000000..76c021477 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpini01.c @@ -0,0 +1,155 @@ +/* glpini01.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "prob.h" +#include "triang.h" + +/*********************************************************************** +* NAME +* +* glp_adv_basis - construct advanced initial LP basis +* +* SYNOPSIS +* +* void glp_adv_basis(glp_prob *P, int flags); +* +* DESCRIPTION +* +* The routine glp_adv_basis constructs an advanced initial LP basis +* for the specified problem object. +* +* The parameter flag is reserved for use in the future and should be +* specified as zero. +* +* NOTE +* +* The routine glp_adv_basis should be called after the constraint +* matrix has been scaled (if scaling is used). */ + +static int mat(void *info, int k, int ind[], double val[]) +{ glp_prob *P = info; + int m = P->m; + int n = P->n; + GLPROW **row = P->row; + GLPCOL **col = P->col; + GLPAIJ *aij; + int i, j, len; + if (k > 0) + { /* retrieve scaled row of constraint matrix */ + i = +k; + xassert(1 <= i && i <= m); + len = 0; + if (row[i]->type == GLP_FX) + { for (aij = row[i]->ptr; aij != NULL; aij = aij->r_next) + { j = aij->col->j; + if (col[j]->type != GLP_FX) + { len++; + ind[len] = j; + val[len] = aij->row->rii * aij->val * aij->col->sjj; + } + } + } + } + else + { /* retrieve scaled column of constraint matrix */ + j = -k; + xassert(1 <= j && j <= n); + len = 0; + if (col[j]->type != GLP_FX) + { for (aij = col[j]->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row->i; + if (row[i]->type == GLP_FX) + { len++; + ind[len] = i; + val[len] = aij->row->rii * aij->val * aij->col->sjj; + } + } + } + } + return len; +} + +void glp_adv_basis(glp_prob *P, int flags) +{ int i, j, k, m, n, min_mn, size, *rn, *cn; + char *flag; + if (flags != 0) + xerror("glp_adv_basis: flags = %d; invalid flags\n", flags); + m = P->m; /* number of rows */ + n = P->n; /* number of columns */ + if (m == 0 || n == 0) + { /* trivial case */ + glp_std_basis(P); + goto done; + } + xprintf("Constructing initial basis...\n"); + /* allocate working arrays */ + min_mn = (m < n ? m : n); + rn = talloc(1+min_mn, int); + cn = talloc(1+min_mn, int); + flag = talloc(1+m, char); + /* make the basis empty */ + for (i = 1; i <= m; i++) + { flag[i] = 0; + glp_set_row_stat(P, i, GLP_NS); + } + for (j = 1; j <= n; j++) + glp_set_col_stat(P, j, GLP_NS); + /* find maximal triangular part of the constraint matrix; + to prevent including non-fixed rows and fixed columns in the + triangular part, such rows and columns are temporarily made + empty by the routine mat */ +#if 1 /* FIXME: tolerance */ + size = triang(m, n, mat, P, 0.001, rn, cn); +#endif + xassert(0 <= size && size <= min_mn); + /* include in the basis non-fixed structural variables, whose + columns constitute the triangular part */ + for (k = 1; k <= size; k++) + { i = rn[k]; + xassert(1 <= i && i <= m); + flag[i] = 1; + j = cn[k]; + xassert(1 <= j && j <= n); + glp_set_col_stat(P, j, GLP_BS); + } + /* include in the basis appropriate auxiliary variables, whose + unity columns preserve triangular form of the basis matrix */ + for (i = 1; i <= m; i++) + { if (flag[i] == 0) + { glp_set_row_stat(P, i, GLP_BS); + if (P->row[i]->type != GLP_FX) + size++; + } + } + /* size of triangular part = (number of rows) - (number of basic + fixed auxiliary variables) */ + xprintf("Size of triangular part is %d\n", size); + /* deallocate working arrays */ + tfree(rn); + tfree(cn); + tfree(flag); +done: return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpini02.c b/resources/3rdparty/glpk-4.53/src/glpini02.c new file mode 100644 index 000000000..6aad59feb --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpini02.c @@ -0,0 +1,270 @@ +/* glpini02.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +struct var +{ /* structural variable */ + int j; + /* ordinal number */ + double q; + /* penalty value */ +}; + +static int fcmp(const void *ptr1, const void *ptr2) +{ /* this routine is passed to the qsort() function */ + struct var *col1 = (void *)ptr1, *col2 = (void *)ptr2; + if (col1->q < col2->q) return -1; + if (col1->q > col2->q) return +1; + return 0; +} + +static int get_column(glp_prob *lp, int j, int ind[], double val[]) +{ /* Bixby's algorithm assumes that the constraint matrix is scaled + such that the maximum absolute value in every non-zero row and + column is 1 */ + int k, len; + double big; + len = glp_get_mat_col(lp, j, ind, val); + big = 0.0; + for (k = 1; k <= len; k++) + if (big < fabs(val[k])) big = fabs(val[k]); + if (big == 0.0) big = 1.0; + for (k = 1; k <= len; k++) val[k] /= big; + return len; +} + +static void cpx_basis(glp_prob *lp) +{ /* main routine */ + struct var *C, *C2, *C3, *C4; + int m, n, i, j, jk, k, l, ll, t, n2, n3, n4, type, len, *I, *r, + *ind; + double alpha, gamma, cmax, temp, *v, *val; + xprintf("Constructing initial basis...\n"); + /* determine the number of rows and columns */ + m = glp_get_num_rows(lp); + n = glp_get_num_cols(lp); + /* allocate working arrays */ + C = xcalloc(1+n, sizeof(struct var)); + I = xcalloc(1+m, sizeof(int)); + r = xcalloc(1+m, sizeof(int)); + v = xcalloc(1+m, sizeof(double)); + ind = xcalloc(1+m, sizeof(int)); + val = xcalloc(1+m, sizeof(double)); + /* make all auxiliary variables non-basic */ + for (i = 1; i <= m; i++) + { if (glp_get_row_type(lp, i) != GLP_DB) + glp_set_row_stat(lp, i, GLP_NS); + else if (fabs(glp_get_row_lb(lp, i)) <= + fabs(glp_get_row_ub(lp, i))) + glp_set_row_stat(lp, i, GLP_NL); + else + glp_set_row_stat(lp, i, GLP_NU); + } + /* make all structural variables non-basic */ + for (j = 1; j <= n; j++) + { if (glp_get_col_type(lp, j) != GLP_DB) + glp_set_col_stat(lp, j, GLP_NS); + else if (fabs(glp_get_col_lb(lp, j)) <= + fabs(glp_get_col_ub(lp, j))) + glp_set_col_stat(lp, j, GLP_NL); + else + glp_set_col_stat(lp, j, GLP_NU); + } + /* C2 is a set of free structural variables */ + n2 = 0, C2 = C + 0; + for (j = 1; j <= n; j++) + { type = glp_get_col_type(lp, j); + if (type == GLP_FR) + { n2++; + C2[n2].j = j; + C2[n2].q = 0.0; + } + } + /* C3 is a set of structural variables having excatly one (lower + or upper) bound */ + n3 = 0, C3 = C2 + n2; + for (j = 1; j <= n; j++) + { type = glp_get_col_type(lp, j); + if (type == GLP_LO) + { n3++; + C3[n3].j = j; + C3[n3].q = + glp_get_col_lb(lp, j); + } + else if (type == GLP_UP) + { n3++; + C3[n3].j = j; + C3[n3].q = - glp_get_col_ub(lp, j); + } + } + /* C4 is a set of structural variables having both (lower and + upper) bounds */ + n4 = 0, C4 = C3 + n3; + for (j = 1; j <= n; j++) + { type = glp_get_col_type(lp, j); + if (type == GLP_DB) + { n4++; + C4[n4].j = j; + C4[n4].q = glp_get_col_lb(lp, j) - glp_get_col_ub(lp, j); + } + } + /* compute gamma = max{|c[j]|: 1 <= j <= n} */ + gamma = 0.0; + for (j = 1; j <= n; j++) + { temp = fabs(glp_get_obj_coef(lp, j)); + if (gamma < temp) gamma = temp; + } + /* compute cmax */ + cmax = (gamma == 0.0 ? 1.0 : 1000.0 * gamma); + /* compute final penalty for all structural variables within sets + C2, C3, and C4 */ + switch (glp_get_obj_dir(lp)) + { case GLP_MIN: temp = +1.0; break; + case GLP_MAX: temp = -1.0; break; + default: xassert(lp != lp); + } + for (k = 1; k <= n2+n3+n4; k++) + { j = C[k].j; + C[k].q += (temp * glp_get_obj_coef(lp, j)) / cmax; + } + /* sort structural variables within C2, C3, and C4 in ascending + order of penalty value */ + qsort(C2+1, n2, sizeof(struct var), fcmp); + for (k = 1; k < n2; k++) xassert(C2[k].q <= C2[k+1].q); + qsort(C3+1, n3, sizeof(struct var), fcmp); + for (k = 1; k < n3; k++) xassert(C3[k].q <= C3[k+1].q); + qsort(C4+1, n4, sizeof(struct var), fcmp); + for (k = 1; k < n4; k++) xassert(C4[k].q <= C4[k+1].q); + /*** STEP 1 ***/ + for (i = 1; i <= m; i++) + { type = glp_get_row_type(lp, i); + if (type != GLP_FX) + { /* row i is either free or inequality constraint */ + glp_set_row_stat(lp, i, GLP_BS); + I[i] = 1; + r[i] = 1; + } + else + { /* row i is equality constraint */ + I[i] = 0; + r[i] = 0; + } + v[i] = +DBL_MAX; + } + /*** STEP 2 ***/ + for (k = 1; k <= n2+n3+n4; k++) + { jk = C[k].j; + len = get_column(lp, jk, ind, val); + /* let alpha = max{|A[l,jk]|: r[l] = 0} and let l' be such + that alpha = |A[l',jk]| */ + alpha = 0.0, ll = 0; + for (t = 1; t <= len; t++) + { l = ind[t]; + if (r[l] == 0 && alpha < fabs(val[t])) + alpha = fabs(val[t]), ll = l; + } + if (alpha >= 0.99) + { /* B := B union {jk} */ + glp_set_col_stat(lp, jk, GLP_BS); + I[ll] = 1; + v[ll] = alpha; + /* r[l] := r[l] + 1 for all l such that |A[l,jk]| != 0 */ + for (t = 1; t <= len; t++) + { l = ind[t]; + if (val[t] != 0.0) r[l]++; + } + /* continue to the next k */ + continue; + } + /* if |A[l,jk]| > 0.01 * v[l] for some l, continue to the + next k */ + for (t = 1; t <= len; t++) + { l = ind[t]; + if (fabs(val[t]) > 0.01 * v[l]) break; + } + if (t <= len) continue; + /* otherwise, let alpha = max{|A[l,jk]|: I[l] = 0} and let l' + be such that alpha = |A[l',jk]| */ + alpha = 0.0, ll = 0; + for (t = 1; t <= len; t++) + { l = ind[t]; + if (I[l] == 0 && alpha < fabs(val[t])) + alpha = fabs(val[t]), ll = l; + } + /* if alpha = 0, continue to the next k */ + if (alpha == 0.0) continue; + /* B := B union {jk} */ + glp_set_col_stat(lp, jk, GLP_BS); + I[ll] = 1; + v[ll] = alpha; + /* r[l] := r[l] + 1 for all l such that |A[l,jk]| != 0 */ + for (t = 1; t <= len; t++) + { l = ind[t]; + if (val[t] != 0.0) r[l]++; + } + } + /*** STEP 3 ***/ + /* add an artificial variable (auxiliary variable for equality + constraint) to cover each remaining uncovered row */ + for (i = 1; i <= m; i++) + if (I[i] == 0) glp_set_row_stat(lp, i, GLP_BS); + /* free working arrays */ + xfree(C); + xfree(I); + xfree(r); + xfree(v); + xfree(ind); + xfree(val); + return; +} + +/*********************************************************************** +* NAME +* +* glp_cpx_basis - construct Bixby's initial LP basis +* +* SYNOPSIS +* +* void glp_cpx_basis(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_cpx_basis constructs an advanced initial basis for +* the specified problem object. +* +* The routine is based on Bixby's algorithm described in the paper: +* +* Robert E. Bixby. Implementing the Simplex Method: The Initial Basis. +* ORSA Journal on Computing, Vol. 4, No. 3, 1992, pp. 267-84. */ + +void glp_cpx_basis(glp_prob *lp) +{ if (lp->m == 0 || lp->n == 0) + glp_std_basis(lp); + else + cpx_basis(lp); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios.h b/resources/3rdparty/glpk-4.53/src/glpios.h new file mode 100644 index 000000000..07ee9810e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios.h @@ -0,0 +1,620 @@ +/* glpios.h (integer optimization suite) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPIOS_H +#define GLPIOS_H + +#include "prob.h" + +typedef struct IOSLOT IOSLOT; +typedef struct IOSNPD IOSNPD; +typedef struct IOSBND IOSBND; +typedef struct IOSTAT IOSTAT; +typedef struct IOSROW IOSROW; +typedef struct IOSAIJ IOSAIJ; +typedef struct IOSPOOL IOSPOOL; +typedef struct IOSCUT IOSCUT; + +struct glp_tree +{ /* branch-and-bound tree */ + int magic; + /* magic value used for debugging */ + DMP *pool; + /* memory pool to store all IOS components */ + int n; + /* number of columns (variables) */ + /*--------------------------------------------------------------*/ + /* problem components corresponding to the original MIP and its + LP relaxation (used to restore the original problem object on + exit from the solver) */ + int orig_m; + /* number of rows */ + unsigned char *orig_type; /* uchar orig_type[1+orig_m+n]; */ + /* types of all variables */ + double *orig_lb; /* double orig_lb[1+orig_m+n]; */ + /* lower bounds of all variables */ + double *orig_ub; /* double orig_ub[1+orig_m+n]; */ + /* upper bounds of all variables */ + unsigned char *orig_stat; /* uchar orig_stat[1+orig_m+n]; */ + /* statuses of all variables */ + double *orig_prim; /* double orig_prim[1+orig_m+n]; */ + /* primal values of all variables */ + double *orig_dual; /* double orig_dual[1+orig_m+n]; */ + /* dual values of all variables */ + double orig_obj; + /* optimal objective value for LP relaxation */ + /*--------------------------------------------------------------*/ + /* branch-and-bound tree */ + int nslots; + /* length of the array of slots (enlarged automatically) */ + int avail; + /* index of the first free slot; 0 means all slots are in use */ + IOSLOT *slot; /* IOSLOT slot[1+nslots]; */ + /* array of slots: + slot[0] is not used; + slot[p], 1 <= p <= nslots, either contains a pointer to some + node of the branch-and-bound tree, in which case p is used on + API level as the reference number of corresponding subproblem, + or is free; all free slots are linked into single linked list; + slot[1] always contains a pointer to the root node (it is free + only if the tree is empty) */ + IOSNPD *head; + /* pointer to the head of the active list */ + IOSNPD *tail; + /* pointer to the tail of the active list */ + /* the active list is a doubly linked list of active subproblems + which correspond to leaves of the tree; all subproblems in the + active list are ordered chronologically (each a new subproblem + is always added to the tail of the list) */ + int a_cnt; + /* current number of active nodes (including the current one) */ + int n_cnt; + /* current number of all (active and inactive) nodes */ + int t_cnt; + /* total number of nodes including those which have been already + removed from the tree; this count is increased by one whenever + a new node is created and never decreased */ + /*--------------------------------------------------------------*/ + /* problem components corresponding to the root subproblem */ + int root_m; + /* number of rows */ + unsigned char *root_type; /* uchar root_type[1+root_m+n]; */ + /* types of all variables */ + double *root_lb; /* double root_lb[1+root_m+n]; */ + /* lower bounds of all variables */ + double *root_ub; /* double root_ub[1+root_m+n]; */ + /* upper bounds of all variables */ + unsigned char *root_stat; /* uchar root_stat[1+root_m+n]; */ + /* statuses of all variables */ + /*--------------------------------------------------------------*/ + /* current subproblem and its LP relaxation */ + IOSNPD *curr; + /* pointer to the current subproblem (which can be only active); + NULL means the current subproblem does not exist */ + glp_prob *mip; + /* original problem object passed to the solver; if the current + subproblem exists, its LP segment corresponds to LP relaxation + of the current subproblem; if the current subproblem does not + exist, its LP segment corresponds to LP relaxation of the root + subproblem (note that the root subproblem may differ from the + original MIP, because it may be preprocessed and/or may have + additional rows) */ + unsigned char *non_int; /* uchar non_int[1+n]; */ + /* these column flags are set each time when LP relaxation of the + current subproblem has been solved; + non_int[0] is not used; + non_int[j], 1 <= j <= n, is j-th column flag; if this flag is + set, corresponding variable is required to be integer, but its + value in basic solution is fractional */ + /*--------------------------------------------------------------*/ + /* problem components corresponding to the parent (predecessor) + subproblem for the current subproblem; used to inspect changes + on freezing the current subproblem */ + int pred_m; + /* number of rows */ + int pred_max; + /* length of the following four arrays (enlarged automatically), + pred_max >= pred_m + n */ + unsigned char *pred_type; /* uchar pred_type[1+pred_m+n]; */ + /* types of all variables */ + double *pred_lb; /* double pred_lb[1+pred_m+n]; */ + /* lower bounds of all variables */ + double *pred_ub; /* double pred_ub[1+pred_m+n]; */ + /* upper bounds of all variables */ + unsigned char *pred_stat; /* uchar pred_stat[1+pred_m+n]; */ + /* statuses of all variables */ + /****************************************************************/ + /* built-in cut generators segment */ + IOSPOOL *local; + /* local cut pool */ + void *mir_gen; + /* pointer to working area used by the MIR cut generator */ + void *clq_gen; + /* pointer to working area used by the clique cut generator */ + /*--------------------------------------------------------------*/ + void *pcost; + /* pointer to working area used on pseudocost branching */ + int *iwrk; /* int iwrk[1+n]; */ + /* working array */ + double *dwrk; /* double dwrk[1+n]; */ + /* working array */ + /*--------------------------------------------------------------*/ + /* control parameters and statistics */ + const glp_iocp *parm; + /* copy of control parameters passed to the solver */ +#if 0 /* 10/VI-2013 */ + glp_long tm_beg; +#else + double tm_beg; +#endif + /* starting time of the search, in seconds; the total time of the + search is the difference between xtime() and tm_beg */ +#if 0 /* 10/VI-2013 */ + glp_long tm_lag; +#else + double tm_lag; +#endif + /* the most recent time, in seconds, at which the progress of the + the search was displayed */ + int sol_cnt; + /* number of integer feasible solutions found */ +#if 1 /* 11/VII-2013 */ + void *P; /* glp_prob *P; */ + /* problem passed to glp_intopt */ + void *npp; /* NPP *npp; */ + /* preprocessor workspace or NULL */ + const char *save_sol; + /* filename (template) to save every new solution */ + int save_cnt; + /* count to generate filename */ +#endif + /*--------------------------------------------------------------*/ + /* advanced solver interface */ + int reason; + /* flag indicating the reason why the callback routine is being + called (see glpk.h) */ + int stop; + /* flag indicating that the callback routine requires premature + termination of the search */ + int next_p; + /* reference number of active subproblem selected to continue + the search; 0 means no subproblem has been selected */ + int reopt; + /* flag indicating that the current LP relaxation needs to be + re-optimized */ + int reinv; + /* flag indicating that some (non-active) rows were removed from + the current LP relaxation, so if there no new rows appear, the + basis must be re-factorized */ + int br_var; + /* the number of variable chosen to branch on */ + int br_sel; + /* flag indicating which branch (subproblem) is suggested to be + selected to continue the search: + GLP_DN_BRNCH - select down-branch + GLP_UP_BRNCH - select up-branch + GLP_NO_BRNCH - use general selection technique */ + int child; + /* subproblem reference number corresponding to br_sel */ +}; + +struct IOSLOT +{ /* node subproblem slot */ + IOSNPD *node; + /* pointer to subproblem descriptor; NULL means free slot */ + int next; + /* index of another free slot (only if this slot is free) */ +}; + +struct IOSNPD +{ /* node subproblem descriptor */ + int p; + /* subproblem reference number (it is the index to corresponding + slot, i.e. slot[p] points to this descriptor) */ + IOSNPD *up; + /* pointer to the parent subproblem; NULL means this node is the + root of the tree, in which case p = 1 */ + int level; + /* node level (the root node has level 0) */ + int count; + /* if count = 0, this subproblem is active; if count > 0, this + subproblem is inactive, in which case count is the number of + its child subproblems */ + /* the following three linked lists are destroyed on reviving and + built anew on freezing the subproblem: */ + IOSBND *b_ptr; + /* linked list of rows and columns of the parent subproblem whose + types and bounds were changed */ + IOSTAT *s_ptr; + /* linked list of rows and columns of the parent subproblem whose + statuses were changed */ + IOSROW *r_ptr; + /* linked list of rows (cuts) added to the parent subproblem */ + int solved; + /* how many times LP relaxation of this subproblem was solved; + for inactive subproblem this count is always non-zero; + for active subproblem, which is not current, this count may be + non-zero, if the subproblem was temporarily suspended */ + double lp_obj; + /* optimal objective value to LP relaxation of this subproblem; + on creating a subproblem this value is inherited from its + parent; for the root subproblem, which has no parent, this + value is initially set to -DBL_MAX (minimization) or +DBL_MAX + (maximization); each time the subproblem is re-optimized, this + value is appropriately changed */ + double bound; + /* local lower (minimization) or upper (maximization) bound for + integer optimal solution to *this* subproblem; this bound is + local in the sense that only subproblems in the subtree rooted + at this node cannot have better integer feasible solutions; + on creating a subproblem its local bound is inherited from its + parent and then can be made stronger (never weaker); for the + root subproblem its local bound is initially set to -DBL_MAX + (minimization) or +DBL_MAX (maximization) and then improved as + the root LP relaxation has been solved */ + /* the following two quantities are defined only if LP relaxation + of this subproblem was solved at least once (solved > 0): */ + int ii_cnt; + /* number of integer variables whose value in optimal solution to + LP relaxation of this subproblem is fractional */ + double ii_sum; + /* sum of integer infeasibilities */ +#if 1 /* 30/XI-2009 */ + int changed; + /* how many times this subproblem was re-formulated (by adding + cutting plane constraints) */ +#endif + int br_var; + /* ordinal number of branching variable, 1 <= br_var <= n, used + to split this subproblem; 0 means that either this subproblem + is active or branching was made on a constraint */ + double br_val; + /* (fractional) value of branching variable in optimal solution + to final LP relaxation of this subproblem */ + void *data; /* char data[tree->cb_size]; */ + /* pointer to the application-specific data */ + IOSNPD *temp; + /* working pointer used by some routines */ + IOSNPD *prev; + /* pointer to previous subproblem in the active list */ + IOSNPD *next; + /* pointer to next subproblem in the active list */ +}; + +struct IOSBND +{ /* bounds change entry */ + int k; + /* ordinal number of corresponding row (1 <= k <= m) or column + (m+1 <= k <= m+n), where m and n are the number of rows and + columns, resp., in the parent subproblem */ + unsigned char type; + /* new type */ + double lb; + /* new lower bound */ + double ub; + /* new upper bound */ + IOSBND *next; + /* pointer to next entry for the same subproblem */ +}; + +struct IOSTAT +{ /* status change entry */ + int k; + /* ordinal number of corresponding row (1 <= k <= m) or column + (m+1 <= k <= m+n), where m and n are the number of rows and + columns, resp., in the parent subproblem */ + unsigned char stat; + /* new status */ + IOSTAT *next; + /* pointer to next entry for the same subproblem */ +}; + +struct IOSROW +{ /* row (constraint) addition entry */ + char *name; + /* row name or NULL */ + unsigned char origin; + /* row origin flag (see glp_attr.origin) */ + unsigned char klass; + /* row class descriptor (see glp_attr.klass) */ + unsigned char type; + /* row type (GLP_LO, GLP_UP, etc.) */ + double lb; + /* row lower bound */ + double ub; + /* row upper bound */ + IOSAIJ *ptr; + /* pointer to the row coefficient list */ + double rii; + /* row scale factor */ + unsigned char stat; + /* row status (GLP_BS, GLP_NL, etc.) */ + IOSROW *next; + /* pointer to next entry for the same subproblem */ +}; + +struct IOSAIJ +{ /* constraint coefficient */ + int j; + /* variable (column) number, 1 <= j <= n */ + double val; + /* non-zero coefficient value */ + IOSAIJ *next; + /* pointer to next coefficient for the same row */ +}; + +struct IOSPOOL +{ /* cut pool */ + int size; + /* pool size = number of cuts in the pool */ + IOSCUT *head; + /* pointer to the first cut */ + IOSCUT *tail; + /* pointer to the last cut */ + int ord; + /* ordinal number of the current cut, 1 <= ord <= size */ + IOSCUT *curr; + /* pointer to the current cut */ +}; + +struct IOSCUT +{ /* cut (cutting plane constraint) */ + char *name; + /* cut name or NULL */ + unsigned char klass; + /* cut class descriptor (see glp_attr.klass) */ + IOSAIJ *ptr; + /* pointer to the cut coefficient list */ + unsigned char type; + /* cut type: + GLP_LO: sum a[j] * x[j] >= b + GLP_UP: sum a[j] * x[j] <= b + GLP_FX: sum a[j] * x[j] = b */ + double rhs; + /* cut right-hand side */ + IOSCUT *prev; + /* pointer to previous cut */ + IOSCUT *next; + /* pointer to next cut */ +}; + +#define ios_create_tree _glp_ios_create_tree +glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm); +/* create branch-and-bound tree */ + +#define ios_revive_node _glp_ios_revive_node +void ios_revive_node(glp_tree *tree, int p); +/* revive specified subproblem */ + +#define ios_freeze_node _glp_ios_freeze_node +void ios_freeze_node(glp_tree *tree); +/* freeze current subproblem */ + +#define ios_clone_node _glp_ios_clone_node +void ios_clone_node(glp_tree *tree, int p, int nnn, int ref[]); +/* clone specified subproblem */ + +#define ios_delete_node _glp_ios_delete_node +void ios_delete_node(glp_tree *tree, int p); +/* delete specified subproblem */ + +#define ios_delete_tree _glp_ios_delete_tree +void ios_delete_tree(glp_tree *tree); +/* delete branch-and-bound tree */ + +#define ios_eval_degrad _glp_ios_eval_degrad +void ios_eval_degrad(glp_tree *tree, int j, double *dn, double *up); +/* estimate obj. degrad. for down- and up-branches */ + +#define ios_round_bound _glp_ios_round_bound +double ios_round_bound(glp_tree *tree, double bound); +/* improve local bound by rounding */ + +#define ios_is_hopeful _glp_ios_is_hopeful +int ios_is_hopeful(glp_tree *tree, double bound); +/* check if subproblem is hopeful */ + +#define ios_best_node _glp_ios_best_node +int ios_best_node(glp_tree *tree); +/* find active node with best local bound */ + +#define ios_relative_gap _glp_ios_relative_gap +double ios_relative_gap(glp_tree *tree); +/* compute relative mip gap */ + +#define ios_solve_node _glp_ios_solve_node +int ios_solve_node(glp_tree *tree); +/* solve LP relaxation of current subproblem */ + +#define ios_create_pool _glp_ios_create_pool +IOSPOOL *ios_create_pool(glp_tree *tree); +/* create cut pool */ + +#define ios_add_row _glp_ios_add_row +int ios_add_row(glp_tree *tree, IOSPOOL *pool, + const char *name, int klass, int flags, int len, const int ind[], + const double val[], int type, double rhs); +/* add row (constraint) to the cut pool */ + +#define ios_find_row _glp_ios_find_row +IOSCUT *ios_find_row(IOSPOOL *pool, int i); +/* find row (constraint) in the cut pool */ + +#define ios_del_row _glp_ios_del_row +void ios_del_row(glp_tree *tree, IOSPOOL *pool, int i); +/* remove row (constraint) from the cut pool */ + +#define ios_clear_pool _glp_ios_clear_pool +void ios_clear_pool(glp_tree *tree, IOSPOOL *pool); +/* remove all rows (constraints) from the cut pool */ + +#define ios_delete_pool _glp_ios_delete_pool +void ios_delete_pool(glp_tree *tree, IOSPOOL *pool); +/* delete cut pool */ + +#if 1 /* 11/VII-2013 */ +#define ios_process_sol _glp_ios_process_sol +void ios_process_sol(glp_tree *T); +/* process integer feasible solution just found */ +#endif + +#define ios_preprocess_node _glp_ios_preprocess_node +int ios_preprocess_node(glp_tree *tree, int max_pass); +/* preprocess current subproblem */ + +#define ios_driver _glp_ios_driver +int ios_driver(glp_tree *tree); +/* branch-and-bound driver */ + +/**********************************************************************/ + +typedef struct IOSVEC IOSVEC; + +struct IOSVEC +{ /* sparse vector v = (v[j]) */ + int n; + /* dimension, n >= 0 */ + int nnz; + /* number of non-zero components, 0 <= nnz <= n */ + int *pos; /* int pos[1+n]; */ + /* pos[j] = k, 1 <= j <= n, is position of (non-zero) v[j] in the + arrays ind and val, where 1 <= k <= nnz; pos[j] = 0 means that + v[j] is structural zero */ + int *ind; /* int ind[1+n]; */ + /* ind[k] = j, 1 <= k <= nnz, is index of v[j] */ + double *val; /* double val[1+n]; */ + /* val[k], 1 <= k <= nnz, is a numeric value of v[j] */ +}; + +#define ios_create_vec _glp_ios_create_vec +IOSVEC *ios_create_vec(int n); +/* create sparse vector */ + +#define ios_check_vec _glp_ios_check_vec +void ios_check_vec(IOSVEC *v); +/* check that sparse vector has correct representation */ + +#define ios_get_vj _glp_ios_get_vj +double ios_get_vj(IOSVEC *v, int j); +/* retrieve component of sparse vector */ + +#define ios_set_vj _glp_ios_set_vj +void ios_set_vj(IOSVEC *v, int j, double val); +/* set/change component of sparse vector */ + +#define ios_clear_vec _glp_ios_clear_vec +void ios_clear_vec(IOSVEC *v); +/* set all components of sparse vector to zero */ + +#define ios_clean_vec _glp_ios_clean_vec +void ios_clean_vec(IOSVEC *v, double eps); +/* remove zero or small components from sparse vector */ + +#define ios_copy_vec _glp_ios_copy_vec +void ios_copy_vec(IOSVEC *x, IOSVEC *y); +/* copy sparse vector (x := y) */ + +#define ios_linear_comb _glp_ios_linear_comb +void ios_linear_comb(IOSVEC *x, double a, IOSVEC *y); +/* compute linear combination (x := x + a * y) */ + +#define ios_delete_vec _glp_ios_delete_vec +void ios_delete_vec(IOSVEC *v); +/* delete sparse vector */ + +/**********************************************************************/ + +#define ios_gmi_gen _glp_ios_gmi_gen +void ios_gmi_gen(glp_tree *tree); +/* generate Gomory's mixed integer cuts */ + +#define ios_mir_init _glp_ios_mir_init +void *ios_mir_init(glp_tree *tree); +/* initialize MIR cut generator */ + +#define ios_mir_gen _glp_ios_mir_gen +void ios_mir_gen(glp_tree *tree, void *gen); +/* generate MIR cuts */ + +#define ios_mir_term _glp_ios_mir_term +void ios_mir_term(void *gen); +/* terminate MIR cut generator */ + +#define ios_cov_gen _glp_ios_cov_gen +void ios_cov_gen(glp_tree *tree); +/* generate mixed cover cuts */ + +#define ios_clq_init _glp_ios_clq_init +void *ios_clq_init(glp_tree *tree); +/* initialize clique cut generator */ + +#define ios_clq_gen _glp_ios_clq_gen +void ios_clq_gen(glp_tree *tree, void *gen); +/* generate clique cuts */ + +#define ios_clq_term _glp_ios_clq_term +void ios_clq_term(void *gen); +/* terminate clique cut generator */ + +#define ios_pcost_init _glp_ios_pcost_init +void *ios_pcost_init(glp_tree *tree); +/* initialize working data used on pseudocost branching */ + +#define ios_pcost_branch _glp_ios_pcost_branch +int ios_pcost_branch(glp_tree *T, int *next); +/* choose branching variable with pseudocost branching */ + +#define ios_pcost_update _glp_ios_pcost_update +void ios_pcost_update(glp_tree *tree); +/* update history information for pseudocost branching */ + +#define ios_pcost_free _glp_ios_pcost_free +void ios_pcost_free(glp_tree *tree); +/* free working area used on pseudocost branching */ + +#define ios_feas_pump _glp_ios_feas_pump +void ios_feas_pump(glp_tree *T); +/* feasibility pump heuristic */ + +#if 1 /* 25/V-2013 */ +#define ios_proxy_heur _glp_ios_proxy_heur +void ios_proxy_heur(glp_tree *T); +/* proximity search heuristic */ +#endif + +#define ios_process_cuts _glp_ios_process_cuts +void ios_process_cuts(glp_tree *T); +/* process cuts stored in the local cut pool */ + +#define ios_choose_node _glp_ios_choose_node +int ios_choose_node(glp_tree *T); +/* select subproblem to continue the search */ + +#define ios_choose_var _glp_ios_choose_var +int ios_choose_var(glp_tree *T, int *next); +/* select variable to branch on */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios01.c b/resources/3rdparty/glpk-4.53/src/glpios01.c new file mode 100644 index 000000000..da1b9479f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios01.c @@ -0,0 +1,1602 @@ +/* glpios01.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" +#include "misc.h" + +static int lpx_eval_tab_row(glp_prob *lp, int k, int ind[], + double val[]) +{ /* compute row of the simplex tableau */ + return glp_eval_tab_row(lp, k, ind, val); +} + +static int lpx_dual_ratio_test(glp_prob *lp, int len, const int ind[], + const double val[], int how, double tol) +{ /* perform dual ratio test */ + int piv; + piv = glp_dual_rtest(lp, len, ind, val, how, tol); + xassert(0 <= piv && piv <= len); + return piv == 0 ? 0 : ind[piv]; +} + +/*********************************************************************** +* NAME +* +* ios_create_tree - create branch-and-bound tree +* +* SYNOPSIS +* +* #include "glpios.h" +* glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm); +* +* DESCRIPTION +* +* The routine ios_create_tree creates the branch-and-bound tree. +* +* Being created the tree consists of the only root subproblem whose +* reference number is 1. Note that initially the root subproblem is in +* frozen state and therefore needs to be revived. +* +* RETURNS +* +* The routine returns a pointer to the tree created. */ + +static IOSNPD *new_node(glp_tree *tree, IOSNPD *parent); + +glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm) +{ int m = mip->m; + int n = mip->n; + glp_tree *tree; + int i, j; + xassert(mip->tree == NULL); + mip->tree = tree = xmalloc(sizeof(glp_tree)); + tree->pool = dmp_create_pool(); + tree->n = n; + /* save original problem components */ + tree->orig_m = m; + tree->orig_type = xcalloc(1+m+n, sizeof(char)); + tree->orig_lb = xcalloc(1+m+n, sizeof(double)); + tree->orig_ub = xcalloc(1+m+n, sizeof(double)); + tree->orig_stat = xcalloc(1+m+n, sizeof(char)); + tree->orig_prim = xcalloc(1+m+n, sizeof(double)); + tree->orig_dual = xcalloc(1+m+n, sizeof(double)); + for (i = 1; i <= m; i++) + { GLPROW *row = mip->row[i]; + tree->orig_type[i] = (char)row->type; + tree->orig_lb[i] = row->lb; + tree->orig_ub[i] = row->ub; + tree->orig_stat[i] = (char)row->stat; + tree->orig_prim[i] = row->prim; + tree->orig_dual[i] = row->dual; + } + for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + tree->orig_type[m+j] = (char)col->type; + tree->orig_lb[m+j] = col->lb; + tree->orig_ub[m+j] = col->ub; + tree->orig_stat[m+j] = (char)col->stat; + tree->orig_prim[m+j] = col->prim; + tree->orig_dual[m+j] = col->dual; + } + tree->orig_obj = mip->obj_val; + /* initialize the branch-and-bound tree */ + tree->nslots = 0; + tree->avail = 0; + tree->slot = NULL; + tree->head = tree->tail = NULL; + tree->a_cnt = tree->n_cnt = tree->t_cnt = 0; + /* the root subproblem is not solved yet, so its final components + are unknown so far */ + tree->root_m = 0; + tree->root_type = NULL; + tree->root_lb = tree->root_ub = NULL; + tree->root_stat = NULL; + /* the current subproblem does not exist yet */ + tree->curr = NULL; + tree->mip = mip; + /*tree->solved = 0;*/ + tree->non_int = xcalloc(1+n, sizeof(char)); + memset(&tree->non_int[1], 0, n); + /* arrays to save parent subproblem components will be allocated + later */ + tree->pred_m = tree->pred_max = 0; + tree->pred_type = NULL; + tree->pred_lb = tree->pred_ub = NULL; + tree->pred_stat = NULL; + /* cut generator */ + tree->local = ios_create_pool(tree); + /*tree->first_attempt = 1;*/ + /*tree->max_added_cuts = 0;*/ + /*tree->min_eff = 0.0;*/ + /*tree->miss = 0;*/ + /*tree->just_selected = 0;*/ + tree->mir_gen = NULL; + tree->clq_gen = NULL; + /*tree->round = 0;*/ +#if 0 + /* create the conflict graph */ + tree->n_ref = xcalloc(1+n, sizeof(int)); + memset(&tree->n_ref[1], 0, n * sizeof(int)); + tree->c_ref = xcalloc(1+n, sizeof(int)); + memset(&tree->c_ref[1], 0, n * sizeof(int)); + tree->g = scg_create_graph(0); + tree->j_ref = xcalloc(1+tree->g->n_max, sizeof(int)); +#endif + /* pseudocost branching */ + tree->pcost = NULL; + tree->iwrk = xcalloc(1+n, sizeof(int)); + tree->dwrk = xcalloc(1+n, sizeof(double)); + /* initialize control parameters */ + tree->parm = parm; + tree->tm_beg = xtime(); +#if 0 /* 10/VI-2013 */ + tree->tm_lag = xlset(0); +#else + tree->tm_lag = 0.0; +#endif + tree->sol_cnt = 0; +#if 1 /* 11/VII-2013 */ + tree->P = NULL; + tree->npp = NULL; + tree->save_sol = parm->save_sol; + tree->save_cnt = 0; +#endif + /* initialize advanced solver interface */ + tree->reason = 0; + tree->reopt = 0; + tree->reinv = 0; + tree->br_var = 0; + tree->br_sel = 0; + tree->child = 0; + tree->next_p = 0; + /*tree->btrack = NULL;*/ + tree->stop = 0; + /* create the root subproblem, which initially is identical to + the original MIP */ + new_node(tree, NULL); + return tree; +} + +/*********************************************************************** +* NAME +* +* ios_revive_node - revive specified subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_revive_node(glp_tree *tree, int p); +* +* DESCRIPTION +* +* The routine ios_revive_node revives the specified subproblem, whose +* reference number is p, and thereby makes it the current subproblem. +* Note that the specified subproblem must be active. Besides, if the +* current subproblem already exists, it must be frozen before reviving +* another subproblem. */ + +void ios_revive_node(glp_tree *tree, int p) +{ glp_prob *mip = tree->mip; + IOSNPD *node, *root; + /* obtain pointer to the specified subproblem */ + xassert(1 <= p && p <= tree->nslots); + node = tree->slot[p].node; + xassert(node != NULL); + /* the specified subproblem must be active */ + xassert(node->count == 0); + /* the current subproblem must not exist */ + xassert(tree->curr == NULL); + /* the specified subproblem becomes current */ + tree->curr = node; + /*tree->solved = 0;*/ + /* obtain pointer to the root subproblem */ + root = tree->slot[1].node; + xassert(root != NULL); + /* at this point problem object components correspond to the root + subproblem, so if the root subproblem should be revived, there + is nothing more to do */ + if (node == root) goto done; + xassert(mip->m == tree->root_m); + /* build path from the root to the current node */ + node->temp = NULL; + for (node = node; node != NULL; node = node->up) + { if (node->up == NULL) + xassert(node == root); + else + node->up->temp = node; + } + /* go down from the root to the current node and make necessary + changes to restore components of the current subproblem */ + for (node = root; node != NULL; node = node->temp) + { int m = mip->m; + int n = mip->n; + /* if the current node is reached, the problem object at this + point corresponds to its parent, so save attributes of rows + and columns for the parent subproblem */ + if (node->temp == NULL) + { int i, j; + tree->pred_m = m; + /* allocate/reallocate arrays, if necessary */ + if (tree->pred_max < m + n) + { int new_size = m + n + 100; + if (tree->pred_type != NULL) xfree(tree->pred_type); + if (tree->pred_lb != NULL) xfree(tree->pred_lb); + if (tree->pred_ub != NULL) xfree(tree->pred_ub); + if (tree->pred_stat != NULL) xfree(tree->pred_stat); + tree->pred_max = new_size; + tree->pred_type = xcalloc(1+new_size, sizeof(char)); + tree->pred_lb = xcalloc(1+new_size, sizeof(double)); + tree->pred_ub = xcalloc(1+new_size, sizeof(double)); + tree->pred_stat = xcalloc(1+new_size, sizeof(char)); + } + /* save row attributes */ + for (i = 1; i <= m; i++) + { GLPROW *row = mip->row[i]; + tree->pred_type[i] = (char)row->type; + tree->pred_lb[i] = row->lb; + tree->pred_ub[i] = row->ub; + tree->pred_stat[i] = (char)row->stat; + } + /* save column attributes */ + for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + tree->pred_type[mip->m+j] = (char)col->type; + tree->pred_lb[mip->m+j] = col->lb; + tree->pred_ub[mip->m+j] = col->ub; + tree->pred_stat[mip->m+j] = (char)col->stat; + } + } + /* change bounds of rows and columns */ + { IOSBND *b; + for (b = node->b_ptr; b != NULL; b = b->next) + { if (b->k <= m) + glp_set_row_bnds(mip, b->k, b->type, b->lb, b->ub); + else + glp_set_col_bnds(mip, b->k-m, b->type, b->lb, b->ub); + } + } + /* change statuses of rows and columns */ + { IOSTAT *s; + for (s = node->s_ptr; s != NULL; s = s->next) + { if (s->k <= m) + glp_set_row_stat(mip, s->k, s->stat); + else + glp_set_col_stat(mip, s->k-m, s->stat); + } + } + /* add new rows */ + if (node->r_ptr != NULL) + { IOSROW *r; + IOSAIJ *a; + int i, len, *ind; + double *val; + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + for (r = node->r_ptr; r != NULL; r = r->next) + { i = glp_add_rows(mip, 1); + glp_set_row_name(mip, i, r->name); +#if 1 /* 20/IX-2008 */ + xassert(mip->row[i]->level == 0); + mip->row[i]->level = node->level; + mip->row[i]->origin = r->origin; + mip->row[i]->klass = r->klass; +#endif + glp_set_row_bnds(mip, i, r->type, r->lb, r->ub); + len = 0; + for (a = r->ptr; a != NULL; a = a->next) + len++, ind[len] = a->j, val[len] = a->val; + glp_set_mat_row(mip, i, len, ind, val); + glp_set_rii(mip, i, r->rii); + glp_set_row_stat(mip, i, r->stat); + } + xfree(ind); + xfree(val); + } +#if 0 + /* add new edges to the conflict graph */ + /* add new cliques to the conflict graph */ + /* (not implemented yet) */ + xassert(node->own_nn == 0); + xassert(node->own_nc == 0); + xassert(node->e_ptr == NULL); +#endif + } + /* the specified subproblem has been revived */ + node = tree->curr; + /* delete its bound change list */ + while (node->b_ptr != NULL) + { IOSBND *b; + b = node->b_ptr; + node->b_ptr = b->next; + dmp_free_atom(tree->pool, b, sizeof(IOSBND)); + } + /* delete its status change list */ + while (node->s_ptr != NULL) + { IOSTAT *s; + s = node->s_ptr; + node->s_ptr = s->next; + dmp_free_atom(tree->pool, s, sizeof(IOSTAT)); + } +#if 1 /* 20/XI-2009 */ + /* delete its row addition list (additional rows may appear, for + example, due to branching on GUB constraints */ + while (node->r_ptr != NULL) + { IOSROW *r; + r = node->r_ptr; + node->r_ptr = r->next; + xassert(r->name == NULL); + while (r->ptr != NULL) + { IOSAIJ *a; + a = r->ptr; + r->ptr = a->next; + dmp_free_atom(tree->pool, a, sizeof(IOSAIJ)); + } + dmp_free_atom(tree->pool, r, sizeof(IOSROW)); + } +#endif +done: return; +} + +/*********************************************************************** +* NAME +* +* ios_freeze_node - freeze current subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_freeze_node(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_freeze_node freezes the current subproblem. */ + +void ios_freeze_node(glp_tree *tree) +{ glp_prob *mip = tree->mip; + int m = mip->m; + int n = mip->n; + IOSNPD *node; + /* obtain pointer to the current subproblem */ + node = tree->curr; + xassert(node != NULL); + if (node->up == NULL) + { /* freeze the root subproblem */ + int k; + xassert(node->p == 1); + xassert(tree->root_m == 0); + xassert(tree->root_type == NULL); + xassert(tree->root_lb == NULL); + xassert(tree->root_ub == NULL); + xassert(tree->root_stat == NULL); + tree->root_m = m; + tree->root_type = xcalloc(1+m+n, sizeof(char)); + tree->root_lb = xcalloc(1+m+n, sizeof(double)); + tree->root_ub = xcalloc(1+m+n, sizeof(double)); + tree->root_stat = xcalloc(1+m+n, sizeof(char)); + for (k = 1; k <= m+n; k++) + { if (k <= m) + { GLPROW *row = mip->row[k]; + tree->root_type[k] = (char)row->type; + tree->root_lb[k] = row->lb; + tree->root_ub[k] = row->ub; + tree->root_stat[k] = (char)row->stat; + } + else + { GLPCOL *col = mip->col[k-m]; + tree->root_type[k] = (char)col->type; + tree->root_lb[k] = col->lb; + tree->root_ub[k] = col->ub; + tree->root_stat[k] = (char)col->stat; + } + } + } + else + { /* freeze non-root subproblem */ + int root_m = tree->root_m; + int pred_m = tree->pred_m; + int i, j, k; + xassert(pred_m <= m); + /* build change lists for rows and columns which exist in the + parent subproblem */ + xassert(node->b_ptr == NULL); + xassert(node->s_ptr == NULL); + for (k = 1; k <= pred_m + n; k++) + { int pred_type, pred_stat, type, stat; + double pred_lb, pred_ub, lb, ub; + /* determine attributes in the parent subproblem */ + pred_type = tree->pred_type[k]; + pred_lb = tree->pred_lb[k]; + pred_ub = tree->pred_ub[k]; + pred_stat = tree->pred_stat[k]; + /* determine attributes in the current subproblem */ + if (k <= pred_m) + { GLPROW *row = mip->row[k]; + type = row->type; + lb = row->lb; + ub = row->ub; + stat = row->stat; + } + else + { GLPCOL *col = mip->col[k - pred_m]; + type = col->type; + lb = col->lb; + ub = col->ub; + stat = col->stat; + } + /* save type and bounds of a row/column, if changed */ + if (!(pred_type == type && pred_lb == lb && pred_ub == ub)) + { IOSBND *b; + b = dmp_get_atom(tree->pool, sizeof(IOSBND)); + b->k = k; + b->type = (unsigned char)type; + b->lb = lb; + b->ub = ub; + b->next = node->b_ptr; + node->b_ptr = b; + } + /* save status of a row/column, if changed */ + if (pred_stat != stat) + { IOSTAT *s; + s = dmp_get_atom(tree->pool, sizeof(IOSTAT)); + s->k = k; + s->stat = (unsigned char)stat; + s->next = node->s_ptr; + node->s_ptr = s; + } + } + /* save new rows added to the current subproblem */ + xassert(node->r_ptr == NULL); + if (pred_m < m) + { int i, len, *ind; + double *val; + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + for (i = m; i > pred_m; i--) + { GLPROW *row = mip->row[i]; + IOSROW *r; + const char *name; + r = dmp_get_atom(tree->pool, sizeof(IOSROW)); + name = glp_get_row_name(mip, i); + if (name == NULL) + r->name = NULL; + else + { r->name = dmp_get_atom(tree->pool, strlen(name)+1); + strcpy(r->name, name); + } +#if 1 /* 20/IX-2008 */ + r->origin = row->origin; + r->klass = row->klass; +#endif + r->type = (unsigned char)row->type; + r->lb = row->lb; + r->ub = row->ub; + r->ptr = NULL; + len = glp_get_mat_row(mip, i, ind, val); + for (k = 1; k <= len; k++) + { IOSAIJ *a; + a = dmp_get_atom(tree->pool, sizeof(IOSAIJ)); + a->j = ind[k]; + a->val = val[k]; + a->next = r->ptr; + r->ptr = a; + } + r->rii = row->rii; + r->stat = (unsigned char)row->stat; + r->next = node->r_ptr; + node->r_ptr = r; + } + xfree(ind); + xfree(val); + } + /* remove all rows missing in the root subproblem */ + if (m != root_m) + { int nrs, *num; + nrs = m - root_m; + xassert(nrs > 0); + num = xcalloc(1+nrs, sizeof(int)); + for (i = 1; i <= nrs; i++) num[i] = root_m + i; + glp_del_rows(mip, nrs, num); + xfree(num); + } + m = mip->m; + /* and restore attributes of all rows and columns for the root + subproblem */ + xassert(m == root_m); + for (i = 1; i <= m; i++) + { glp_set_row_bnds(mip, i, tree->root_type[i], + tree->root_lb[i], tree->root_ub[i]); + glp_set_row_stat(mip, i, tree->root_stat[i]); + } + for (j = 1; j <= n; j++) + { glp_set_col_bnds(mip, j, tree->root_type[m+j], + tree->root_lb[m+j], tree->root_ub[m+j]); + glp_set_col_stat(mip, j, tree->root_stat[m+j]); + } +#if 1 + /* remove all edges and cliques missing in the conflict graph + for the root subproblem */ + /* (not implemented yet) */ +#endif + } + /* the current subproblem has been frozen */ + tree->curr = NULL; + return; +} + +/*********************************************************************** +* NAME +* +* ios_clone_node - clone specified subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_clone_node(glp_tree *tree, int p, int nnn, int ref[]); +* +* DESCRIPTION +* +* The routine ios_clone_node clones the specified subproblem, whose +* reference number is p, creating its nnn exact copies. Note that the +* specified subproblem must be active and must be in the frozen state +* (i.e. it must not be the current subproblem). +* +* Each clone, an exact copy of the specified subproblem, becomes a new +* active subproblem added to the end of the active list. After cloning +* the specified subproblem becomes inactive. +* +* The reference numbers of clone subproblems are stored to locations +* ref[1], ..., ref[nnn]. */ + +static int get_slot(glp_tree *tree) +{ int p; + /* if no free slots are available, increase the room */ + if (tree->avail == 0) + { int nslots = tree->nslots; + IOSLOT *save = tree->slot; + if (nslots == 0) + tree->nslots = 20; + else + { tree->nslots = nslots + nslots; + xassert(tree->nslots > nslots); + } + tree->slot = xcalloc(1+tree->nslots, sizeof(IOSLOT)); + if (save != NULL) + { memcpy(&tree->slot[1], &save[1], nslots * sizeof(IOSLOT)); + xfree(save); + } + /* push more free slots into the stack */ + for (p = tree->nslots; p > nslots; p--) + { tree->slot[p].node = NULL; + tree->slot[p].next = tree->avail; + tree->avail = p; + } + } + /* pull a free slot from the stack */ + p = tree->avail; + tree->avail = tree->slot[p].next; + xassert(tree->slot[p].node == NULL); + tree->slot[p].next = 0; + return p; +} + +static IOSNPD *new_node(glp_tree *tree, IOSNPD *parent) +{ IOSNPD *node; + int p; + /* pull a free slot for the new node */ + p = get_slot(tree); + /* create descriptor of the new subproblem */ + node = dmp_get_atom(tree->pool, sizeof(IOSNPD)); + tree->slot[p].node = node; + node->p = p; + node->up = parent; + node->level = (parent == NULL ? 0 : parent->level + 1); + node->count = 0; + node->b_ptr = NULL; + node->s_ptr = NULL; + node->r_ptr = NULL; + node->solved = 0; +#if 0 + node->own_nn = node->own_nc = 0; + node->e_ptr = NULL; +#endif +#if 1 /* 04/X-2008 */ + node->lp_obj = (parent == NULL ? (tree->mip->dir == GLP_MIN ? + -DBL_MAX : +DBL_MAX) : parent->lp_obj); +#endif + node->bound = (parent == NULL ? (tree->mip->dir == GLP_MIN ? + -DBL_MAX : +DBL_MAX) : parent->bound); + node->br_var = 0; + node->br_val = 0.0; + node->ii_cnt = 0; + node->ii_sum = 0.0; +#if 1 /* 30/XI-2009 */ + node->changed = 0; +#endif + if (tree->parm->cb_size == 0) + node->data = NULL; + else + { node->data = dmp_get_atom(tree->pool, tree->parm->cb_size); + memset(node->data, 0, tree->parm->cb_size); + } + node->temp = NULL; + node->prev = tree->tail; + node->next = NULL; + /* add the new subproblem to the end of the active list */ + if (tree->head == NULL) + tree->head = node; + else + tree->tail->next = node; + tree->tail = node; + tree->a_cnt++; + tree->n_cnt++; + tree->t_cnt++; + /* increase the number of child subproblems */ + if (parent == NULL) + xassert(p == 1); + else + parent->count++; + return node; +} + +void ios_clone_node(glp_tree *tree, int p, int nnn, int ref[]) +{ IOSNPD *node; + int k; + /* obtain pointer to the subproblem to be cloned */ + xassert(1 <= p && p <= tree->nslots); + node = tree->slot[p].node; + xassert(node != NULL); + /* the specified subproblem must be active */ + xassert(node->count == 0); + /* and must be in the frozen state */ + xassert(tree->curr != node); + /* remove the specified subproblem from the active list, because + it becomes inactive */ + if (node->prev == NULL) + tree->head = node->next; + else + node->prev->next = node->next; + if (node->next == NULL) + tree->tail = node->prev; + else + node->next->prev = node->prev; + node->prev = node->next = NULL; + tree->a_cnt--; + /* create clone subproblems */ + xassert(nnn > 0); + for (k = 1; k <= nnn; k++) + ref[k] = new_node(tree, node)->p; + return; +} + +/*********************************************************************** +* NAME +* +* ios_delete_node - delete specified subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_delete_node(glp_tree *tree, int p); +* +* DESCRIPTION +* +* The routine ios_delete_node deletes the specified subproblem, whose +* reference number is p. The subproblem must be active and must be in +* the frozen state (i.e. it must not be the current subproblem). +* +* Note that deletion is performed recursively, i.e. if a subproblem to +* be deleted is the only child of its parent, the parent subproblem is +* also deleted, etc. */ + +void ios_delete_node(glp_tree *tree, int p) +{ IOSNPD *node, *temp; + /* obtain pointer to the subproblem to be deleted */ + xassert(1 <= p && p <= tree->nslots); + node = tree->slot[p].node; + xassert(node != NULL); + /* the specified subproblem must be active */ + xassert(node->count == 0); + /* and must be in the frozen state */ + xassert(tree->curr != node); + /* remove the specified subproblem from the active list, because + it is gone from the tree */ + if (node->prev == NULL) + tree->head = node->next; + else + node->prev->next = node->next; + if (node->next == NULL) + tree->tail = node->prev; + else + node->next->prev = node->prev; + node->prev = node->next = NULL; + tree->a_cnt--; +loop: /* recursive deletion starts here */ + /* delete the bound change list */ + { IOSBND *b; + while (node->b_ptr != NULL) + { b = node->b_ptr; + node->b_ptr = b->next; + dmp_free_atom(tree->pool, b, sizeof(IOSBND)); + } + } + /* delete the status change list */ + { IOSTAT *s; + while (node->s_ptr != NULL) + { s = node->s_ptr; + node->s_ptr = s->next; + dmp_free_atom(tree->pool, s, sizeof(IOSTAT)); + } + } + /* delete the row addition list */ + while (node->r_ptr != NULL) + { IOSROW *r; + r = node->r_ptr; + if (r->name != NULL) + dmp_free_atom(tree->pool, r->name, strlen(r->name)+1); + while (r->ptr != NULL) + { IOSAIJ *a; + a = r->ptr; + r->ptr = a->next; + dmp_free_atom(tree->pool, a, sizeof(IOSAIJ)); + } + node->r_ptr = r->next; + dmp_free_atom(tree->pool, r, sizeof(IOSROW)); + } +#if 0 + /* delete the edge addition list */ + /* delete the clique addition list */ + /* (not implemented yet) */ + xassert(node->own_nn == 0); + xassert(node->own_nc == 0); + xassert(node->e_ptr == NULL); +#endif + /* free application-specific data */ + if (tree->parm->cb_size == 0) + xassert(node->data == NULL); + else + dmp_free_atom(tree->pool, node->data, tree->parm->cb_size); + /* free the corresponding node slot */ + p = node->p; + xassert(tree->slot[p].node == node); + tree->slot[p].node = NULL; + tree->slot[p].next = tree->avail; + tree->avail = p; + /* save pointer to the parent subproblem */ + temp = node->up; + /* delete the subproblem descriptor */ + dmp_free_atom(tree->pool, node, sizeof(IOSNPD)); + tree->n_cnt--; + /* take pointer to the parent subproblem */ + node = temp; + if (node != NULL) + { /* the parent subproblem exists; decrease the number of its + child subproblems */ + xassert(node->count > 0); + node->count--; + /* if now the parent subproblem has no childs, it also must be + deleted */ + if (node->count == 0) goto loop; + } + return; +} + +/*********************************************************************** +* NAME +* +* ios_delete_tree - delete branch-and-bound tree +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_delete_tree(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_delete_tree deletes the branch-and-bound tree, which +* the parameter tree points to, and frees all the memory allocated to +* this program object. +* +* On exit components of the problem object are restored to correspond +* to the original MIP passed to the routine ios_create_tree. */ + +void ios_delete_tree(glp_tree *tree) +{ glp_prob *mip = tree->mip; + int i, j; + int m = mip->m; + int n = mip->n; + xassert(mip->tree == tree); + /* remove all additional rows */ + if (m != tree->orig_m) + { int nrs, *num; + nrs = m - tree->orig_m; + xassert(nrs > 0); + num = xcalloc(1+nrs, sizeof(int)); + for (i = 1; i <= nrs; i++) num[i] = tree->orig_m + i; + glp_del_rows(mip, nrs, num); + xfree(num); + } + m = tree->orig_m; + /* restore original attributes of rows and columns */ + xassert(m == tree->orig_m); + xassert(n == tree->n); + for (i = 1; i <= m; i++) + { glp_set_row_bnds(mip, i, tree->orig_type[i], + tree->orig_lb[i], tree->orig_ub[i]); + glp_set_row_stat(mip, i, tree->orig_stat[i]); + mip->row[i]->prim = tree->orig_prim[i]; + mip->row[i]->dual = tree->orig_dual[i]; + } + for (j = 1; j <= n; j++) + { glp_set_col_bnds(mip, j, tree->orig_type[m+j], + tree->orig_lb[m+j], tree->orig_ub[m+j]); + glp_set_col_stat(mip, j, tree->orig_stat[m+j]); + mip->col[j]->prim = tree->orig_prim[m+j]; + mip->col[j]->dual = tree->orig_dual[m+j]; + } + mip->pbs_stat = mip->dbs_stat = GLP_FEAS; + mip->obj_val = tree->orig_obj; + /* delete the branch-and-bound tree */ + xassert(tree->local != NULL); + ios_delete_pool(tree, tree->local); + dmp_delete_pool(tree->pool); + xfree(tree->orig_type); + xfree(tree->orig_lb); + xfree(tree->orig_ub); + xfree(tree->orig_stat); + xfree(tree->orig_prim); + xfree(tree->orig_dual); + xfree(tree->slot); + if (tree->root_type != NULL) xfree(tree->root_type); + if (tree->root_lb != NULL) xfree(tree->root_lb); + if (tree->root_ub != NULL) xfree(tree->root_ub); + if (tree->root_stat != NULL) xfree(tree->root_stat); + xfree(tree->non_int); +#if 0 + xfree(tree->n_ref); + xfree(tree->c_ref); + xfree(tree->j_ref); +#endif + if (tree->pcost != NULL) ios_pcost_free(tree); + xfree(tree->iwrk); + xfree(tree->dwrk); +#if 0 + scg_delete_graph(tree->g); +#endif + if (tree->pred_type != NULL) xfree(tree->pred_type); + if (tree->pred_lb != NULL) xfree(tree->pred_lb); + if (tree->pred_ub != NULL) xfree(tree->pred_ub); + if (tree->pred_stat != NULL) xfree(tree->pred_stat); +#if 0 + xassert(tree->cut_gen == NULL); +#endif + xassert(tree->mir_gen == NULL); + xassert(tree->clq_gen == NULL); + xfree(tree); + mip->tree = NULL; + return; +} + +/*********************************************************************** +* NAME +* +* ios_eval_degrad - estimate obj. degrad. for down- and up-branches +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_eval_degrad(glp_tree *tree, int j, double *dn, double *up); +* +* DESCRIPTION +* +* Given optimal basis to LP relaxation of the current subproblem the +* routine ios_eval_degrad performs the dual ratio test to compute the +* objective values in the adjacent basis for down- and up-branches, +* which are stored in locations *dn and *up, assuming that x[j] is a +* variable chosen to branch upon. */ + +void ios_eval_degrad(glp_tree *tree, int j, double *dn, double *up) +{ glp_prob *mip = tree->mip; + int m = mip->m, n = mip->n; + int len, kase, k, t, stat; + double alfa, beta, gamma, delta, dz; + int *ind = tree->iwrk; + double *val = tree->dwrk; + /* current basis must be optimal */ + xassert(glp_get_status(mip) == GLP_OPT); + /* basis factorization must exist */ + xassert(glp_bf_exists(mip)); + /* obtain (fractional) value of x[j] in optimal basic solution + to LP relaxation of the current subproblem */ + xassert(1 <= j && j <= n); + beta = mip->col[j]->prim; + /* since the value of x[j] is fractional, it is basic; compute + corresponding row of the simplex table */ + len = lpx_eval_tab_row(mip, m+j, ind, val); + /* kase < 0 means down-branch; kase > 0 means up-branch */ + for (kase = -1; kase <= +1; kase += 2) + { /* for down-branch we introduce new upper bound floor(beta) + for x[j]; similarly, for up-branch we introduce new lower + bound ceil(beta) for x[j]; in the current basis this new + upper/lower bound is violated, so in the adjacent basis + x[j] will leave the basis and go to its new upper/lower + bound; we need to know which non-basic variable x[k] should + enter the basis to keep dual feasibility */ +#if 0 /* 23/XI-2009 */ + k = lpx_dual_ratio_test(mip, len, ind, val, kase, 1e-7); +#else + k = lpx_dual_ratio_test(mip, len, ind, val, kase, 1e-9); +#endif + /* if no variable has been chosen, current basis being primal + infeasible due to the new upper/lower bound of x[j] is dual + unbounded, therefore, LP relaxation to corresponding branch + has no primal feasible solution */ + if (k == 0) + { if (mip->dir == GLP_MIN) + { if (kase < 0) + *dn = +DBL_MAX; + else + *up = +DBL_MAX; + } + else if (mip->dir == GLP_MAX) + { if (kase < 0) + *dn = -DBL_MAX; + else + *up = -DBL_MAX; + } + else + xassert(mip != mip); + continue; + } + xassert(1 <= k && k <= m+n); + /* row of the simplex table corresponding to specified basic + variable x[j] is the following: + x[j] = ... + alfa * x[k] + ... ; + we need to know influence coefficient, alfa, at non-basic + variable x[k] chosen with the dual ratio test */ + for (t = 1; t <= len; t++) + if (ind[t] == k) break; + xassert(1 <= t && t <= len); + alfa = val[t]; + /* determine status and reduced cost of variable x[k] */ + if (k <= m) + { stat = mip->row[k]->stat; + gamma = mip->row[k]->dual; + } + else + { stat = mip->col[k-m]->stat; + gamma = mip->col[k-m]->dual; + } + /* x[k] cannot be basic or fixed non-basic */ + xassert(stat == GLP_NL || stat == GLP_NU || stat == GLP_NF); + /* if the current basis is dual degenerative, some reduced + costs, which are close to zero, may have wrong sign due to + round-off errors, so correct the sign of gamma */ + if (mip->dir == GLP_MIN) + { if (stat == GLP_NL && gamma < 0.0 || + stat == GLP_NU && gamma > 0.0 || + stat == GLP_NF) gamma = 0.0; + } + else if (mip->dir == GLP_MAX) + { if (stat == GLP_NL && gamma > 0.0 || + stat == GLP_NU && gamma < 0.0 || + stat == GLP_NF) gamma = 0.0; + } + else + xassert(mip != mip); + /* determine the change of x[j] in the adjacent basis: + delta x[j] = new x[j] - old x[j] */ + delta = (kase < 0 ? floor(beta) : ceil(beta)) - beta; + /* compute the change of x[k] in the adjacent basis: + delta x[k] = new x[k] - old x[k] = delta x[j] / alfa */ + delta /= alfa; + /* compute the change of the objective in the adjacent basis: + delta z = new z - old z = gamma * delta x[k] */ + dz = gamma * delta; + if (mip->dir == GLP_MIN) + xassert(dz >= 0.0); + else if (mip->dir == GLP_MAX) + xassert(dz <= 0.0); + else + xassert(mip != mip); + /* compute the new objective value in the adjacent basis: + new z = old z + delta z */ + if (kase < 0) + *dn = mip->obj_val + dz; + else + *up = mip->obj_val + dz; + } + /*xprintf("obj = %g; dn = %g; up = %g\n", + mip->obj_val, *dn, *up);*/ + return; +} + +/*********************************************************************** +* NAME +* +* ios_round_bound - improve local bound by rounding +* +* SYNOPSIS +* +* #include "glpios.h" +* double ios_round_bound(glp_tree *tree, double bound); +* +* RETURNS +* +* For the given local bound for any integer feasible solution to the +* current subproblem the routine ios_round_bound returns an improved +* local bound for the same integer feasible solution. +* +* BACKGROUND +* +* Let the current subproblem has the following objective function: +* +* z = sum c[j] * x[j] + s >= b, (1) +* j in J +* +* where J = {j: c[j] is non-zero and integer, x[j] is integer}, s is +* the sum of terms corresponding to fixed variables, b is an initial +* local bound (minimization). +* +* From (1) it follows that: +* +* d * sum (c[j] / d) * x[j] + s >= b, (2) +* j in J +* +* or, equivalently, +* +* sum (c[j] / d) * x[j] >= (b - s) / d = h, (3) +* j in J +* +* where d = gcd(c[j]). Since the left-hand side of (3) is integer, +* h = (b - s) / d can be rounded up to the nearest integer: +* +* h' = ceil(h) = (b' - s) / d, (4) +* +* that gives an rounded, improved local bound: +* +* b' = d * h' + s. (5) +* +* In case of maximization '>=' in (1) should be replaced by '<=' that +* leads to the following formula: +* +* h' = floor(h) = (b' - s) / d, (6) +* +* which should used in the same way as (4). +* +* NOTE: If b is a valid local bound for a child of the current +* subproblem, b' is also valid for that child subproblem. */ + +double ios_round_bound(glp_tree *tree, double bound) +{ glp_prob *mip = tree->mip; + int n = mip->n; + int d, j, nn, *c = tree->iwrk; + double s, h; + /* determine c[j] and compute s */ + nn = 0, s = mip->c0, d = 0; + for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + if (col->coef == 0.0) continue; + if (col->type == GLP_FX) + { /* fixed variable */ + s += col->coef * col->prim; + } + else + { /* non-fixed variable */ + if (col->kind != GLP_IV) goto skip; + if (col->coef != floor(col->coef)) goto skip; + if (fabs(col->coef) <= (double)INT_MAX) + c[++nn] = (int)fabs(col->coef); + else + d = 1; + } + } + /* compute d = gcd(c[1],...c[nn]) */ + if (d == 0) + { if (nn == 0) goto skip; + d = gcdn(nn, c); + } + xassert(d > 0); + /* compute new local bound */ + if (mip->dir == GLP_MIN) + { if (bound != +DBL_MAX) + { h = (bound - s) / (double)d; + if (h >= floor(h) + 0.001) + { /* round up */ + h = ceil(h); + /*xprintf("d = %d; old = %g; ", d, bound);*/ + bound = (double)d * h + s; + /*xprintf("new = %g\n", bound);*/ + } + } + } + else if (mip->dir == GLP_MAX) + { if (bound != -DBL_MAX) + { h = (bound - s) / (double)d; + if (h <= ceil(h) - 0.001) + { /* round down */ + h = floor(h); + bound = (double)d * h + s; + } + } + } + else + xassert(mip != mip); +skip: return bound; +} + +/*********************************************************************** +* NAME +* +* ios_is_hopeful - check if subproblem is hopeful +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_is_hopeful(glp_tree *tree, double bound); +* +* DESCRIPTION +* +* Given the local bound of a subproblem the routine ios_is_hopeful +* checks if the subproblem can have an integer optimal solution which +* is better than the best one currently known. +* +* RETURNS +* +* If the subproblem can have a better integer optimal solution, the +* routine returns non-zero; otherwise, if the corresponding branch can +* be pruned, the routine returns zero. */ + +int ios_is_hopeful(glp_tree *tree, double bound) +{ glp_prob *mip = tree->mip; + int ret = 1; + double eps; + if (mip->mip_stat == GLP_FEAS) + { eps = tree->parm->tol_obj * (1.0 + fabs(mip->mip_obj)); + switch (mip->dir) + { case GLP_MIN: + if (bound >= mip->mip_obj - eps) ret = 0; + break; + case GLP_MAX: + if (bound <= mip->mip_obj + eps) ret = 0; + break; + default: + xassert(mip != mip); + } + } + else + { switch (mip->dir) + { case GLP_MIN: + if (bound == +DBL_MAX) ret = 0; + break; + case GLP_MAX: + if (bound == -DBL_MAX) ret = 0; + break; + default: + xassert(mip != mip); + } + } + return ret; +} + +/*********************************************************************** +* NAME +* +* ios_best_node - find active node with best local bound +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_best_node(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_best_node finds an active node whose local bound is +* best among other active nodes. +* +* It is understood that the integer optimal solution of the original +* mip problem cannot be better than the best bound, so the best bound +* is an lower (minimization) or upper (maximization) global bound for +* the original problem. +* +* RETURNS +* +* The routine ios_best_node returns the subproblem reference number +* for the best node. However, if the tree is empty, it returns zero. */ + +int ios_best_node(glp_tree *tree) +{ IOSNPD *node, *best = NULL; + switch (tree->mip->dir) + { case GLP_MIN: + /* minimization */ + for (node = tree->head; node != NULL; node = node->next) + if (best == NULL || best->bound > node->bound) + best = node; + break; + case GLP_MAX: + /* maximization */ + for (node = tree->head; node != NULL; node = node->next) + if (best == NULL || best->bound < node->bound) + best = node; + break; + default: + xassert(tree != tree); + } + return best == NULL ? 0 : best->p; +} + +/*********************************************************************** +* NAME +* +* ios_relative_gap - compute relative mip gap +* +* SYNOPSIS +* +* #include "glpios.h" +* double ios_relative_gap(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_relative_gap computes the relative mip gap using the +* formula: +* +* gap = |best_mip - best_bnd| / (|best_mip| + DBL_EPSILON), +* +* where best_mip is the best integer feasible solution found so far, +* best_bnd is the best (global) bound. If no integer feasible solution +* has been found yet, rel_gap is set to DBL_MAX. +* +* RETURNS +* +* The routine ios_relative_gap returns the relative mip gap. */ + +double ios_relative_gap(glp_tree *tree) +{ glp_prob *mip = tree->mip; + int p; + double best_mip, best_bnd, gap; + if (mip->mip_stat == GLP_FEAS) + { best_mip = mip->mip_obj; + p = ios_best_node(tree); + if (p == 0) + { /* the tree is empty */ + gap = 0.0; + } + else + { best_bnd = tree->slot[p].node->bound; + gap = fabs(best_mip - best_bnd) / (fabs(best_mip) + + DBL_EPSILON); + } + } + else + { /* no integer feasible solution has been found yet */ + gap = DBL_MAX; + } + return gap; +} + +/*********************************************************************** +* NAME +* +* ios_solve_node - solve LP relaxation of current subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_solve_node(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_solve_node re-optimizes LP relaxation of the current +* subproblem using the dual simplex method. +* +* RETURNS +* +* The routine returns the code which is reported by glp_simplex. */ + +int ios_solve_node(glp_tree *tree) +{ glp_prob *mip = tree->mip; + glp_smcp parm; + int ret; + /* the current subproblem must exist */ + xassert(tree->curr != NULL); + /* set some control parameters */ + glp_init_smcp(&parm); + switch (tree->parm->msg_lev) + { case GLP_MSG_OFF: + parm.msg_lev = GLP_MSG_OFF; break; + case GLP_MSG_ERR: + parm.msg_lev = GLP_MSG_ERR; break; + case GLP_MSG_ON: + case GLP_MSG_ALL: + parm.msg_lev = GLP_MSG_ON; break; + case GLP_MSG_DBG: + parm.msg_lev = GLP_MSG_ALL; break; + default: + xassert(tree != tree); + } + parm.meth = GLP_DUALP; + if (tree->parm->msg_lev < GLP_MSG_DBG) + parm.out_dly = tree->parm->out_dly; + else + parm.out_dly = 0; + /* if the incumbent objective value is already known, use it to + prematurely terminate the dual simplex search */ + if (mip->mip_stat == GLP_FEAS) + { switch (tree->mip->dir) + { case GLP_MIN: + parm.obj_ul = mip->mip_obj; + break; + case GLP_MAX: + parm.obj_ll = mip->mip_obj; + break; + default: + xassert(mip != mip); + } + } + /* try to solve/re-optimize the LP relaxation */ + ret = glp_simplex(mip, &parm); + tree->curr->solved++; +#if 0 + xprintf("ret = %d; status = %d; pbs = %d; dbs = %d; some = %d\n", + ret, glp_get_status(mip), mip->pbs_stat, mip->dbs_stat, + mip->some); + lpx_print_sol(mip, "sol"); +#endif + return ret; +} + +/**********************************************************************/ + +IOSPOOL *ios_create_pool(glp_tree *tree) +{ /* create cut pool */ + IOSPOOL *pool; +#if 0 + pool = dmp_get_atom(tree->pool, sizeof(IOSPOOL)); +#else + xassert(tree == tree); + pool = xmalloc(sizeof(IOSPOOL)); +#endif + pool->size = 0; + pool->head = pool->tail = NULL; + pool->ord = 0, pool->curr = NULL; + return pool; +} + +int ios_add_row(glp_tree *tree, IOSPOOL *pool, + const char *name, int klass, int flags, int len, const int ind[], + const double val[], int type, double rhs) +{ /* add row (constraint) to the cut pool */ + IOSCUT *cut; + IOSAIJ *aij; + int k; + xassert(pool != NULL); + cut = dmp_get_atom(tree->pool, sizeof(IOSCUT)); + if (name == NULL || name[0] == '\0') + cut->name = NULL; + else + { for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_ios_add_row: cut name too long\n"); + if (iscntrl((unsigned char)name[k])) + xerror("glp_ios_add_row: cut name contains invalid chara" + "cter(s)\n"); + } + cut->name = dmp_get_atom(tree->pool, strlen(name)+1); + strcpy(cut->name, name); + } + if (!(0 <= klass && klass <= 255)) + xerror("glp_ios_add_row: klass = %d; invalid cut class\n", + klass); + cut->klass = (unsigned char)klass; + if (flags != 0) + xerror("glp_ios_add_row: flags = %d; invalid cut flags\n", + flags); + cut->ptr = NULL; + if (!(0 <= len && len <= tree->n)) + xerror("glp_ios_add_row: len = %d; invalid cut length\n", + len); + for (k = 1; k <= len; k++) + { aij = dmp_get_atom(tree->pool, sizeof(IOSAIJ)); + if (!(1 <= ind[k] && ind[k] <= tree->n)) + xerror("glp_ios_add_row: ind[%d] = %d; column index out of " + "range\n", k, ind[k]); + aij->j = ind[k]; + aij->val = val[k]; + aij->next = cut->ptr; + cut->ptr = aij; + } + if (!(type == GLP_LO || type == GLP_UP || type == GLP_FX)) + xerror("glp_ios_add_row: type = %d; invalid cut type\n", + type); + cut->type = (unsigned char)type; + cut->rhs = rhs; + cut->prev = pool->tail; + cut->next = NULL; + if (cut->prev == NULL) + pool->head = cut; + else + cut->prev->next = cut; + pool->tail = cut; + pool->size++; + return pool->size; +} + +IOSCUT *ios_find_row(IOSPOOL *pool, int i) +{ /* find row (constraint) in the cut pool */ + /* (smart linear search) */ + xassert(pool != NULL); + xassert(1 <= i && i <= pool->size); + if (pool->ord == 0) + { xassert(pool->curr == NULL); + pool->ord = 1; + pool->curr = pool->head; + } + xassert(pool->curr != NULL); + if (i < pool->ord) + { if (i < pool->ord - i) + { pool->ord = 1; + pool->curr = pool->head; + while (pool->ord != i) + { pool->ord++; + xassert(pool->curr != NULL); + pool->curr = pool->curr->next; + } + } + else + { while (pool->ord != i) + { pool->ord--; + xassert(pool->curr != NULL); + pool->curr = pool->curr->prev; + } + } + } + else if (i > pool->ord) + { if (i - pool->ord < pool->size - i) + { while (pool->ord != i) + { pool->ord++; + xassert(pool->curr != NULL); + pool->curr = pool->curr->next; + } + } + else + { pool->ord = pool->size; + pool->curr = pool->tail; + while (pool->ord != i) + { pool->ord--; + xassert(pool->curr != NULL); + pool->curr = pool->curr->prev; + } + } + } + xassert(pool->ord == i); + xassert(pool->curr != NULL); + return pool->curr; +} + +void ios_del_row(glp_tree *tree, IOSPOOL *pool, int i) +{ /* remove row (constraint) from the cut pool */ + IOSCUT *cut; + IOSAIJ *aij; + xassert(pool != NULL); + if (!(1 <= i && i <= pool->size)) + xerror("glp_ios_del_row: i = %d; cut number out of range\n", + i); + cut = ios_find_row(pool, i); + xassert(pool->curr == cut); + if (cut->next != NULL) + pool->curr = cut->next; + else if (cut->prev != NULL) + pool->ord--, pool->curr = cut->prev; + else + pool->ord = 0, pool->curr = NULL; + if (cut->name != NULL) + dmp_free_atom(tree->pool, cut->name, strlen(cut->name)+1); + if (cut->prev == NULL) + { xassert(pool->head == cut); + pool->head = cut->next; + } + else + { xassert(cut->prev->next == cut); + cut->prev->next = cut->next; + } + if (cut->next == NULL) + { xassert(pool->tail == cut); + pool->tail = cut->prev; + } + else + { xassert(cut->next->prev == cut); + cut->next->prev = cut->prev; + } + while (cut->ptr != NULL) + { aij = cut->ptr; + cut->ptr = aij->next; + dmp_free_atom(tree->pool, aij, sizeof(IOSAIJ)); + } + dmp_free_atom(tree->pool, cut, sizeof(IOSCUT)); + pool->size--; + return; +} + +void ios_clear_pool(glp_tree *tree, IOSPOOL *pool) +{ /* remove all rows (constraints) from the cut pool */ + xassert(pool != NULL); + while (pool->head != NULL) + { IOSCUT *cut = pool->head; + pool->head = cut->next; + if (cut->name != NULL) + dmp_free_atom(tree->pool, cut->name, strlen(cut->name)+1); + while (cut->ptr != NULL) + { IOSAIJ *aij = cut->ptr; + cut->ptr = aij->next; + dmp_free_atom(tree->pool, aij, sizeof(IOSAIJ)); + } + dmp_free_atom(tree->pool, cut, sizeof(IOSCUT)); + } + pool->size = 0; + pool->head = pool->tail = NULL; + pool->ord = 0, pool->curr = NULL; + return; +} + +void ios_delete_pool(glp_tree *tree, IOSPOOL *pool) +{ /* delete cut pool */ + xassert(pool != NULL); + ios_clear_pool(tree, pool); + xfree(pool); + return; +} + +#if 1 /* 11/VII-2013 */ +#include "glpnpp.h" + +void ios_process_sol(glp_tree *T) +{ /* process integer feasible solution just found */ + if (T->npp != NULL) + { /* postprocess solution from transformed mip */ + npp_postprocess(T->npp, T->mip); + /* store solution to problem passed to glp_intopt */ + npp_unload_sol(T->npp, T->P); + } + xassert(T->P != NULL); + /* save solution to text file, if requested */ + if (T->save_sol != NULL) + { char *fn, *mark; + fn = talloc(strlen(T->save_sol) + 50, char); + mark = strrchr(T->save_sol, '*'); + if (mark == NULL) + strcpy(fn, T->save_sol); + else + { memcpy(fn, T->save_sol, mark - T->save_sol); + fn[mark - T->save_sol] = '\0'; + sprintf(fn + strlen(fn), "%03d", ++(T->save_cnt)); + strcat(fn, &mark[1]); + } + glp_write_mip(T->P, fn); + tfree(fn); + } + return; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios02.c b/resources/3rdparty/glpk-4.53/src/glpios02.c new file mode 100644 index 000000000..43cff57e1 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios02.c @@ -0,0 +1,826 @@ +/* glpios02.c (preprocess current subproblem) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" + +/*********************************************************************** +* prepare_row_info - prepare row info to determine implied bounds +* +* Given a row (linear form) +* +* n +* sum a[j] * x[j] (1) +* j=1 +* +* and bounds of columns (variables) +* +* l[j] <= x[j] <= u[j] (2) +* +* this routine computes f_min, j_min, f_max, j_max needed to determine +* implied bounds. +* +* ALGORITHM +* +* Let J+ = {j : a[j] > 0} and J- = {j : a[j] < 0}. +* +* Parameters f_min and j_min are computed as follows: +* +* 1) if there is no x[k] such that k in J+ and l[k] = -inf or k in J- +* and u[k] = +inf, then +* +* f_min := sum a[j] * l[j] + sum a[j] * u[j] +* j in J+ j in J- +* (3) +* j_min := 0 +* +* 2) if there is exactly one x[k] such that k in J+ and l[k] = -inf +* or k in J- and u[k] = +inf, then +* +* f_min := sum a[j] * l[j] + sum a[j] * u[j] +* j in J+\{k} j in J-\{k} +* (4) +* j_min := k +* +* 3) if there are two or more x[k] such that k in J+ and l[k] = -inf +* or k in J- and u[k] = +inf, then +* +* f_min := -inf +* (5) +* j_min := 0 +* +* Parameters f_max and j_max are computed in a similar way as follows: +* +* 1) if there is no x[k] such that k in J+ and u[k] = +inf or k in J- +* and l[k] = -inf, then +* +* f_max := sum a[j] * u[j] + sum a[j] * l[j] +* j in J+ j in J- +* (6) +* j_max := 0 +* +* 2) if there is exactly one x[k] such that k in J+ and u[k] = +inf +* or k in J- and l[k] = -inf, then +* +* f_max := sum a[j] * u[j] + sum a[j] * l[j] +* j in J+\{k} j in J-\{k} +* (7) +* j_max := k +* +* 3) if there are two or more x[k] such that k in J+ and u[k] = +inf +* or k in J- and l[k] = -inf, then +* +* f_max := +inf +* (8) +* j_max := 0 */ + +struct f_info +{ int j_min, j_max; + double f_min, f_max; +}; + +static void prepare_row_info(int n, const double a[], const double l[], + const double u[], struct f_info *f) +{ int j, j_min, j_max; + double f_min, f_max; + xassert(n >= 0); + /* determine f_min and j_min */ + f_min = 0.0, j_min = 0; + for (j = 1; j <= n; j++) + { if (a[j] > 0.0) + { if (l[j] == -DBL_MAX) + { if (j_min == 0) + j_min = j; + else + { f_min = -DBL_MAX, j_min = 0; + break; + } + } + else + f_min += a[j] * l[j]; + } + else if (a[j] < 0.0) + { if (u[j] == +DBL_MAX) + { if (j_min == 0) + j_min = j; + else + { f_min = -DBL_MAX, j_min = 0; + break; + } + } + else + f_min += a[j] * u[j]; + } + else + xassert(a != a); + } + f->f_min = f_min, f->j_min = j_min; + /* determine f_max and j_max */ + f_max = 0.0, j_max = 0; + for (j = 1; j <= n; j++) + { if (a[j] > 0.0) + { if (u[j] == +DBL_MAX) + { if (j_max == 0) + j_max = j; + else + { f_max = +DBL_MAX, j_max = 0; + break; + } + } + else + f_max += a[j] * u[j]; + } + else if (a[j] < 0.0) + { if (l[j] == -DBL_MAX) + { if (j_max == 0) + j_max = j; + else + { f_max = +DBL_MAX, j_max = 0; + break; + } + } + else + f_max += a[j] * l[j]; + } + else + xassert(a != a); + } + f->f_max = f_max, f->j_max = j_max; + return; +} + +/*********************************************************************** +* row_implied_bounds - determine row implied bounds +* +* Given a row (linear form) +* +* n +* sum a[j] * x[j] +* j=1 +* +* and bounds of columns (variables) +* +* l[j] <= x[j] <= u[j] +* +* this routine determines implied bounds of the row. +* +* ALGORITHM +* +* Let J+ = {j : a[j] > 0} and J- = {j : a[j] < 0}. +* +* The implied lower bound of the row is computed as follows: +* +* L' := sum a[j] * l[j] + sum a[j] * u[j] (9) +* j in J+ j in J- +* +* and as it follows from (3), (4), and (5): +* +* L' := if j_min = 0 then f_min else -inf (10) +* +* The implied upper bound of the row is computed as follows: +* +* U' := sum a[j] * u[j] + sum a[j] * l[j] (11) +* j in J+ j in J- +* +* and as it follows from (6), (7), and (8): +* +* U' := if j_max = 0 then f_max else +inf (12) +* +* The implied bounds are stored in locations LL and UU. */ + +static void row_implied_bounds(const struct f_info *f, double *LL, + double *UU) +{ *LL = (f->j_min == 0 ? f->f_min : -DBL_MAX); + *UU = (f->j_max == 0 ? f->f_max : +DBL_MAX); + return; +} + +/*********************************************************************** +* col_implied_bounds - determine column implied bounds +* +* Given a row (constraint) +* +* n +* L <= sum a[j] * x[j] <= U (13) +* j=1 +* +* and bounds of columns (variables) +* +* l[j] <= x[j] <= u[j] +* +* this routine determines implied bounds of variable x[k]. +* +* It is assumed that if L != -inf, the lower bound of the row can be +* active, and if U != +inf, the upper bound of the row can be active. +* +* ALGORITHM +* +* From (13) it follows that +* +* L <= sum a[j] * x[j] + a[k] * x[k] <= U +* j!=k +* or +* +* L - sum a[j] * x[j] <= a[k] * x[k] <= U - sum a[j] * x[j] +* j!=k j!=k +* +* Thus, if the row lower bound L can be active, implied lower bound of +* term a[k] * x[k] can be determined as follows: +* +* ilb(a[k] * x[k]) = min(L - sum a[j] * x[j]) = +* j!=k +* (14) +* = L - max sum a[j] * x[j] +* j!=k +* +* where, as it follows from (6), (7), and (8) +* +* / f_max - a[k] * u[k], j_max = 0, a[k] > 0 +* | +* | f_max - a[k] * l[k], j_max = 0, a[k] < 0 +* max sum a[j] * x[j] = { +* j!=k | f_max, j_max = k +* | +* \ +inf, j_max != 0 +* +* and if the upper bound U can be active, implied upper bound of term +* a[k] * x[k] can be determined as follows: +* +* iub(a[k] * x[k]) = max(U - sum a[j] * x[j]) = +* j!=k +* (15) +* = U - min sum a[j] * x[j] +* j!=k +* +* where, as it follows from (3), (4), and (5) +* +* / f_min - a[k] * l[k], j_min = 0, a[k] > 0 +* | +* | f_min - a[k] * u[k], j_min = 0, a[k] < 0 +* min sum a[j] * x[j] = { +* j!=k | f_min, j_min = k +* | +* \ -inf, j_min != 0 +* +* Since +* +* ilb(a[k] * x[k]) <= a[k] * x[k] <= iub(a[k] * x[k]) +* +* implied lower and upper bounds of x[k] are determined as follows: +* +* l'[k] := if a[k] > 0 then ilb / a[k] else ulb / a[k] (16) +* +* u'[k] := if a[k] > 0 then ulb / a[k] else ilb / a[k] (17) +* +* The implied bounds are stored in locations ll and uu. */ + +static void col_implied_bounds(const struct f_info *f, int n, + const double a[], double L, double U, const double l[], + const double u[], int k, double *ll, double *uu) +{ double ilb, iub; + xassert(n >= 0); + xassert(1 <= k && k <= n); + /* determine implied lower bound of term a[k] * x[k] (14) */ + if (L == -DBL_MAX || f->f_max == +DBL_MAX) + ilb = -DBL_MAX; + else if (f->j_max == 0) + { if (a[k] > 0.0) + { xassert(u[k] != +DBL_MAX); + ilb = L - (f->f_max - a[k] * u[k]); + } + else if (a[k] < 0.0) + { xassert(l[k] != -DBL_MAX); + ilb = L - (f->f_max - a[k] * l[k]); + } + else + xassert(a != a); + } + else if (f->j_max == k) + ilb = L - f->f_max; + else + ilb = -DBL_MAX; + /* determine implied upper bound of term a[k] * x[k] (15) */ + if (U == +DBL_MAX || f->f_min == -DBL_MAX) + iub = +DBL_MAX; + else if (f->j_min == 0) + { if (a[k] > 0.0) + { xassert(l[k] != -DBL_MAX); + iub = U - (f->f_min - a[k] * l[k]); + } + else if (a[k] < 0.0) + { xassert(u[k] != +DBL_MAX); + iub = U - (f->f_min - a[k] * u[k]); + } + else + xassert(a != a); + } + else if (f->j_min == k) + iub = U - f->f_min; + else + iub = +DBL_MAX; + /* determine implied bounds of x[k] (16) and (17) */ +#if 1 + /* do not use a[k] if it has small magnitude to prevent wrong + implied bounds; for example, 1e-15 * x1 >= x2 + x3, where + x1 >= -10, x2, x3 >= 0, would lead to wrong conclusion that + x1 >= 0 */ + if (fabs(a[k]) < 1e-6) + *ll = -DBL_MAX, *uu = +DBL_MAX; else +#endif + if (a[k] > 0.0) + { *ll = (ilb == -DBL_MAX ? -DBL_MAX : ilb / a[k]); + *uu = (iub == +DBL_MAX ? +DBL_MAX : iub / a[k]); + } + else if (a[k] < 0.0) + { *ll = (iub == +DBL_MAX ? -DBL_MAX : iub / a[k]); + *uu = (ilb == -DBL_MAX ? +DBL_MAX : ilb / a[k]); + } + else + xassert(a != a); + return; +} + +/*********************************************************************** +* check_row_bounds - check and relax original row bounds +* +* Given a row (constraint) +* +* n +* L <= sum a[j] * x[j] <= U +* j=1 +* +* and bounds of columns (variables) +* +* l[j] <= x[j] <= u[j] +* +* this routine checks the original row bounds L and U for feasibility +* and redundancy. If the original lower bound L or/and upper bound U +* cannot be active due to bounds of variables, the routine remove them +* replacing by -inf or/and +inf, respectively. +* +* If no primal infeasibility is detected, the routine returns zero, +* otherwise non-zero. */ + +static int check_row_bounds(const struct f_info *f, double *L_, + double *U_) +{ int ret = 0; + double L = *L_, U = *U_, LL, UU; + /* determine implied bounds of the row */ + row_implied_bounds(f, &LL, &UU); + /* check if the original lower bound is infeasible */ + if (L != -DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(L)); + if (UU < L - eps) + { ret = 1; + goto done; + } + } + /* check if the original upper bound is infeasible */ + if (U != +DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(U)); + if (LL > U + eps) + { ret = 1; + goto done; + } + } + /* check if the original lower bound is redundant */ + if (L != -DBL_MAX) + { double eps = 1e-12 * (1.0 + fabs(L)); + if (LL > L - eps) + { /* it cannot be active, so remove it */ + *L_ = -DBL_MAX; + } + } + /* check if the original upper bound is redundant */ + if (U != +DBL_MAX) + { double eps = 1e-12 * (1.0 + fabs(U)); + if (UU < U + eps) + { /* it cannot be active, so remove it */ + *U_ = +DBL_MAX; + } + } +done: return ret; +} + +/*********************************************************************** +* check_col_bounds - check and tighten original column bounds +* +* Given a row (constraint) +* +* n +* L <= sum a[j] * x[j] <= U +* j=1 +* +* and bounds of columns (variables) +* +* l[j] <= x[j] <= u[j] +* +* for column (variable) x[j] this routine checks the original column +* bounds l[j] and u[j] for feasibility and redundancy. If the original +* lower bound l[j] or/and upper bound u[j] cannot be active due to +* bounds of the constraint and other variables, the routine tighten +* them replacing by corresponding implied bounds, if possible. +* +* NOTE: It is assumed that if L != -inf, the row lower bound can be +* active, and if U != +inf, the row upper bound can be active. +* +* The flag means that variable x[j] is required to be integer. +* +* New actual bounds for x[j] are stored in locations lj and uj. +* +* If no primal infeasibility is detected, the routine returns zero, +* otherwise non-zero. */ + +static int check_col_bounds(const struct f_info *f, int n, + const double a[], double L, double U, const double l[], + const double u[], int flag, int j, double *_lj, double *_uj) +{ int ret = 0; + double lj, uj, ll, uu; + xassert(n >= 0); + xassert(1 <= j && j <= n); + lj = l[j], uj = u[j]; + /* determine implied bounds of the column */ + col_implied_bounds(f, n, a, L, U, l, u, j, &ll, &uu); + /* if x[j] is integral, round its implied bounds */ + if (flag) + { if (ll != -DBL_MAX) + ll = (ll - floor(ll) < 1e-3 ? floor(ll) : ceil(ll)); + if (uu != +DBL_MAX) + uu = (ceil(uu) - uu < 1e-3 ? ceil(uu) : floor(uu)); + } + /* check if the original lower bound is infeasible */ + if (lj != -DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(lj)); + if (uu < lj - eps) + { ret = 1; + goto done; + } + } + /* check if the original upper bound is infeasible */ + if (uj != +DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(uj)); + if (ll > uj + eps) + { ret = 1; + goto done; + } + } + /* check if the original lower bound is redundant */ + if (ll != -DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(ll)); + if (lj < ll - eps) + { /* it cannot be active, so tighten it */ + lj = ll; + } + } + /* check if the original upper bound is redundant */ + if (uu != +DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(uu)); + if (uj > uu + eps) + { /* it cannot be active, so tighten it */ + uj = uu; + } + } + /* due to round-off errors it may happen that lj > uj (although + lj < uj + eps, since no primal infeasibility is detected), so + adjuct the new actual bounds to provide lj <= uj */ + if (!(lj == -DBL_MAX || uj == +DBL_MAX)) + { double t1 = fabs(lj), t2 = fabs(uj); + double eps = 1e-10 * (1.0 + (t1 <= t2 ? t1 : t2)); + if (lj > uj - eps) + { if (lj == l[j]) + uj = lj; + else if (uj == u[j]) + lj = uj; + else if (t1 <= t2) + uj = lj; + else + lj = uj; + } + } + *_lj = lj, *_uj = uj; +done: return ret; +} + +/*********************************************************************** +* check_efficiency - check if change in column bounds is efficient +* +* Given the original bounds of a column l and u and its new actual +* bounds l' and u' (possibly tighten by the routine check_col_bounds) +* this routine checks if the change in the column bounds is efficient +* enough. If so, the routine returns non-zero, otherwise zero. +* +* The flag means that the variable is required to be integer. */ + +static int check_efficiency(int flag, double l, double u, double ll, + double uu) +{ int eff = 0; + /* check efficiency for lower bound */ + if (l < ll) + { if (flag || l == -DBL_MAX) + eff++; + else + { double r; + if (u == +DBL_MAX) + r = 1.0 + fabs(l); + else + r = 1.0 + (u - l); + if (ll - l >= 0.25 * r) + eff++; + } + } + /* check efficiency for upper bound */ + if (u > uu) + { if (flag || u == +DBL_MAX) + eff++; + else + { double r; + if (l == -DBL_MAX) + r = 1.0 + fabs(u); + else + r = 1.0 + (u - l); + if (u - uu >= 0.25 * r) + eff++; + } + } + return eff; +} + +/*********************************************************************** +* basic_preprocessing - perform basic preprocessing +* +* This routine performs basic preprocessing of the specified MIP that +* includes relaxing some row bounds and tightening some column bounds. +* +* On entry the arrays L and U contains original row bounds, and the +* arrays l and u contains original column bounds: +* +* L[0] is the lower bound of the objective row; +* L[i], i = 1,...,m, is the lower bound of i-th row; +* U[0] is the upper bound of the objective row; +* U[i], i = 1,...,m, is the upper bound of i-th row; +* l[0] is not used; +* l[j], j = 1,...,n, is the lower bound of j-th column; +* u[0] is not used; +* u[j], j = 1,...,n, is the upper bound of j-th column. +* +* On exit the arrays L, U, l, and u contain new actual bounds of rows +* and column in the same locations. +* +* The parameters nrs and num specify an initial list of rows to be +* processed: +* +* nrs is the number of rows in the initial list, 0 <= nrs <= m+1; +* num[0] is not used; +* num[1,...,nrs] are row numbers (0 means the objective row). +* +* The parameter max_pass specifies the maximal number of times that +* each row can be processed, max_pass > 0. +* +* If no primal infeasibility is detected, the routine returns zero, +* otherwise non-zero. */ + +static int basic_preprocessing(glp_prob *mip, double L[], double U[], + double l[], double u[], int nrs, const int num[], int max_pass) +{ int m = mip->m; + int n = mip->n; + struct f_info f; + int i, j, k, len, size, ret = 0; + int *ind, *list, *mark, *pass; + double *val, *lb, *ub; + xassert(0 <= nrs && nrs <= m+1); + xassert(max_pass > 0); + /* allocate working arrays */ + ind = xcalloc(1+n, sizeof(int)); + list = xcalloc(1+m+1, sizeof(int)); + mark = xcalloc(1+m+1, sizeof(int)); + memset(&mark[0], 0, (m+1) * sizeof(int)); + pass = xcalloc(1+m+1, sizeof(int)); + memset(&pass[0], 0, (m+1) * sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + lb = xcalloc(1+n, sizeof(double)); + ub = xcalloc(1+n, sizeof(double)); + /* initialize the list of rows to be processed */ + size = 0; + for (k = 1; k <= nrs; k++) + { i = num[k]; + xassert(0 <= i && i <= m); + /* duplicate row numbers are not allowed */ + xassert(!mark[i]); + list[++size] = i, mark[i] = 1; + } + xassert(size == nrs); + /* process rows in the list until it becomes empty */ + while (size > 0) + { /* get a next row from the list */ + i = list[size--], mark[i] = 0; + /* increase the row processing count */ + pass[i]++; + /* if the row is free, skip it */ + if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) continue; + /* obtain coefficients of the row */ + len = 0; + if (i == 0) + { for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + if (col->coef != 0.0) + len++, ind[len] = j, val[len] = col->coef; + } + } + else + { GLPROW *row = mip->row[i]; + GLPAIJ *aij; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + len++, ind[len] = aij->col->j, val[len] = aij->val; + } + /* determine lower and upper bounds of columns corresponding + to non-zero row coefficients */ + for (k = 1; k <= len; k++) + j = ind[k], lb[k] = l[j], ub[k] = u[j]; + /* prepare the row info to determine implied bounds */ + prepare_row_info(len, val, lb, ub, &f); + /* check and relax bounds of the row */ + if (check_row_bounds(&f, &L[i], &U[i])) + { /* the feasible region is empty */ + ret = 1; + goto done; + } + /* if the row became free, drop it */ + if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) continue; + /* process columns having non-zero coefficients in the row */ + for (k = 1; k <= len; k++) + { GLPCOL *col; + int flag, eff; + double ll, uu; + /* take a next column in the row */ + j = ind[k], col = mip->col[j]; + flag = col->kind != GLP_CV; + /* check and tighten bounds of the column */ + if (check_col_bounds(&f, len, val, L[i], U[i], lb, ub, + flag, k, &ll, &uu)) + { /* the feasible region is empty */ + ret = 1; + goto done; + } + /* check if change in the column bounds is efficient */ + eff = check_efficiency(flag, l[j], u[j], ll, uu); + /* set new actual bounds of the column */ + l[j] = ll, u[j] = uu; + /* if the change is efficient, add all rows affected by the + corresponding column, to the list */ + if (eff > 0) + { GLPAIJ *aij; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + { int ii = aij->row->i; + /* if the row was processed maximal number of times, + skip it */ + if (pass[ii] >= max_pass) continue; + /* if the row is free, skip it */ + if (L[ii] == -DBL_MAX && U[ii] == +DBL_MAX) continue; + /* put the row into the list */ + if (mark[ii] == 0) + { xassert(size <= m); + list[++size] = ii, mark[ii] = 1; + } + } + } + } + } +done: /* free working arrays */ + xfree(ind); + xfree(list); + xfree(mark); + xfree(pass); + xfree(val); + xfree(lb); + xfree(ub); + return ret; +} + +/*********************************************************************** +* NAME +* +* ios_preprocess_node - preprocess current subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_preprocess_node(glp_tree *tree, int max_pass); +* +* DESCRIPTION +* +* The routine ios_preprocess_node performs basic preprocessing of the +* current subproblem. +* +* RETURNS +* +* If no primal infeasibility is detected, the routine returns zero, +* otherwise non-zero. */ + +int ios_preprocess_node(glp_tree *tree, int max_pass) +{ glp_prob *mip = tree->mip; + int m = mip->m; + int n = mip->n; + int i, j, nrs, *num, ret = 0; + double *L, *U, *l, *u; + /* the current subproblem must exist */ + xassert(tree->curr != NULL); + /* determine original row bounds */ + L = xcalloc(1+m, sizeof(double)); + U = xcalloc(1+m, sizeof(double)); + switch (mip->mip_stat) + { case GLP_UNDEF: + L[0] = -DBL_MAX, U[0] = +DBL_MAX; + break; + case GLP_FEAS: + switch (mip->dir) + { case GLP_MIN: + L[0] = -DBL_MAX, U[0] = mip->mip_obj - mip->c0; + break; + case GLP_MAX: + L[0] = mip->mip_obj - mip->c0, U[0] = +DBL_MAX; + break; + default: + xassert(mip != mip); + } + break; + default: + xassert(mip != mip); + } + for (i = 1; i <= m; i++) + { L[i] = glp_get_row_lb(mip, i); + U[i] = glp_get_row_ub(mip, i); + } + /* determine original column bounds */ + l = xcalloc(1+n, sizeof(double)); + u = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) + { l[j] = glp_get_col_lb(mip, j); + u[j] = glp_get_col_ub(mip, j); + } + /* build the initial list of rows to be analyzed */ + nrs = m + 1; + num = xcalloc(1+nrs, sizeof(int)); + for (i = 1; i <= nrs; i++) num[i] = i - 1; + /* perform basic preprocessing */ + if (basic_preprocessing(mip , L, U, l, u, nrs, num, max_pass)) + { ret = 1; + goto done; + } + /* set new actual (relaxed) row bounds */ + for (i = 1; i <= m; i++) + { /* consider only non-active rows to keep dual feasibility */ + if (glp_get_row_stat(mip, i) == GLP_BS) + { if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) + glp_set_row_bnds(mip, i, GLP_FR, 0.0, 0.0); + else if (U[i] == +DBL_MAX) + glp_set_row_bnds(mip, i, GLP_LO, L[i], 0.0); + else if (L[i] == -DBL_MAX) + glp_set_row_bnds(mip, i, GLP_UP, 0.0, U[i]); + } + } + /* set new actual (tightened) column bounds */ + for (j = 1; j <= n; j++) + { int type; + if (l[j] == -DBL_MAX && u[j] == +DBL_MAX) + type = GLP_FR; + else if (u[j] == +DBL_MAX) + type = GLP_LO; + else if (l[j] == -DBL_MAX) + type = GLP_UP; + else if (l[j] != u[j]) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(mip, j, type, l[j], u[j]); + } +done: /* free working arrays and return */ + xfree(L); + xfree(U); + xfree(l); + xfree(u); + xfree(num); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios03.c b/resources/3rdparty/glpk-4.53/src/glpios03.c new file mode 100644 index 000000000..3ee79ee04 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios03.c @@ -0,0 +1,1438 @@ +/* glpios03.c (branch-and-cut driver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" + +/*********************************************************************** +* show_progress - display current progress of the search +* +* This routine displays some information about current progress of the +* search. +* +* The information includes: +* +* the current number of iterations performed by the simplex solver; +* +* the objective value for the best known integer feasible solution, +* which is upper (minimization) or lower (maximization) global bound +* for optimal solution of the original mip problem; +* +* the best local bound for active nodes, which is lower (minimization) +* or upper (maximization) global bound for optimal solution of the +* original mip problem; +* +* the relative mip gap, in percents; +* +* the number of open (active) subproblems; +* +* the number of completely explored subproblems, i.e. whose nodes have +* been removed from the tree. */ + +static void show_progress(glp_tree *T, int bingo) +{ int p; + double temp; + char best_mip[50], best_bound[50], *rho, rel_gap[50]; + /* format the best known integer feasible solution */ + if (T->mip->mip_stat == GLP_FEAS) + sprintf(best_mip, "%17.9e", T->mip->mip_obj); + else + sprintf(best_mip, "%17s", "not found yet"); + /* determine reference number of an active subproblem whose local + bound is best */ + p = ios_best_node(T); + /* format the best bound */ + if (p == 0) + sprintf(best_bound, "%17s", "tree is empty"); + else + { temp = T->slot[p].node->bound; + if (temp == -DBL_MAX) + sprintf(best_bound, "%17s", "-inf"); + else if (temp == +DBL_MAX) + sprintf(best_bound, "%17s", "+inf"); + else + sprintf(best_bound, "%17.9e", temp); + } + /* choose the relation sign between global bounds */ + if (T->mip->dir == GLP_MIN) + rho = ">="; + else if (T->mip->dir == GLP_MAX) + rho = "<="; + else + xassert(T != T); + /* format the relative mip gap */ + temp = ios_relative_gap(T); + if (temp == 0.0) + sprintf(rel_gap, " 0.0%%"); + else if (temp < 0.001) + sprintf(rel_gap, "< 0.1%%"); + else if (temp <= 9.999) + sprintf(rel_gap, "%5.1f%%", 100.0 * temp); + else + sprintf(rel_gap, "%6s", ""); + /* display progress of the search */ + xprintf("+%6d: %s %s %s %s %s (%d; %d)\n", + T->mip->it_cnt, bingo ? ">>>>>" : "mip =", best_mip, rho, + best_bound, rel_gap, T->a_cnt, T->t_cnt - T->n_cnt); + T->tm_lag = xtime(); + return; +} + +/*********************************************************************** +* is_branch_hopeful - check if specified branch is hopeful +* +* This routine checks if the specified subproblem can have an integer +* optimal solution which is better than the best known one. +* +* The check is based on comparison of the local objective bound stored +* in the subproblem descriptor and the incumbent objective value which +* is the global objective bound. +* +* If there is a chance that the specified subproblem can have a better +* integer optimal solution, the routine returns non-zero. Otherwise, if +* the corresponding branch can pruned, zero is returned. */ + +static int is_branch_hopeful(glp_tree *T, int p) +{ xassert(1 <= p && p <= T->nslots); + xassert(T->slot[p].node != NULL); + return ios_is_hopeful(T, T->slot[p].node->bound); +} + +/*********************************************************************** +* check_integrality - check integrality of basic solution +* +* This routine checks if the basic solution of LP relaxation of the +* current subproblem satisfies to integrality conditions, i.e. that all +* variables of integer kind have integral primal values. (The solution +* is assumed to be optimal.) +* +* For each variable of integer kind the routine computes the following +* quantity: +* +* ii(x[j]) = min(x[j] - floor(x[j]), ceil(x[j]) - x[j]), (1) +* +* which is a measure of the integer infeasibility (non-integrality) of +* x[j] (for example, ii(2.1) = 0.1, ii(3.7) = 0.3, ii(5.0) = 0). It is +* understood that 0 <= ii(x[j]) <= 0.5, and variable x[j] is integer +* feasible if ii(x[j]) = 0. However, due to floating-point arithmetic +* the routine checks less restrictive condition: +* +* ii(x[j]) <= tol_int, (2) +* +* where tol_int is a given tolerance (small positive number) and marks +* each variable which does not satisfy to (2) as integer infeasible by +* setting its fractionality flag. +* +* In order to characterize integer infeasibility of the basic solution +* in the whole the routine computes two parameters: ii_cnt, which is +* the number of variables with the fractionality flag set, and ii_sum, +* which is the sum of integer infeasibilities (1). */ + +static void check_integrality(glp_tree *T) +{ glp_prob *mip = T->mip; + int j, type, ii_cnt = 0; + double lb, ub, x, temp1, temp2, ii_sum = 0.0; + /* walk through the set of columns (structural variables) */ + for (j = 1; j <= mip->n; j++) + { GLPCOL *col = mip->col[j]; + T->non_int[j] = 0; + /* if the column is not integer, skip it */ + if (col->kind != GLP_IV) continue; + /* if the column is non-basic, it is integer feasible */ + if (col->stat != GLP_BS) continue; + /* obtain the type and bounds of the column */ + type = col->type, lb = col->lb, ub = col->ub; + /* obtain value of the column in optimal basic solution */ + x = col->prim; + /* if the column's primal value is close to the lower bound, + the column is integer feasible within given tolerance */ + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { temp1 = lb - T->parm->tol_int; + temp2 = lb + T->parm->tol_int; + if (temp1 <= x && x <= temp2) continue; +#if 0 + /* the lower bound must not be violated */ + xassert(x >= lb); +#else + if (x < lb) continue; +#endif + } + /* if the column's primal value is close to the upper bound, + the column is integer feasible within given tolerance */ + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { temp1 = ub - T->parm->tol_int; + temp2 = ub + T->parm->tol_int; + if (temp1 <= x && x <= temp2) continue; +#if 0 + /* the upper bound must not be violated */ + xassert(x <= ub); +#else + if (x > ub) continue; +#endif + } + /* if the column's primal value is close to nearest integer, + the column is integer feasible within given tolerance */ + temp1 = floor(x + 0.5) - T->parm->tol_int; + temp2 = floor(x + 0.5) + T->parm->tol_int; + if (temp1 <= x && x <= temp2) continue; + /* otherwise the column is integer infeasible */ + T->non_int[j] = 1; + /* increase the number of fractional-valued columns */ + ii_cnt++; + /* compute the sum of integer infeasibilities */ + temp1 = x - floor(x); + temp2 = ceil(x) - x; + xassert(temp1 > 0.0 && temp2 > 0.0); + ii_sum += (temp1 <= temp2 ? temp1 : temp2); + } + /* store ii_cnt and ii_sum to the current problem descriptor */ + xassert(T->curr != NULL); + T->curr->ii_cnt = ii_cnt; + T->curr->ii_sum = ii_sum; + /* and also display these parameters */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + { if (ii_cnt == 0) + xprintf("There are no fractional columns\n"); + else if (ii_cnt == 1) + xprintf("There is one fractional column, integer infeasibil" + "ity is %.3e\n", ii_sum); + else + xprintf("There are %d fractional columns, integer infeasibi" + "lity is %.3e\n", ii_cnt, ii_sum); + } + return; +} + +/*********************************************************************** +* record_solution - record better integer feasible solution +* +* This routine records optimal basic solution of LP relaxation of the +* current subproblem, which being integer feasible is better than the +* best known integer feasible solution. */ + +static void record_solution(glp_tree *T) +{ glp_prob *mip = T->mip; + int i, j; + mip->mip_stat = GLP_FEAS; + mip->mip_obj = mip->obj_val; + for (i = 1; i <= mip->m; i++) + { GLPROW *row = mip->row[i]; + row->mipx = row->prim; + } + for (j = 1; j <= mip->n; j++) + { GLPCOL *col = mip->col[j]; + if (col->kind == GLP_CV) + col->mipx = col->prim; + else if (col->kind == GLP_IV) + { /* value of the integer column must be integral */ + col->mipx = floor(col->prim + 0.5); + } + else + xassert(col != col); + } + T->sol_cnt++; + return; +} + +/*********************************************************************** +* fix_by_red_cost - fix non-basic integer columns by reduced costs +* +* This routine fixes some non-basic integer columns if their reduced +* costs indicate that increasing (decreasing) the column at least by +* one involves the objective value becoming worse than the incumbent +* objective value. */ + +static void fix_by_red_cost(glp_tree *T) +{ glp_prob *mip = T->mip; + int j, stat, fixed = 0; + double obj, lb, ub, dj; + /* the global bound must exist */ + xassert(T->mip->mip_stat == GLP_FEAS); + /* basic solution of LP relaxation must be optimal */ + xassert(mip->pbs_stat == GLP_FEAS && mip->dbs_stat == GLP_FEAS); + /* determine the objective function value */ + obj = mip->obj_val; + /* walk through the column list */ + for (j = 1; j <= mip->n; j++) + { GLPCOL *col = mip->col[j]; + /* if the column is not integer, skip it */ + if (col->kind != GLP_IV) continue; + /* obtain bounds of j-th column */ + lb = col->lb, ub = col->ub; + /* and determine its status and reduced cost */ + stat = col->stat, dj = col->dual; + /* analyze the reduced cost */ + switch (mip->dir) + { case GLP_MIN: + /* minimization */ + if (stat == GLP_NL) + { /* j-th column is non-basic on its lower bound */ + if (dj < 0.0) dj = 0.0; + if (obj + dj >= mip->mip_obj) + glp_set_col_bnds(mip, j, GLP_FX, lb, lb), fixed++; + } + else if (stat == GLP_NU) + { /* j-th column is non-basic on its upper bound */ + if (dj > 0.0) dj = 0.0; + if (obj - dj >= mip->mip_obj) + glp_set_col_bnds(mip, j, GLP_FX, ub, ub), fixed++; + } + break; + case GLP_MAX: + /* maximization */ + if (stat == GLP_NL) + { /* j-th column is non-basic on its lower bound */ + if (dj > 0.0) dj = 0.0; + if (obj + dj <= mip->mip_obj) + glp_set_col_bnds(mip, j, GLP_FX, lb, lb), fixed++; + } + else if (stat == GLP_NU) + { /* j-th column is non-basic on its upper bound */ + if (dj < 0.0) dj = 0.0; + if (obj - dj <= mip->mip_obj) + glp_set_col_bnds(mip, j, GLP_FX, ub, ub), fixed++; + } + break; + default: + xassert(T != T); + } + } + if (T->parm->msg_lev >= GLP_MSG_DBG) + { if (fixed == 0) + /* nothing to say */; + else if (fixed == 1) + xprintf("One column has been fixed by reduced cost\n"); + else + xprintf("%d columns have been fixed by reduced costs\n", + fixed); + } + /* fixing non-basic columns on their current bounds does not + change the basic solution */ + xassert(mip->pbs_stat == GLP_FEAS && mip->dbs_stat == GLP_FEAS); + return; +} + +/*********************************************************************** +* branch_on - perform branching on specified variable +* +* This routine performs branching on j-th column (structural variable) +* of the current subproblem. The specified column must be of integer +* kind and must have a fractional value in optimal basic solution of +* LP relaxation of the current subproblem (i.e. only columns for which +* the flag non_int[j] is set are valid candidates to branch on). +* +* Let x be j-th structural variable, and beta be its primal fractional +* value in the current basic solution. Branching on j-th variable is +* dividing the current subproblem into two new subproblems, which are +* identical to the current subproblem with the following exception: in +* the first subproblem that begins the down-branch x has a new upper +* bound x <= floor(beta), and in the second subproblem that begins the +* up-branch x has a new lower bound x >= ceil(beta). +* +* Depending on estimation of local bounds for down- and up-branches +* this routine returns the following: +* +* 0 - both branches have been created; +* 1 - one branch is hopeless and has been pruned, so now the current +* subproblem is other branch; +* 2 - both branches are hopeless and have been pruned; new subproblem +* selection is needed to continue the search. */ + +static int branch_on(glp_tree *T, int j, int next) +{ glp_prob *mip = T->mip; + IOSNPD *node; + int m = mip->m; + int n = mip->n; + int type, dn_type, up_type, dn_bad, up_bad, p, ret, clone[1+2]; + double lb, ub, beta, new_ub, new_lb, dn_lp, up_lp, dn_bnd, up_bnd; + /* determine bounds and value of x[j] in optimal solution to LP + relaxation of the current subproblem */ + xassert(1 <= j && j <= n); + type = mip->col[j]->type; + lb = mip->col[j]->lb; + ub = mip->col[j]->ub; + beta = mip->col[j]->prim; + /* determine new bounds of x[j] for down- and up-branches */ + new_ub = floor(beta); + new_lb = ceil(beta); + switch (type) + { case GLP_FR: + dn_type = GLP_UP; + up_type = GLP_LO; + break; + case GLP_LO: + xassert(lb <= new_ub); + dn_type = (lb == new_ub ? GLP_FX : GLP_DB); + xassert(lb + 1.0 <= new_lb); + up_type = GLP_LO; + break; + case GLP_UP: + xassert(new_ub <= ub - 1.0); + dn_type = GLP_UP; + xassert(new_lb <= ub); + up_type = (new_lb == ub ? GLP_FX : GLP_DB); + break; + case GLP_DB: + xassert(lb <= new_ub && new_ub <= ub - 1.0); + dn_type = (lb == new_ub ? GLP_FX : GLP_DB); + xassert(lb + 1.0 <= new_lb && new_lb <= ub); + up_type = (new_lb == ub ? GLP_FX : GLP_DB); + break; + default: + xassert(type != type); + } + /* compute local bounds to LP relaxation for both branches */ + ios_eval_degrad(T, j, &dn_lp, &up_lp); + /* and improve them by rounding */ + dn_bnd = ios_round_bound(T, dn_lp); + up_bnd = ios_round_bound(T, up_lp); + /* check local bounds for down- and up-branches */ + dn_bad = !ios_is_hopeful(T, dn_bnd); + up_bad = !ios_is_hopeful(T, up_bnd); + if (dn_bad && up_bad) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Both down- and up-branches are hopeless\n"); + ret = 2; + goto done; + } + else if (up_bad) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Up-branch is hopeless\n"); + glp_set_col_bnds(mip, j, dn_type, lb, new_ub); + T->curr->lp_obj = dn_lp; + if (mip->dir == GLP_MIN) + { if (T->curr->bound < dn_bnd) + T->curr->bound = dn_bnd; + } + else if (mip->dir == GLP_MAX) + { if (T->curr->bound > dn_bnd) + T->curr->bound = dn_bnd; + } + else + xassert(mip != mip); + ret = 1; + goto done; + } + else if (dn_bad) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Down-branch is hopeless\n"); + glp_set_col_bnds(mip, j, up_type, new_lb, ub); + T->curr->lp_obj = up_lp; + if (mip->dir == GLP_MIN) + { if (T->curr->bound < up_bnd) + T->curr->bound = up_bnd; + } + else if (mip->dir == GLP_MAX) + { if (T->curr->bound > up_bnd) + T->curr->bound = up_bnd; + } + else + xassert(mip != mip); + ret = 1; + goto done; + } + /* both down- and up-branches seem to be hopeful */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Branching on column %d, primal value is %.9e\n", + j, beta); + /* determine the reference number of the current subproblem */ + xassert(T->curr != NULL); + p = T->curr->p; + T->curr->br_var = j; + T->curr->br_val = beta; + /* freeze the current subproblem */ + ios_freeze_node(T); + /* create two clones of the current subproblem; the first clone + begins the down-branch, the second one begins the up-branch */ + ios_clone_node(T, p, 2, clone); + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Node %d begins down branch, node %d begins up branch " + "\n", clone[1], clone[2]); + /* set new upper bound of j-th column in the down-branch */ + node = T->slot[clone[1]].node; + xassert(node != NULL); + xassert(node->up != NULL); + xassert(node->b_ptr == NULL); + node->b_ptr = dmp_get_atom(T->pool, sizeof(IOSBND)); + node->b_ptr->k = m + j; + node->b_ptr->type = (unsigned char)dn_type; + node->b_ptr->lb = lb; + node->b_ptr->ub = new_ub; + node->b_ptr->next = NULL; + node->lp_obj = dn_lp; + if (mip->dir == GLP_MIN) + { if (node->bound < dn_bnd) + node->bound = dn_bnd; + } + else if (mip->dir == GLP_MAX) + { if (node->bound > dn_bnd) + node->bound = dn_bnd; + } + else + xassert(mip != mip); + /* set new lower bound of j-th column in the up-branch */ + node = T->slot[clone[2]].node; + xassert(node != NULL); + xassert(node->up != NULL); + xassert(node->b_ptr == NULL); + node->b_ptr = dmp_get_atom(T->pool, sizeof(IOSBND)); + node->b_ptr->k = m + j; + node->b_ptr->type = (unsigned char)up_type; + node->b_ptr->lb = new_lb; + node->b_ptr->ub = ub; + node->b_ptr->next = NULL; + node->lp_obj = up_lp; + if (mip->dir == GLP_MIN) + { if (node->bound < up_bnd) + node->bound = up_bnd; + } + else if (mip->dir == GLP_MAX) + { if (node->bound > up_bnd) + node->bound = up_bnd; + } + else + xassert(mip != mip); + /* suggest the subproblem to be solved next */ + xassert(T->child == 0); + if (next == GLP_NO_BRNCH) + T->child = 0; + else if (next == GLP_DN_BRNCH) + T->child = clone[1]; + else if (next == GLP_UP_BRNCH) + T->child = clone[2]; + else + xassert(next != next); + ret = 0; +done: return ret; +} + +/*********************************************************************** +* cleanup_the_tree - prune hopeless branches from the tree +* +* This routine walks through the active list and checks the local +* bound for every active subproblem. If the local bound indicates that +* the subproblem cannot have integer optimal solution better than the +* incumbent objective value, the routine deletes such subproblem that, +* in turn, involves pruning the corresponding branch of the tree. */ + +static void cleanup_the_tree(glp_tree *T) +{ IOSNPD *node, *next_node; + int count = 0; + /* the global bound must exist */ + xassert(T->mip->mip_stat == GLP_FEAS); + /* walk through the list of active subproblems */ + for (node = T->head; node != NULL; node = next_node) + { /* deleting some active problem node may involve deleting its + parents recursively; however, all its parents being created + *before* it are always *precede* it in the node list, so + the next problem node is never affected by such deletion */ + next_node = node->next; + /* if the branch is hopeless, prune it */ + if (!is_branch_hopeful(T, node->p)) + ios_delete_node(T, node->p), count++; + } + if (T->parm->msg_lev >= GLP_MSG_DBG) + { if (count == 1) + xprintf("One hopeless branch has been pruned\n"); + else if (count > 1) + xprintf("%d hopeless branches have been pruned\n", count); + } + return; +} + +#if 0 /* 09/VII-2013 */ +/*********************************************************************** +* round_heur - simple rounding heuristic +* +* This routine attempts to guess an integer feasible solution by +* simple rounding values of all integer variables in basic solution to +* nearest integers. */ + +static int round_heur(glp_tree *T) +{ glp_prob *P = T->mip; + int m = P->m; + int n = P->n; + int i, j, ret; + double *x; + /* compute rounded values of variables */ + x = talloc(1+n, double); + for (j = 1; j <= n; j++) + { GLPCOL *col = P->col[j]; + if (col->kind == GLP_IV) + { /* integer variable */ + x[j] = floor(col->prim + 0.5); + } + else if (col->type == GLP_FX) + { /* fixed variable */ + x[j] = col->prim; + } + else + { /* non-integer non-fixed variable */ + ret = 3; + goto done; + } + } + /* check that no constraints are violated */ + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + int type = row->type; + GLPAIJ *aij; + double sum; + if (type == GLP_FR) + continue; + /* compute value of linear form */ + sum = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + sum += aij->val * x[aij->col->j]; + /* check lower bound */ + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { if (sum < row->lb - 1e-9) + { /* lower bound is violated */ + ret = 2; + goto done; + } + } + /* check upper bound */ + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { if (sum > row->ub + 1e-9) + { /* upper bound is violated */ + ret = 2; + goto done; + } + } + } + /* rounded solution is integer feasible */ + if (glp_ios_heur_sol(T, x) == 0) + { /* solution is accepted */ + ret = 0; + } + else + { /* solution is rejected */ + ret = 1; + } +done: tfree(x); + return ret; +} +#else +/*********************************************************************** +* round_heur - simple rounding heuristic +* +* This routine attempts to guess an integer feasible solution by +* simple rounding values of all integer variables in basic solution to +* nearest integers. */ + +static int round_heur(glp_tree *T) +{ glp_prob *P = T->mip; + /*int m = P->m;*/ + int n = P->n; + int i, j, ret; + double *x; + /* compute rounded values of variables */ + x = talloc(1+n, double); + for (j = 1; j <= n; j++) + { GLPCOL *col = P->col[j]; + if (col->kind == GLP_IV) + { /* integer variable */ + x[j] = floor(col->prim + 0.5); + } + else if (col->type == GLP_FX) + { /* fixed variable */ + x[j] = col->prim; + } + else + { /* non-integer non-fixed variable */ + ret = 3; + goto done; + } + } + /* check that no constraints are violated */ + for (i = 1; i <= T->orig_m; i++) + { int type = T->orig_type[i]; + GLPAIJ *aij; + double sum; + if (type == GLP_FR) + continue; + /* compute value of linear form */ + sum = 0.0; + for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) + sum += aij->val * x[aij->col->j]; + /* check lower bound */ + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { if (sum < T->orig_lb[i] - 1e-9) + { /* lower bound is violated */ + ret = 2; + goto done; + } + } + /* check upper bound */ + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { if (sum > T->orig_ub[i] + 1e-9) + { /* upper bound is violated */ + ret = 2; + goto done; + } + } + } + /* rounded solution is integer feasible */ + if (glp_ios_heur_sol(T, x) == 0) + { /* solution is accepted */ + ret = 0; + } + else + { /* solution is rejected */ + ret = 1; + } +done: tfree(x); + return ret; +} +#endif + +#if 0 +#define round_heur round_heur2 +static int round_heur(glp_tree *T) +{ glp_prob *lp; + int *ind, ret, i, j, len; + double *val; + lp = glp_create_prob(); + ind = talloc(1+T->mip->n, int); + val = talloc(1+T->mip->n, double); + glp_add_rows(lp, T->orig_m); + glp_add_cols(lp, T->n); + for (i = 1; i <= T->orig_m; i++) + { glp_set_row_bnds(lp, i, + T->orig_type[i], T->orig_lb[i], T->orig_ub[i]); + len = glp_get_mat_row(T->mip, i, ind, val); + glp_set_mat_row(lp, i, len, ind, val); + } + for (j = 1; j <= T->n; j++) + { GLPCOL *col = T->mip->col[j]; + glp_set_obj_coef(lp, j, col->coef); + if (col->kind == GLP_IV) + { /* integer variable */ + glp_set_col_bnds(lp, j, GLP_FX, floor(col->prim + .5), 0); + } + else + { glp_set_col_bnds(lp, j, T->orig_type[T->orig_m+j], + T->orig_lb[T->orig_m+j], T->orig_ub[T->orig_m+j]); + } + } +glp_term_out(GLP_OFF); + glp_adv_basis(lp, 0); + ret = glp_simplex(lp, NULL); +glp_term_out(GLP_ON); + if (ret != 0) + { ret = 1; + goto done; + } + if (glp_get_status(lp) != GLP_OPT) + { ret = 2; + goto done; + } + for (j = 1; j <= lp->n; j++) + val[j] = lp->col[j]->prim; + if (glp_ios_heur_sol(T, val) == 0) + ret = 0; + else + ret = 3; +done: glp_delete_prob(lp); + tfree(ind); + tfree(val); + return ret; +} +#endif + +/**********************************************************************/ + +static void generate_cuts(glp_tree *T) +{ /* generate generic cuts with built-in generators */ + if (!(T->parm->mir_cuts == GLP_ON || + T->parm->gmi_cuts == GLP_ON || + T->parm->cov_cuts == GLP_ON || + T->parm->clq_cuts == GLP_ON)) goto done; +#if 1 /* 20/IX-2008 */ + { int i, max_cuts, added_cuts; + max_cuts = T->n; + if (max_cuts < 1000) max_cuts = 1000; + added_cuts = 0; + for (i = T->orig_m+1; i <= T->mip->m; i++) + { if (T->mip->row[i]->origin == GLP_RF_CUT) + added_cuts++; + } + /* xprintf("added_cuts = %d\n", added_cuts); */ + if (added_cuts >= max_cuts) goto done; + } +#endif + /* generate and add to POOL all cuts violated by x* */ + if (T->parm->gmi_cuts == GLP_ON) + { if (T->curr->changed < 7) + ios_gmi_gen(T); + } + if (T->parm->mir_cuts == GLP_ON) + { xassert(T->mir_gen != NULL); + ios_mir_gen(T, T->mir_gen); + } + if (T->parm->cov_cuts == GLP_ON) + { /* cover cuts works well along with mir cuts */ + /*if (T->round <= 5)*/ + ios_cov_gen(T); + } + if (T->parm->clq_cuts == GLP_ON) + { if (T->clq_gen != NULL) +#if 0 /* 29/VI-2013 */ + { if (T->curr->level == 0 && T->curr->changed < 50 || + T->curr->level > 0 && T->curr->changed < 5) +#else /* FIXME */ + { if (T->curr->level == 0 && T->curr->changed < 500 || + T->curr->level > 0 && T->curr->changed < 50) +#endif + ios_clq_gen(T, T->clq_gen); + } + } +done: return; +} + +/**********************************************************************/ + +static void remove_cuts(glp_tree *T) +{ /* remove inactive cuts (some valueable globally valid cut might + be saved in the global cut pool) */ + int i, cnt = 0, *num = NULL; + xassert(T->curr != NULL); + for (i = T->orig_m+1; i <= T->mip->m; i++) + { if (T->mip->row[i]->origin == GLP_RF_CUT && + T->mip->row[i]->level == T->curr->level && + T->mip->row[i]->stat == GLP_BS) + { if (num == NULL) + num = xcalloc(1+T->mip->m, sizeof(int)); + num[++cnt] = i; + } + } + if (cnt > 0) + { glp_del_rows(T->mip, cnt, num); +#if 0 + xprintf("%d inactive cut(s) removed\n", cnt); +#endif + xfree(num); + xassert(glp_factorize(T->mip) == 0); + } + return; +} + +/**********************************************************************/ + +static void display_cut_info(glp_tree *T) +{ glp_prob *mip = T->mip; + int i, gmi = 0, mir = 0, cov = 0, clq = 0, app = 0; + for (i = mip->m; i > 0; i--) + { GLPROW *row; + row = mip->row[i]; + /* if (row->level < T->curr->level) break; */ + if (row->origin == GLP_RF_CUT) + { if (row->klass == GLP_RF_GMI) + gmi++; + else if (row->klass == GLP_RF_MIR) + mir++; + else if (row->klass == GLP_RF_COV) + cov++; + else if (row->klass == GLP_RF_CLQ) + clq++; + else + app++; + } + } + xassert(T->curr != NULL); + if (gmi + mir + cov + clq + app > 0) + { xprintf("Cuts on level %d:", T->curr->level); + if (gmi > 0) xprintf(" gmi = %d;", gmi); + if (mir > 0) xprintf(" mir = %d;", mir); + if (cov > 0) xprintf(" cov = %d;", cov); + if (clq > 0) xprintf(" clq = %d;", clq); + if (app > 0) xprintf(" app = %d;", app); + xprintf("\n"); + } + return; +} + +/*********************************************************************** +* NAME +* +* ios_driver - branch-and-cut driver +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_driver(glp_tree *T); +* +* DESCRIPTION +* +* The routine ios_driver is a branch-and-cut driver. It controls the +* MIP solution process. +* +* RETURNS +* +* 0 The MIP problem instance has been successfully solved. This code +* does not necessarily mean that the solver has found optimal +* solution. It only means that the solution process was successful. +* +* GLP_EFAIL +* The search was prematurely terminated due to the solver failure. +* +* GLP_EMIPGAP +* The search was prematurely terminated, because the relative mip +* gap tolerance has been reached. +* +* GLP_ETMLIM +* The search was prematurely terminated, because the time limit has +* been exceeded. +* +* GLP_ESTOP +* The search was prematurely terminated by application. */ + +int ios_driver(glp_tree *T) +{ int p, curr_p, p_stat, d_stat, ret; +#if 1 /* carry out to glp_tree */ + int pred_p = 0; + /* if the current subproblem has been just created due to + branching, pred_p is the reference number of its parent + subproblem, otherwise pred_p is zero */ +#endif +#if 1 /* 18/VII-2013 */ + int bad_cut; + double old_obj; +#endif +#if 0 /* 10/VI-2013 */ + glp_long ttt = T->tm_beg; +#else + double ttt = T->tm_beg; +#endif +#if 0 + ((glp_iocp *)T->parm)->msg_lev = GLP_MSG_DBG; +#endif + /* on entry to the B&B driver it is assumed that the active list + contains the only active (i.e. root) subproblem, which is the + original MIP problem to be solved */ +loop: /* main loop starts here */ + /* at this point the current subproblem does not exist */ + xassert(T->curr == NULL); + /* if the active list is empty, the search is finished */ + if (T->head == NULL) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Active list is empty!\n"); +#if 0 /* 10/VI-2013 */ + xassert(dmp_in_use(T->pool).lo == 0); +#else + xassert(dmp_in_use(T->pool) == 0); +#endif + ret = 0; + goto done; + } + /* select some active subproblem to continue the search */ + xassert(T->next_p == 0); + /* let the application program select subproblem */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_ISELECT; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + } + if (T->next_p != 0) + { /* the application program has selected something */ + ; + } + else if (T->a_cnt == 1) + { /* the only active subproblem exists, so select it */ + xassert(T->head->next == NULL); + T->next_p = T->head->p; + } + else if (T->child != 0) + { /* select one of branching childs suggested by the branching + heuristic */ + T->next_p = T->child; + } + else + { /* select active subproblem as specified by the backtracking + technique option */ + T->next_p = ios_choose_node(T); + } + /* the active subproblem just selected becomes current */ + ios_revive_node(T, T->next_p); + T->next_p = T->child = 0; + /* invalidate pred_p, if it is not the reference number of the + parent of the current subproblem */ + if (T->curr->up != NULL && T->curr->up->p != pred_p) pred_p = 0; + /* determine the reference number of the current subproblem */ + p = T->curr->p; + if (T->parm->msg_lev >= GLP_MSG_DBG) + { xprintf("-----------------------------------------------------" + "-------------------\n"); + xprintf("Processing node %d at level %d\n", p, T->curr->level); + } +#if 0 + if (p == 1) + glp_write_lp(T->mip, NULL, "root.lp"); +#endif + /* if it is the root subproblem, initialize cut generators */ + if (p == 1) + { if (T->parm->gmi_cuts == GLP_ON) + { if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Gomory's cuts enabled\n"); + } + if (T->parm->mir_cuts == GLP_ON) + { if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("MIR cuts enabled\n"); + xassert(T->mir_gen == NULL); + T->mir_gen = ios_mir_init(T); + } + if (T->parm->cov_cuts == GLP_ON) + { if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Cover cuts enabled\n"); + } + if (T->parm->clq_cuts == GLP_ON) + { xassert(T->clq_gen == NULL); + if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Clique cuts enabled\n"); + T->clq_gen = ios_clq_init(T); + } + } +#if 1 /* 18/VII-2013 */ + bad_cut = 0; +#endif +more: /* minor loop starts here */ + /* at this point the current subproblem needs either to be solved + for the first time or re-optimized due to reformulation */ + /* display current progress of the search */ + if (T->parm->msg_lev >= GLP_MSG_DBG || + T->parm->msg_lev >= GLP_MSG_ON && + (double)(T->parm->out_frq - 1) <= + 1000.0 * xdifftime(xtime(), T->tm_lag)) + show_progress(T, 0); + if (T->parm->msg_lev >= GLP_MSG_ALL && + xdifftime(xtime(), ttt) >= 60.0) +#if 0 /* 16/II-2012 */ + { glp_long total; + glp_mem_usage(NULL, NULL, &total, NULL); + xprintf("Time used: %.1f secs. Memory used: %.1f Mb.\n", + xdifftime(xtime(), T->tm_beg), xltod(total) / 1048576.0); + ttt = xtime(); + } +#else + { size_t total; + glp_mem_usage(NULL, NULL, &total, NULL); + xprintf("Time used: %.1f secs. Memory used: %.1f Mb.\n", + xdifftime(xtime(), T->tm_beg), (double)total / 1048576.0); + ttt = xtime(); + } +#endif + /* check the mip gap */ + if (T->parm->mip_gap > 0.0 && + ios_relative_gap(T) <= T->parm->mip_gap) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Relative gap tolerance reached; search terminated " + "\n"); + ret = GLP_EMIPGAP; + goto done; + } + /* check if the time limit has been exhausted */ + if (T->parm->tm_lim < INT_MAX && + (double)(T->parm->tm_lim - 1) <= + 1000.0 * xdifftime(xtime(), T->tm_beg)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Time limit exhausted; search terminated\n"); + ret = GLP_ETMLIM; + goto done; + } + /* let the application program preprocess the subproblem */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_IPREPRO; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + } + /* perform basic preprocessing */ + if (T->parm->pp_tech == GLP_PP_NONE) + ; + else if (T->parm->pp_tech == GLP_PP_ROOT) + { if (T->curr->level == 0) + { if (ios_preprocess_node(T, 100)) + goto fath; + } + } + else if (T->parm->pp_tech == GLP_PP_ALL) + { if (ios_preprocess_node(T, T->curr->level == 0 ? 100 : 10)) + goto fath; + } + else + xassert(T != T); + /* preprocessing may improve the global bound */ + if (!is_branch_hopeful(T, p)) + { xprintf("*** not tested yet ***\n"); + goto fath; + } + /* solve LP relaxation of the current subproblem */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Solving LP relaxation...\n"); + ret = ios_solve_node(T); + if (!(ret == 0 || ret == GLP_EOBJLL || ret == GLP_EOBJUL)) + { if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("ios_driver: unable to solve current LP relaxation;" + " glp_simplex returned %d\n", ret); + ret = GLP_EFAIL; + goto done; + } + /* analyze status of the basic solution to LP relaxation found */ + p_stat = T->mip->pbs_stat; + d_stat = T->mip->dbs_stat; + if (p_stat == GLP_FEAS && d_stat == GLP_FEAS) + { /* LP relaxation has optimal solution */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Found optimal solution to LP relaxation\n"); + } + else if (d_stat == GLP_NOFEAS) + { /* LP relaxation has no dual feasible solution */ + /* since the current subproblem cannot have a larger feasible + region than its parent, there is something wrong */ + if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("ios_driver: current LP relaxation has no dual feas" + "ible solution\n"); + ret = GLP_EFAIL; + goto done; + } + else if (p_stat == GLP_INFEAS && d_stat == GLP_FEAS) + { /* LP relaxation has no primal solution which is better than + the incumbent objective value */ + xassert(T->mip->mip_stat == GLP_FEAS); + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("LP relaxation has no solution better than incumben" + "t objective value\n"); + /* prune the branch */ + goto fath; + } + else if (p_stat == GLP_NOFEAS) + { /* LP relaxation has no primal feasible solution */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("LP relaxation has no feasible solution\n"); + /* prune the branch */ + goto fath; + } + else + { /* other cases cannot appear */ + xassert(T->mip != T->mip); + } + /* at this point basic solution to LP relaxation of the current + subproblem is optimal */ + xassert(p_stat == GLP_FEAS && d_stat == GLP_FEAS); + xassert(T->curr != NULL); + T->curr->lp_obj = T->mip->obj_val; + /* thus, it defines a local bound to integer optimal solution of + the current subproblem */ + { double bound = T->mip->obj_val; + /* some local bound to the current subproblem could be already + set before, so we should only improve it */ + bound = ios_round_bound(T, bound); + if (T->mip->dir == GLP_MIN) + { if (T->curr->bound < bound) + T->curr->bound = bound; + } + else if (T->mip->dir == GLP_MAX) + { if (T->curr->bound > bound) + T->curr->bound = bound; + } + else + xassert(T->mip != T->mip); + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Local bound is %.9e\n", bound); + } + /* if the local bound indicates that integer optimal solution of + the current subproblem cannot be better than the global bound, + prune the branch */ + if (!is_branch_hopeful(T, p)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Current branch is hopeless and can be pruned\n"); + goto fath; + } + /* let the application program generate additional rows ("lazy" + constraints) */ + xassert(T->reopt == 0); + xassert(T->reinv == 0); + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_IROWGEN; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + if (T->reopt) + { /* some rows were added; re-optimization is needed */ + T->reopt = T->reinv = 0; + goto more; + } + if (T->reinv) + { /* no rows were added, however, some inactive rows were + removed */ + T->reinv = 0; + xassert(glp_factorize(T->mip) == 0); + } + } + /* check if the basic solution is integer feasible */ + check_integrality(T); + /* if the basic solution satisfies to all integrality conditions, + it is a new, better integer feasible solution */ + if (T->curr->ii_cnt == 0) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("New integer feasible solution found\n"); + if (T->parm->msg_lev >= GLP_MSG_ALL) + display_cut_info(T); + record_solution(T); + if (T->parm->msg_lev >= GLP_MSG_ON) + show_progress(T, 1); +#if 1 /* 11/VII-2013 */ + ios_process_sol(T); +#endif + /* make the application program happy */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_IBINGO; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + } + /* since the current subproblem has been fathomed, prune its + branch */ + goto fath; + } + /* at this point basic solution to LP relaxation of the current + subproblem is optimal, but integer infeasible */ + /* try to fix some non-basic structural variables of integer kind + on their current bounds due to reduced costs */ + if (T->mip->mip_stat == GLP_FEAS) + fix_by_red_cost(T); + /* let the application program try to find some solution to the + original MIP with a primal heuristic */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_IHEUR; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + /* check if the current branch became hopeless */ + if (!is_branch_hopeful(T, p)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Current branch became hopeless and can be prune" + "d\n"); + goto fath; + } + } + /* try to find solution with the feasibility pump heuristic */ + if (T->parm->fp_heur) + { xassert(T->reason == 0); + T->reason = GLP_IHEUR; + ios_feas_pump(T); + T->reason = 0; + /* check if the current branch became hopeless */ + if (!is_branch_hopeful(T, p)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Current branch became hopeless and can be prune" + "d\n"); + goto fath; + } + } +#if 1 /* 25/V-2013 */ + /* try to find solution with the proximity search heuristic */ + if (T->parm->ps_heur) + { xassert(T->reason == 0); + T->reason = GLP_IHEUR; + ios_proxy_heur(T); + T->reason = 0; + /* check if the current branch became hopeless */ + if (!is_branch_hopeful(T, p)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Current branch became hopeless and can be prune" + "d\n"); + goto fath; + } + } +#endif +#if 1 /* 09/VII-2013 */ + /* try to find solution with a simple rounding heuristic */ + { xassert(T->reason == 0); + T->reason = GLP_IHEUR; + round_heur(T); + T->reason = 0; + /* check if the current branch became hopeless */ + if (!is_branch_hopeful(T, p)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Current branch became hopeless and can be prune" + "d\n"); + goto fath; + } + } +#endif + /* it's time to generate cutting planes */ + xassert(T->local != NULL); + xassert(T->local->size == 0); + /* let the application program generate some cuts; note that it + can add cuts either to the local cut pool or directly to the + current subproblem */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_ICUTGEN; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + } +#if 1 /* 18/VII-2013 */ + if (T->curr->changed > 0) + { double degrad = fabs(T->curr->lp_obj - old_obj); + if (degrad < 1e-4 * (1.0 + fabs(old_obj))) + bad_cut++; + else + bad_cut = 0; + } + old_obj = T->curr->lp_obj; + if (bad_cut == 0 || (T->curr->level == 0 && bad_cut <= 3)) +#endif + /* try to generate generic cuts with built-in generators + (as suggested by Prof. Fischetti et al. the built-in cuts are + not generated at each branching node; an intense attempt of + generating new cuts is only made at the root node, and then + a moderate effort is spent after each backtracking step) */ + if (T->curr->level == 0 || pred_p == 0) + { xassert(T->reason == 0); + T->reason = GLP_ICUTGEN; + generate_cuts(T); + T->reason = 0; + } + /* if the local cut pool is not empty, select useful cuts and add + them to the current subproblem */ + if (T->local->size > 0) + { xassert(T->reason == 0); + T->reason = GLP_ICUTGEN; + ios_process_cuts(T); + T->reason = 0; + } + /* clear the local cut pool */ + ios_clear_pool(T, T->local); + /* perform re-optimization, if necessary */ + if (T->reopt) + { T->reopt = 0; + T->curr->changed++; + goto more; + } + /* no cuts were generated; remove inactive cuts */ + remove_cuts(T); + if (T->parm->msg_lev >= GLP_MSG_ALL && T->curr->level == 0) + display_cut_info(T); + /* update history information used on pseudocost branching */ + if (T->pcost != NULL) ios_pcost_update(T); + /* it's time to perform branching */ + xassert(T->br_var == 0); + xassert(T->br_sel == 0); + /* let the application program choose variable to branch on */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + xassert(T->br_var == 0); + xassert(T->br_sel == 0); + T->reason = GLP_IBRANCH; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + } + /* if nothing has been chosen, choose some variable as specified + by the branching technique option */ + if (T->br_var == 0) + T->br_var = ios_choose_var(T, &T->br_sel); + /* perform actual branching */ + curr_p = T->curr->p; + ret = branch_on(T, T->br_var, T->br_sel); + T->br_var = T->br_sel = 0; + if (ret == 0) + { /* both branches have been created */ + pred_p = curr_p; + goto loop; + } + else if (ret == 1) + { /* one branch is hopeless and has been pruned, so now the + current subproblem is other branch */ + /* the current subproblem should be considered as a new one, + since one bound of the branching variable was changed */ + T->curr->solved = T->curr->changed = 0; +#if 1 /* 18/VII-2013 */ + /* bad_cut = 0; */ +#endif + goto more; + } + else if (ret == 2) + { /* both branches are hopeless and have been pruned; new + subproblem selection is needed to continue the search */ + goto fath; + } + else + xassert(ret != ret); +fath: /* the current subproblem has been fathomed */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Node %d fathomed\n", p); + /* freeze the current subproblem */ + ios_freeze_node(T); + /* and prune the corresponding branch of the tree */ + ios_delete_node(T, p); + /* if a new integer feasible solution has just been found, other + branches may become hopeless and therefore must be pruned */ + if (T->mip->mip_stat == GLP_FEAS) cleanup_the_tree(T); + /* new subproblem selection is needed due to backtracking */ + pred_p = 0; + goto loop; +done: /* display progress of the search on exit from the solver */ + if (T->parm->msg_lev >= GLP_MSG_ON) + show_progress(T, 0); + if (T->mir_gen != NULL) + ios_mir_term(T->mir_gen), T->mir_gen = NULL; + if (T->clq_gen != NULL) + ios_clq_term(T->clq_gen), T->clq_gen = NULL; + /* return to the calling program */ + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios04.c b/resources/3rdparty/glpk-4.53/src/glpios04.c new file mode 100644 index 000000000..8074f7e71 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios04.c @@ -0,0 +1,304 @@ +/* glpios04.c (operations on sparse vectors) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" + +/*********************************************************************** +* NAME +* +* ios_create_vec - create sparse vector +* +* SYNOPSIS +* +* #include "glpios.h" +* IOSVEC *ios_create_vec(int n); +* +* DESCRIPTION +* +* The routine ios_create_vec creates a sparse vector of dimension n, +* which initially is a null vector. +* +* RETURNS +* +* The routine returns a pointer to the vector created. */ + +IOSVEC *ios_create_vec(int n) +{ IOSVEC *v; + xassert(n >= 0); + v = xmalloc(sizeof(IOSVEC)); + v->n = n; + v->nnz = 0; + v->pos = xcalloc(1+n, sizeof(int)); + memset(&v->pos[1], 0, n * sizeof(int)); + v->ind = xcalloc(1+n, sizeof(int)); + v->val = xcalloc(1+n, sizeof(double)); + return v; +} + +/*********************************************************************** +* NAME +* +* ios_check_vec - check that sparse vector has correct representation +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_check_vec(IOSVEC *v); +* +* DESCRIPTION +* +* The routine ios_check_vec checks that a sparse vector specified by +* the parameter v has correct representation. +* +* NOTE +* +* Complexity of this operation is O(n). */ + +void ios_check_vec(IOSVEC *v) +{ int j, k, nnz; + xassert(v->n >= 0); + nnz = 0; + for (j = v->n; j >= 1; j--) + { k = v->pos[j]; + xassert(0 <= k && k <= v->nnz); + if (k != 0) + { xassert(v->ind[k] == j); + nnz++; + } + } + xassert(v->nnz == nnz); + return; +} + +/*********************************************************************** +* NAME +* +* ios_get_vj - retrieve component of sparse vector +* +* SYNOPSIS +* +* #include "glpios.h" +* double ios_get_vj(IOSVEC *v, int j); +* +* RETURNS +* +* The routine ios_get_vj returns j-th component of a sparse vector +* specified by the parameter v. */ + +double ios_get_vj(IOSVEC *v, int j) +{ int k; + xassert(1 <= j && j <= v->n); + k = v->pos[j]; + xassert(0 <= k && k <= v->nnz); + return (k == 0 ? 0.0 : v->val[k]); +} + +/*********************************************************************** +* NAME +* +* ios_set_vj - set/change component of sparse vector +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_set_vj(IOSVEC *v, int j, double val); +* +* DESCRIPTION +* +* The routine ios_set_vj assigns val to j-th component of a sparse +* vector specified by the parameter v. */ + +void ios_set_vj(IOSVEC *v, int j, double val) +{ int k; + xassert(1 <= j && j <= v->n); + k = v->pos[j]; + if (val == 0.0) + { if (k != 0) + { /* remove j-th component */ + v->pos[j] = 0; + if (k < v->nnz) + { v->pos[v->ind[v->nnz]] = k; + v->ind[k] = v->ind[v->nnz]; + v->val[k] = v->val[v->nnz]; + } + v->nnz--; + } + } + else + { if (k == 0) + { /* create j-th component */ + k = ++(v->nnz); + v->pos[j] = k; + v->ind[k] = j; + } + v->val[k] = val; + } + return; +} + +/*********************************************************************** +* NAME +* +* ios_clear_vec - set all components of sparse vector to zero +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_clear_vec(IOSVEC *v); +* +* DESCRIPTION +* +* The routine ios_clear_vec sets all components of a sparse vector +* specified by the parameter v to zero. */ + +void ios_clear_vec(IOSVEC *v) +{ int k; + for (k = 1; k <= v->nnz; k++) + v->pos[v->ind[k]] = 0; + v->nnz = 0; + return; +} + +/*********************************************************************** +* NAME +* +* ios_clean_vec - remove zero or small components from sparse vector +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_clean_vec(IOSVEC *v, double eps); +* +* DESCRIPTION +* +* The routine ios_clean_vec removes zero components and components +* whose magnitude is less than eps from a sparse vector specified by +* the parameter v. If eps is 0.0, only zero components are removed. */ + +void ios_clean_vec(IOSVEC *v, double eps) +{ int k, nnz; + nnz = 0; + for (k = 1; k <= v->nnz; k++) + { if (fabs(v->val[k]) == 0.0 || fabs(v->val[k]) < eps) + { /* remove component */ + v->pos[v->ind[k]] = 0; + } + else + { /* keep component */ + nnz++; + v->pos[v->ind[k]] = nnz; + v->ind[nnz] = v->ind[k]; + v->val[nnz] = v->val[k]; + } + } + v->nnz = nnz; + return; +} + +/*********************************************************************** +* NAME +* +* ios_copy_vec - copy sparse vector (x := y) +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_copy_vec(IOSVEC *x, IOSVEC *y); +* +* DESCRIPTION +* +* The routine ios_copy_vec copies a sparse vector specified by the +* parameter y to a sparse vector specified by the parameter x. */ + +void ios_copy_vec(IOSVEC *x, IOSVEC *y) +{ int j; + xassert(x != y); + xassert(x->n == y->n); + ios_clear_vec(x); + x->nnz = y->nnz; + memcpy(&x->ind[1], &y->ind[1], x->nnz * sizeof(int)); + memcpy(&x->val[1], &y->val[1], x->nnz * sizeof(double)); + for (j = 1; j <= x->nnz; j++) + x->pos[x->ind[j]] = j; + return; +} + +/*********************************************************************** +* NAME +* +* ios_linear_comb - compute linear combination (x := x + a * y) +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_linear_comb(IOSVEC *x, double a, IOSVEC *y); +* +* DESCRIPTION +* +* The routine ios_linear_comb computes the linear combination +* +* x := x + a * y, +* +* where x and y are sparse vectors, a is a scalar. */ + +void ios_linear_comb(IOSVEC *x, double a, IOSVEC *y) +{ int j, k; + double xj, yj; + xassert(x != y); + xassert(x->n == y->n); + for (k = 1; k <= y->nnz; k++) + { j = y->ind[k]; + xj = ios_get_vj(x, j); + yj = y->val[k]; + ios_set_vj(x, j, xj + a * yj); + } + return; +} + +/*********************************************************************** +* NAME +* +* ios_delete_vec - delete sparse vector +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_delete_vec(IOSVEC *v); +* +* DESCRIPTION +* +* The routine ios_delete_vec deletes a sparse vector specified by the +* parameter v freeing all the memory allocated to this object. */ + +void ios_delete_vec(IOSVEC *v) +{ /* delete sparse vector */ + xfree(v->pos); + xfree(v->ind); + xfree(v->val); + xfree(v); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios05.c b/resources/3rdparty/glpk-4.53/src/glpios05.c new file mode 100644 index 000000000..18ae0cbbb --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios05.c @@ -0,0 +1,282 @@ +/* glpios05.c (Gomory's mixed integer cut generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" + +/*********************************************************************** +* NAME +* +* ios_gmi_gen - generate Gomory's mixed integer cuts. +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_gmi_gen(glp_tree *tree, IOSPOOL *pool); +* +* DESCRIPTION +* +* The routine ios_gmi_gen generates Gomory's mixed integer cuts for +* the current point and adds them to the cut pool. */ + +#define MAXCUTS 50 +/* maximal number of cuts to be generated for one round */ + +struct worka +{ /* Gomory's cut generator working area */ + int *ind; /* int ind[1+n]; */ + double *val; /* double val[1+n]; */ + double *phi; /* double phi[1+m+n]; */ +}; + +#define f(x) ((x) - floor(x)) +/* compute fractional part of x */ + +static void gen_cut(glp_tree *tree, struct worka *worka, int j) +{ /* this routine tries to generate Gomory's mixed integer cut for + specified structural variable x[m+j] of integer kind, which is + basic and has fractional value in optimal solution to current + LP relaxation */ + glp_prob *mip = tree->mip; + int m = mip->m; + int n = mip->n; + int *ind = worka->ind; + double *val = worka->val; + double *phi = worka->phi; + int i, k, len, kind, stat; + double lb, ub, alfa, beta, ksi, phi1, rhs; + /* compute row of the simplex tableau, which (row) corresponds + to specified basic variable xB[i] = x[m+j]; see (23) */ + len = glp_eval_tab_row(mip, m+j, ind, val); + /* determine beta[i], which a value of xB[i] in optimal solution + to current LP relaxation; note that this value is the same as + if it would be computed with formula (27); it is assumed that + beta[i] is fractional enough */ + beta = mip->col[j]->prim; + /* compute cut coefficients phi and right-hand side rho, which + correspond to formula (30); dense format is used, because rows + of the simplex tableau is usually dense */ + for (k = 1; k <= m+n; k++) phi[k] = 0.0; + rhs = f(beta); /* initial value of rho; see (28), (32) */ + for (j = 1; j <= len; j++) + { /* determine original number of non-basic variable xN[j] */ + k = ind[j]; + xassert(1 <= k && k <= m+n); + /* determine the kind, bounds and current status of xN[j] in + optimal solution to LP relaxation */ + if (k <= m) + { /* auxiliary variable */ + GLPROW *row = mip->row[k]; + kind = GLP_CV; + lb = row->lb; + ub = row->ub; + stat = row->stat; + } + else + { /* structural variable */ + GLPCOL *col = mip->col[k-m]; + kind = col->kind; + lb = col->lb; + ub = col->ub; + stat = col->stat; + } + /* xN[j] cannot be basic */ + xassert(stat != GLP_BS); + /* determine row coefficient ksi[i,j] at xN[j]; see (23) */ + ksi = val[j]; + /* if ksi[i,j] is too large in the magnitude, do not generate + the cut */ + if (fabs(ksi) > 1e+05) goto fini; + /* if ksi[i,j] is too small in the magnitude, skip it */ + if (fabs(ksi) < 1e-10) goto skip; + /* compute row coefficient alfa[i,j] at y[j]; see (26) */ + switch (stat) + { case GLP_NF: + /* xN[j] is free (unbounded) having non-zero ksi[i,j]; + do not generate the cut */ + goto fini; + case GLP_NL: + /* xN[j] has active lower bound */ + alfa = - ksi; + break; + case GLP_NU: + /* xN[j] has active upper bound */ + alfa = + ksi; + break; + case GLP_NS: + /* xN[j] is fixed; skip it */ + goto skip; + default: + xassert(stat != stat); + } + /* compute cut coefficient phi'[j] at y[j]; see (21), (28) */ + switch (kind) + { case GLP_IV: + /* y[j] is integer */ + if (fabs(alfa - floor(alfa + 0.5)) < 1e-10) + { /* alfa[i,j] is close to nearest integer; skip it */ + goto skip; + } + else if (f(alfa) <= f(beta)) + phi1 = f(alfa); + else + phi1 = (f(beta) / (1.0 - f(beta))) * (1.0 - f(alfa)); + break; + case GLP_CV: + /* y[j] is continuous */ + if (alfa >= 0.0) + phi1 = + alfa; + else + phi1 = (f(beta) / (1.0 - f(beta))) * (- alfa); + break; + default: + xassert(kind != kind); + } + /* compute cut coefficient phi[j] at xN[j] and update right- + hand side rho; see (31), (32) */ + switch (stat) + { case GLP_NL: + /* xN[j] has active lower bound */ + phi[k] = + phi1; + rhs += phi1 * lb; + break; + case GLP_NU: + /* xN[j] has active upper bound */ + phi[k] = - phi1; + rhs -= phi1 * ub; + break; + default: + xassert(stat != stat); + } +skip: ; + } + /* now the cut has the form sum_k phi[k] * x[k] >= rho, where cut + coefficients are stored in the array phi in dense format; + x[1,...,m] are auxiliary variables, x[m+1,...,m+n] are struc- + tural variables; see (30) */ + /* eliminate auxiliary variables in order to express the cut only + through structural variables; see (33) */ + for (i = 1; i <= m; i++) + { GLPROW *row; + GLPAIJ *aij; + if (fabs(phi[i]) < 1e-10) continue; + /* auxiliary variable x[i] has non-zero cut coefficient */ + row = mip->row[i]; + /* x[i] cannot be fixed */ + xassert(row->type != GLP_FX); + /* substitute x[i] = sum_j a[i,j] * x[m+j] */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + phi[m+aij->col->j] += phi[i] * aij->val; + } + /* convert the final cut to sparse format and substitute fixed + (structural) variables */ + len = 0; + for (j = 1; j <= n; j++) + { GLPCOL *col; + if (fabs(phi[m+j]) < 1e-10) continue; + /* structural variable x[m+j] has non-zero cut coefficient */ + col = mip->col[j]; + if (col->type == GLP_FX) + { /* eliminate x[m+j] */ + rhs -= phi[m+j] * col->lb; + } + else + { len++; + ind[len] = j; + val[len] = phi[m+j]; + } + } + if (fabs(rhs) < 1e-12) rhs = 0.0; + /* if the cut inequality seems to be badly scaled, reject it to + avoid numeric difficulties */ + for (k = 1; k <= len; k++) + { if (fabs(val[k]) < 1e-03) goto fini; + if (fabs(val[k]) > 1e+03) goto fini; + } + /* add the cut to the cut pool for further consideration */ +#if 0 + ios_add_cut_row(tree, pool, GLP_RF_GMI, len, ind, val, GLP_LO, + rhs); +#else + glp_ios_add_row(tree, NULL, GLP_RF_GMI, 0, len, ind, val, GLP_LO, + rhs); +#endif +fini: return; +} + +struct var { int j; double f; }; + +static int fcmp(const void *p1, const void *p2) +{ const struct var *v1 = p1, *v2 = p2; + if (v1->f > v2->f) return -1; + if (v1->f < v2->f) return +1; + return 0; +} + +void ios_gmi_gen(glp_tree *tree) +{ /* main routine to generate Gomory's cuts */ + glp_prob *mip = tree->mip; + int m = mip->m; + int n = mip->n; + struct var *var; + int k, nv, j, size; + struct worka _worka, *worka = &_worka; + /* allocate working arrays */ + var = xcalloc(1+n, sizeof(struct var)); + worka->ind = xcalloc(1+n, sizeof(int)); + worka->val = xcalloc(1+n, sizeof(double)); + worka->phi = xcalloc(1+m+n, sizeof(double)); + /* build the list of integer structural variables, which are + basic and have fractional value in optimal solution to current + LP relaxation */ + nv = 0; + for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + double frac; + if (col->kind != GLP_IV) continue; + if (col->type == GLP_FX) continue; + if (col->stat != GLP_BS) continue; + frac = f(col->prim); + if (!(0.05 <= frac && frac <= 0.95)) continue; + /* add variable to the list */ + nv++, var[nv].j = j, var[nv].f = frac; + } + /* order the list by descending fractionality */ + qsort(&var[1], nv, sizeof(struct var), fcmp); + /* try to generate cuts by one for each variable in the list, but + not more than MAXCUTS cuts */ + size = glp_ios_pool_size(tree); + for (k = 1; k <= nv; k++) + { if (glp_ios_pool_size(tree) - size >= MAXCUTS) break; + gen_cut(tree, worka, var[k].j); + } + /* free working arrays */ + xfree(var); + xfree(worka->ind); + xfree(worka->val); + xfree(worka->phi); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios06.c b/resources/3rdparty/glpk-4.53/src/glpios06.c new file mode 100644 index 000000000..53f8dcfc7 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios06.c @@ -0,0 +1,1448 @@ +/* glpios06.c (MIR cut generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" + +#define _MIR_DEBUG 0 + +#define MAXAGGR 5 +/* maximal number of rows which can be aggregated */ + +struct MIR +{ /* MIR cut generator working area */ + /*--------------------------------------------------------------*/ + /* global information valid for the root subproblem */ + int m; + /* number of rows (in the root subproblem) */ + int n; + /* number of columns */ + char *skip; /* char skip[1+m]; */ + /* skip[i], 1 <= i <= m, is a flag that means that row i should + not be used because (1) it is not suitable, or (2) because it + has been used in the aggregated constraint */ + char *isint; /* char isint[1+m+n]; */ + /* isint[k], 1 <= k <= m+n, is a flag that means that variable + x[k] is integer (otherwise, continuous) */ + double *lb; /* double lb[1+m+n]; */ + /* lb[k], 1 <= k <= m+n, is lower bound of x[k]; -DBL_MAX means + that x[k] has no lower bound */ + int *vlb; /* int vlb[1+m+n]; */ + /* vlb[k] = k', 1 <= k <= m+n, is the number of integer variable, + which defines variable lower bound x[k] >= lb[k] * x[k']; zero + means that x[k] has simple lower bound */ + double *ub; /* double ub[1+m+n]; */ + /* ub[k], 1 <= k <= m+n, is upper bound of x[k]; +DBL_MAX means + that x[k] has no upper bound */ + int *vub; /* int vub[1+m+n]; */ + /* vub[k] = k', 1 <= k <= m+n, is the number of integer variable, + which defines variable upper bound x[k] <= ub[k] * x[k']; zero + means that x[k] has simple upper bound */ + /*--------------------------------------------------------------*/ + /* current (fractional) point to be separated */ + double *x; /* double x[1+m+n]; */ + /* x[k] is current value of auxiliary (1 <= k <= m) or structural + (m+1 <= k <= m+n) variable */ + /*--------------------------------------------------------------*/ + /* aggregated constraint sum a[k] * x[k] = b, which is a linear + combination of original constraints transformed to equalities + by introducing auxiliary variables */ + int agg_cnt; + /* number of rows (original constraints) used to build aggregated + constraint, 1 <= agg_cnt <= MAXAGGR */ + int *agg_row; /* int agg_row[1+MAXAGGR]; */ + /* agg_row[k], 1 <= k <= agg_cnt, is the row number used to build + aggregated constraint */ + IOSVEC *agg_vec; /* IOSVEC agg_vec[1:m+n]; */ + /* sparse vector of aggregated constraint coefficients, a[k] */ + double agg_rhs; + /* right-hand side of the aggregated constraint, b */ + /*--------------------------------------------------------------*/ + /* bound substitution flags for modified constraint */ + char *subst; /* char subst[1+m+n]; */ + /* subst[k], 1 <= k <= m+n, is a bound substitution flag used for + variable x[k]: + '?' - x[k] is missing in modified constraint + 'L' - x[k] = (lower bound) + x'[k] + 'U' - x[k] = (upper bound) - x'[k] */ + /*--------------------------------------------------------------*/ + /* modified constraint sum a'[k] * x'[k] = b', where x'[k] >= 0, + derived from aggregated constraint by substituting bounds; + note that due to substitution of variable bounds there may be + additional terms in the modified constraint */ + IOSVEC *mod_vec; /* IOSVEC mod_vec[1:m+n]; */ + /* sparse vector of modified constraint coefficients, a'[k] */ + double mod_rhs; + /* right-hand side of the modified constraint, b' */ + /*--------------------------------------------------------------*/ + /* cutting plane sum alpha[k] * x[k] <= beta */ + IOSVEC *cut_vec; /* IOSVEC cut_vec[1:m+n]; */ + /* sparse vector of cutting plane coefficients, alpha[k] */ + double cut_rhs; + /* right-hand size of the cutting plane, beta */ +}; + +/*********************************************************************** +* NAME +* +* ios_mir_init - initialize MIR cut generator +* +* SYNOPSIS +* +* #include "glpios.h" +* void *ios_mir_init(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_mir_init initializes the MIR cut generator assuming +* that the current subproblem is the root subproblem. +* +* RETURNS +* +* The routine ios_mir_init returns a pointer to the MIR cut generator +* working area. */ + +static void set_row_attrib(glp_tree *tree, struct MIR *mir) +{ /* set global row attributes */ + glp_prob *mip = tree->mip; + int m = mir->m; + int k; + for (k = 1; k <= m; k++) + { GLPROW *row = mip->row[k]; + mir->skip[k] = 0; + mir->isint[k] = 0; + switch (row->type) + { case GLP_FR: + mir->lb[k] = -DBL_MAX, mir->ub[k] = +DBL_MAX; break; + case GLP_LO: + mir->lb[k] = row->lb, mir->ub[k] = +DBL_MAX; break; + case GLP_UP: + mir->lb[k] = -DBL_MAX, mir->ub[k] = row->ub; break; + case GLP_DB: + mir->lb[k] = row->lb, mir->ub[k] = row->ub; break; + case GLP_FX: + mir->lb[k] = mir->ub[k] = row->lb; break; + default: + xassert(row != row); + } + mir->vlb[k] = mir->vub[k] = 0; + } + return; +} + +static void set_col_attrib(glp_tree *tree, struct MIR *mir) +{ /* set global column attributes */ + glp_prob *mip = tree->mip; + int m = mir->m; + int n = mir->n; + int k; + for (k = m+1; k <= m+n; k++) + { GLPCOL *col = mip->col[k-m]; + switch (col->kind) + { case GLP_CV: + mir->isint[k] = 0; break; + case GLP_IV: + mir->isint[k] = 1; break; + default: + xassert(col != col); + } + switch (col->type) + { case GLP_FR: + mir->lb[k] = -DBL_MAX, mir->ub[k] = +DBL_MAX; break; + case GLP_LO: + mir->lb[k] = col->lb, mir->ub[k] = +DBL_MAX; break; + case GLP_UP: + mir->lb[k] = -DBL_MAX, mir->ub[k] = col->ub; break; + case GLP_DB: + mir->lb[k] = col->lb, mir->ub[k] = col->ub; break; + case GLP_FX: + mir->lb[k] = mir->ub[k] = col->lb; break; + default: + xassert(col != col); + } + mir->vlb[k] = mir->vub[k] = 0; + } + return; +} + +static void set_var_bounds(glp_tree *tree, struct MIR *mir) +{ /* set variable bounds */ + glp_prob *mip = tree->mip; + int m = mir->m; + GLPAIJ *aij; + int i, k1, k2; + double a1, a2; + for (i = 1; i <= m; i++) + { /* we need the row to be '>= 0' or '<= 0' */ + if (!(mir->lb[i] == 0.0 && mir->ub[i] == +DBL_MAX || + mir->lb[i] == -DBL_MAX && mir->ub[i] == 0.0)) continue; + /* take first term */ + aij = mip->row[i]->ptr; + if (aij == NULL) continue; + k1 = m + aij->col->j, a1 = aij->val; + /* take second term */ + aij = aij->r_next; + if (aij == NULL) continue; + k2 = m + aij->col->j, a2 = aij->val; + /* there must be only two terms */ + if (aij->r_next != NULL) continue; + /* interchange terms, if needed */ + if (!mir->isint[k1] && mir->isint[k2]) + ; + else if (mir->isint[k1] && !mir->isint[k2]) + { k2 = k1, a2 = a1; + k1 = m + aij->col->j, a1 = aij->val; + } + else + { /* both terms are either continuous or integer */ + continue; + } + /* x[k2] should be double-bounded */ + if (mir->lb[k2] == -DBL_MAX || mir->ub[k2] == +DBL_MAX || + mir->lb[k2] == mir->ub[k2]) continue; + /* change signs, if necessary */ + if (mir->ub[i] == 0.0) a1 = - a1, a2 = - a2; + /* now the row has the form a1 * x1 + a2 * x2 >= 0, where x1 + is continuous, x2 is integer */ + if (a1 > 0.0) + { /* x1 >= - (a2 / a1) * x2 */ + if (mir->vlb[k1] == 0) + { /* set variable lower bound for x1 */ + mir->lb[k1] = - a2 / a1; + mir->vlb[k1] = k2; + /* the row should not be used */ + mir->skip[i] = 1; + } + } + else /* a1 < 0.0 */ + { /* x1 <= - (a2 / a1) * x2 */ + if (mir->vub[k1] == 0) + { /* set variable upper bound for x1 */ + mir->ub[k1] = - a2 / a1; + mir->vub[k1] = k2; + /* the row should not be used */ + mir->skip[i] = 1; + } + } + } + return; +} + +static void mark_useless_rows(glp_tree *tree, struct MIR *mir) +{ /* mark rows which should not be used */ + glp_prob *mip = tree->mip; + int m = mir->m; + GLPAIJ *aij; + int i, k, nv; + for (i = 1; i <= m; i++) + { /* free rows should not be used */ + if (mir->lb[i] == -DBL_MAX && mir->ub[i] == +DBL_MAX) + { mir->skip[i] = 1; + continue; + } + nv = 0; + for (aij = mip->row[i]->ptr; aij != NULL; aij = aij->r_next) + { k = m + aij->col->j; + /* rows with free variables should not be used */ + if (mir->lb[k] == -DBL_MAX && mir->ub[k] == +DBL_MAX) + { mir->skip[i] = 1; + break; + } + /* rows with integer variables having infinite (lower or + upper) bound should not be used */ + if (mir->isint[k] && mir->lb[k] == -DBL_MAX || + mir->isint[k] && mir->ub[k] == +DBL_MAX) + { mir->skip[i] = 1; + break; + } + /* count non-fixed variables */ + if (!(mir->vlb[k] == 0 && mir->vub[k] == 0 && + mir->lb[k] == mir->ub[k])) nv++; + } + /* rows with all variables fixed should not be used */ + if (nv == 0) + { mir->skip[i] = 1; + continue; + } + } + return; +} + +void *ios_mir_init(glp_tree *tree) +{ /* initialize MIR cut generator */ + glp_prob *mip = tree->mip; + int m = mip->m; + int n = mip->n; + struct MIR *mir; +#if _MIR_DEBUG + xprintf("ios_mir_init: warning: debug mode enabled\n"); +#endif + /* allocate working area */ + mir = xmalloc(sizeof(struct MIR)); + mir->m = m; + mir->n = n; + mir->skip = xcalloc(1+m, sizeof(char)); + mir->isint = xcalloc(1+m+n, sizeof(char)); + mir->lb = xcalloc(1+m+n, sizeof(double)); + mir->vlb = xcalloc(1+m+n, sizeof(int)); + mir->ub = xcalloc(1+m+n, sizeof(double)); + mir->vub = xcalloc(1+m+n, sizeof(int)); + mir->x = xcalloc(1+m+n, sizeof(double)); + mir->agg_row = xcalloc(1+MAXAGGR, sizeof(int)); + mir->agg_vec = ios_create_vec(m+n); + mir->subst = xcalloc(1+m+n, sizeof(char)); + mir->mod_vec = ios_create_vec(m+n); + mir->cut_vec = ios_create_vec(m+n); + /* set global row attributes */ + set_row_attrib(tree, mir); + /* set global column attributes */ + set_col_attrib(tree, mir); + /* set variable bounds */ + set_var_bounds(tree, mir); + /* mark rows which should not be used */ + mark_useless_rows(tree, mir); + return mir; +} + +/*********************************************************************** +* NAME +* +* ios_mir_gen - generate MIR cuts +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_mir_gen(glp_tree *tree, void *gen, IOSPOOL *pool); +* +* DESCRIPTION +* +* The routine ios_mir_gen generates MIR cuts for the current point and +* adds them to the cut pool. */ + +static void get_current_point(glp_tree *tree, struct MIR *mir) +{ /* obtain current point */ + glp_prob *mip = tree->mip; + int m = mir->m; + int n = mir->n; + int k; + for (k = 1; k <= m; k++) + mir->x[k] = mip->row[k]->prim; + for (k = m+1; k <= m+n; k++) + mir->x[k] = mip->col[k-m]->prim; + return; +} + +#if _MIR_DEBUG +static void check_current_point(struct MIR *mir) +{ /* check current point */ + int m = mir->m; + int n = mir->n; + int k, kk; + double lb, ub, eps; + for (k = 1; k <= m+n; k++) + { /* determine lower bound */ + lb = mir->lb[k]; + kk = mir->vlb[k]; + if (kk != 0) + { xassert(lb != -DBL_MAX); + xassert(!mir->isint[k]); + xassert(mir->isint[kk]); + lb *= mir->x[kk]; + } + /* check lower bound */ + if (lb != -DBL_MAX) + { eps = 1e-6 * (1.0 + fabs(lb)); + xassert(mir->x[k] >= lb - eps); + } + /* determine upper bound */ + ub = mir->ub[k]; + kk = mir->vub[k]; + if (kk != 0) + { xassert(ub != +DBL_MAX); + xassert(!mir->isint[k]); + xassert(mir->isint[kk]); + ub *= mir->x[kk]; + } + /* check upper bound */ + if (ub != +DBL_MAX) + { eps = 1e-6 * (1.0 + fabs(ub)); + xassert(mir->x[k] <= ub + eps); + } + } + return; +} +#endif + +static void initial_agg_row(glp_tree *tree, struct MIR *mir, int i) +{ /* use original i-th row as initial aggregated constraint */ + glp_prob *mip = tree->mip; + int m = mir->m; + GLPAIJ *aij; + xassert(1 <= i && i <= m); + xassert(!mir->skip[i]); + /* mark i-th row in order not to use it in the same aggregated + constraint */ + mir->skip[i] = 2; + mir->agg_cnt = 1; + mir->agg_row[1] = i; + /* use x[i] - sum a[i,j] * x[m+j] = 0, where x[i] is auxiliary + variable of row i, x[m+j] are structural variables */ + ios_clear_vec(mir->agg_vec); + ios_set_vj(mir->agg_vec, i, 1.0); + for (aij = mip->row[i]->ptr; aij != NULL; aij = aij->r_next) + ios_set_vj(mir->agg_vec, m + aij->col->j, - aij->val); + mir->agg_rhs = 0.0; +#if _MIR_DEBUG + ios_check_vec(mir->agg_vec); +#endif + return; +} + +#if _MIR_DEBUG +static void check_agg_row(struct MIR *mir) +{ /* check aggregated constraint */ + int m = mir->m; + int n = mir->n; + int j, k; + double r, big; + /* compute the residual r = sum a[k] * x[k] - b and determine + big = max(1, |a[k]|, |b|) */ + r = 0.0, big = 1.0; + for (j = 1; j <= mir->agg_vec->nnz; j++) + { k = mir->agg_vec->ind[j]; + xassert(1 <= k && k <= m+n); + r += mir->agg_vec->val[j] * mir->x[k]; + if (big < fabs(mir->agg_vec->val[j])) + big = fabs(mir->agg_vec->val[j]); + } + r -= mir->agg_rhs; + if (big < fabs(mir->agg_rhs)) + big = fabs(mir->agg_rhs); + /* the residual must be close to zero */ + xassert(fabs(r) <= 1e-6 * big); + return; +} +#endif + +static void subst_fixed_vars(struct MIR *mir) +{ /* substitute fixed variables into aggregated constraint */ + int m = mir->m; + int n = mir->n; + int j, k; + for (j = 1; j <= mir->agg_vec->nnz; j++) + { k = mir->agg_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->vlb[k] == 0 && mir->vub[k] == 0 && + mir->lb[k] == mir->ub[k]) + { /* x[k] is fixed */ + mir->agg_rhs -= mir->agg_vec->val[j] * mir->lb[k]; + mir->agg_vec->val[j] = 0.0; + } + } + /* remove terms corresponding to fixed variables */ + ios_clean_vec(mir->agg_vec, DBL_EPSILON); +#if _MIR_DEBUG + ios_check_vec(mir->agg_vec); +#endif + return; +} + +static void bound_subst_heur(struct MIR *mir) +{ /* bound substitution heuristic */ + int m = mir->m; + int n = mir->n; + int j, k, kk; + double d1, d2; + for (j = 1; j <= mir->agg_vec->nnz; j++) + { k = mir->agg_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->isint[k]) continue; /* skip integer variable */ + /* compute distance from x[k] to its lower bound */ + kk = mir->vlb[k]; + if (kk == 0) + { if (mir->lb[k] == -DBL_MAX) + d1 = DBL_MAX; + else + d1 = mir->x[k] - mir->lb[k]; + } + else + { xassert(1 <= kk && kk <= m+n); + xassert(mir->isint[kk]); + xassert(mir->lb[k] != -DBL_MAX); + d1 = mir->x[k] - mir->lb[k] * mir->x[kk]; + } + /* compute distance from x[k] to its upper bound */ + kk = mir->vub[k]; + if (kk == 0) + { if (mir->vub[k] == +DBL_MAX) + d2 = DBL_MAX; + else + d2 = mir->ub[k] - mir->x[k]; + } + else + { xassert(1 <= kk && kk <= m+n); + xassert(mir->isint[kk]); + xassert(mir->ub[k] != +DBL_MAX); + d2 = mir->ub[k] * mir->x[kk] - mir->x[k]; + } + /* x[k] cannot be free */ + xassert(d1 != DBL_MAX || d2 != DBL_MAX); + /* choose the bound which is closer to x[k] */ + xassert(mir->subst[k] == '?'); + if (d1 <= d2) + mir->subst[k] = 'L'; + else + mir->subst[k] = 'U'; + } + return; +} + +static void build_mod_row(struct MIR *mir) +{ /* substitute bounds and build modified constraint */ + int m = mir->m; + int n = mir->n; + int j, jj, k, kk; + /* initially modified constraint is aggregated constraint */ + ios_copy_vec(mir->mod_vec, mir->agg_vec); + mir->mod_rhs = mir->agg_rhs; +#if _MIR_DEBUG + ios_check_vec(mir->mod_vec); +#endif + /* substitute bounds for continuous variables; note that due to + substitution of variable bounds additional terms may appear in + modified constraint */ + for (j = mir->mod_vec->nnz; j >= 1; j--) + { k = mir->mod_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->isint[k]) continue; /* skip integer variable */ + if (mir->subst[k] == 'L') + { /* x[k] = (lower bound) + x'[k] */ + xassert(mir->lb[k] != -DBL_MAX); + kk = mir->vlb[k]; + if (kk == 0) + { /* x[k] = lb[k] + x'[k] */ + mir->mod_rhs -= mir->mod_vec->val[j] * mir->lb[k]; + } + else + { /* x[k] = lb[k] * x[kk] + x'[k] */ + xassert(mir->isint[kk]); + jj = mir->mod_vec->pos[kk]; + if (jj == 0) + { ios_set_vj(mir->mod_vec, kk, 1.0); + jj = mir->mod_vec->pos[kk]; + mir->mod_vec->val[jj] = 0.0; + } + mir->mod_vec->val[jj] += + mir->mod_vec->val[j] * mir->lb[k]; + } + } + else if (mir->subst[k] == 'U') + { /* x[k] = (upper bound) - x'[k] */ + xassert(mir->ub[k] != +DBL_MAX); + kk = mir->vub[k]; + if (kk == 0) + { /* x[k] = ub[k] - x'[k] */ + mir->mod_rhs -= mir->mod_vec->val[j] * mir->ub[k]; + } + else + { /* x[k] = ub[k] * x[kk] - x'[k] */ + xassert(mir->isint[kk]); + jj = mir->mod_vec->pos[kk]; + if (jj == 0) + { ios_set_vj(mir->mod_vec, kk, 1.0); + jj = mir->mod_vec->pos[kk]; + mir->mod_vec->val[jj] = 0.0; + } + mir->mod_vec->val[jj] += + mir->mod_vec->val[j] * mir->ub[k]; + } + mir->mod_vec->val[j] = - mir->mod_vec->val[j]; + } + else + xassert(k != k); + } +#if _MIR_DEBUG + ios_check_vec(mir->mod_vec); +#endif + /* substitute bounds for integer variables */ + for (j = 1; j <= mir->mod_vec->nnz; j++) + { k = mir->mod_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (!mir->isint[k]) continue; /* skip continuous variable */ + xassert(mir->subst[k] == '?'); + xassert(mir->vlb[k] == 0 && mir->vub[k] == 0); + xassert(mir->lb[k] != -DBL_MAX && mir->ub[k] != +DBL_MAX); + if (fabs(mir->lb[k]) <= fabs(mir->ub[k])) + { /* x[k] = lb[k] + x'[k] */ + mir->subst[k] = 'L'; + mir->mod_rhs -= mir->mod_vec->val[j] * mir->lb[k]; + } + else + { /* x[k] = ub[k] - x'[k] */ + mir->subst[k] = 'U'; + mir->mod_rhs -= mir->mod_vec->val[j] * mir->ub[k]; + mir->mod_vec->val[j] = - mir->mod_vec->val[j]; + } + } +#if _MIR_DEBUG + ios_check_vec(mir->mod_vec); +#endif + return; +} + +#if _MIR_DEBUG +static void check_mod_row(struct MIR *mir) +{ /* check modified constraint */ + int m = mir->m; + int n = mir->n; + int j, k, kk; + double r, big, x; + /* compute the residual r = sum a'[k] * x'[k] - b' and determine + big = max(1, |a[k]|, |b|) */ + r = 0.0, big = 1.0; + for (j = 1; j <= mir->mod_vec->nnz; j++) + { k = mir->mod_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->subst[k] == 'L') + { /* x'[k] = x[k] - (lower bound) */ + xassert(mir->lb[k] != -DBL_MAX); + kk = mir->vlb[k]; + if (kk == 0) + x = mir->x[k] - mir->lb[k]; + else + x = mir->x[k] - mir->lb[k] * mir->x[kk]; + } + else if (mir->subst[k] == 'U') + { /* x'[k] = (upper bound) - x[k] */ + xassert(mir->ub[k] != +DBL_MAX); + kk = mir->vub[k]; + if (kk == 0) + x = mir->ub[k] - mir->x[k]; + else + x = mir->ub[k] * mir->x[kk] - mir->x[k]; + } + else + xassert(k != k); + r += mir->mod_vec->val[j] * x; + if (big < fabs(mir->mod_vec->val[j])) + big = fabs(mir->mod_vec->val[j]); + } + r -= mir->mod_rhs; + if (big < fabs(mir->mod_rhs)) + big = fabs(mir->mod_rhs); + /* the residual must be close to zero */ + xassert(fabs(r) <= 1e-6 * big); + return; +} +#endif + +/*********************************************************************** +* mir_ineq - construct MIR inequality +* +* Given the single constraint mixed integer set +* +* |N| +* X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s}, +* + + j in N +* +* this routine constructs the mixed integer rounding (MIR) inequality +* +* sum alpha[j] * x[j] <= beta + gamma * s, +* j in N +* +* which is valid for X. +* +* If the MIR inequality has been successfully constructed, the routine +* returns zero. Otherwise, if b is close to nearest integer, there may +* be numeric difficulties due to big coefficients; so in this case the +* routine returns non-zero. */ + +static int mir_ineq(const int n, const double a[], const double b, + double alpha[], double *beta, double *gamma) +{ int j; + double f, t; + if (fabs(b - floor(b + .5)) < 0.01) + return 1; + f = b - floor(b); + for (j = 1; j <= n; j++) + { t = (a[j] - floor(a[j])) - f; + if (t <= 0.0) + alpha[j] = floor(a[j]); + else + alpha[j] = floor(a[j]) + t / (1.0 - f); + } + *beta = floor(b); + *gamma = 1.0 / (1.0 - f); + return 0; +} + +/*********************************************************************** +* cmir_ineq - construct c-MIR inequality +* +* Given the mixed knapsack set +* +* MK |N| +* X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s, +* + + j in N +* +* x[j] <= u[j]}, +* +* a subset C of variables to be complemented, and a divisor delta > 0, +* this routine constructs the complemented MIR (c-MIR) inequality +* +* sum alpha[j] * x[j] <= beta + gamma * s, +* j in N +* MK +* which is valid for X . +* +* If the c-MIR inequality has been successfully constructed, the +* routine returns zero. Otherwise, if there is a risk of numerical +* difficulties due to big coefficients (see comments to the routine +* mir_ineq), the routine cmir_ineq returns non-zero. */ + +static int cmir_ineq(const int n, const double a[], const double b, + const double u[], const char cset[], const double delta, + double alpha[], double *beta, double *gamma) +{ int j; + double *aa, bb; + aa = alpha, bb = b; + for (j = 1; j <= n; j++) + { aa[j] = a[j] / delta; + if (cset[j]) + aa[j] = - aa[j], bb -= a[j] * u[j]; + } + bb /= delta; + if (mir_ineq(n, aa, bb, alpha, beta, gamma)) return 1; + for (j = 1; j <= n; j++) + { if (cset[j]) + alpha[j] = - alpha[j], *beta += alpha[j] * u[j]; + } + *gamma /= delta; + return 0; +} + +/*********************************************************************** +* cmir_sep - c-MIR separation heuristic +* +* Given the mixed knapsack set +* +* MK |N| +* X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s, +* + + j in N +* +* x[j] <= u[j]} +* +* * * +* and a fractional point (x , s ), this routine tries to construct +* c-MIR inequality +* +* sum alpha[j] * x[j] <= beta + gamma * s, +* j in N +* MK +* which is valid for X and has (desirably maximal) violation at the +* fractional point given. This is attained by choosing an appropriate +* set C of variables to be complemented and a divisor delta > 0, which +* together define corresponding c-MIR inequality. +* +* If a violated c-MIR inequality has been successfully constructed, +* the routine returns its violation: +* +* * * +* sum alpha[j] * x [j] - beta - gamma * s , +* j in N +* +* which is positive. In case of failure the routine returns zero. */ + +struct vset { int j; double v; }; + +static int cmir_cmp(const void *p1, const void *p2) +{ const struct vset *v1 = p1, *v2 = p2; + if (v1->v < v2->v) return -1; + if (v1->v > v2->v) return +1; + return 0; +} + +static double cmir_sep(const int n, const double a[], const double b, + const double u[], const double x[], const double s, + double alpha[], double *beta, double *gamma) +{ int fail, j, k, nv, v; + double delta, eps, d_try[1+3], r, r_best; + char *cset; + struct vset *vset; + /* allocate working arrays */ + cset = xcalloc(1+n, sizeof(char)); + vset = xcalloc(1+n, sizeof(struct vset)); + /* choose initial C */ + for (j = 1; j <= n; j++) + cset[j] = (char)(x[j] >= 0.5 * u[j]); + /* choose initial delta */ + r_best = delta = 0.0; + for (j = 1; j <= n; j++) + { xassert(a[j] != 0.0); + /* if x[j] is close to its bounds, skip it */ + eps = 1e-9 * (1.0 + fabs(u[j])); + if (x[j] < eps || x[j] > u[j] - eps) continue; + /* try delta = |a[j]| to construct c-MIR inequality */ + fail = cmir_ineq(n, a, b, u, cset, fabs(a[j]), alpha, beta, + gamma); + if (fail) continue; + /* compute violation */ + r = - (*beta) - (*gamma) * s; + for (k = 1; k <= n; k++) r += alpha[k] * x[k]; + if (r_best < r) r_best = r, delta = fabs(a[j]); + } + if (r_best < 0.001) r_best = 0.0; + if (r_best == 0.0) goto done; + xassert(delta > 0.0); + /* try to increase violation by dividing delta by 2, 4, and 8, + respectively */ + d_try[1] = delta / 2.0; + d_try[2] = delta / 4.0; + d_try[3] = delta / 8.0; + for (j = 1; j <= 3; j++) + { /* construct c-MIR inequality */ + fail = cmir_ineq(n, a, b, u, cset, d_try[j], alpha, beta, + gamma); + if (fail) continue; + /* compute violation */ + r = - (*beta) - (*gamma) * s; + for (k = 1; k <= n; k++) r += alpha[k] * x[k]; + if (r_best < r) r_best = r, delta = d_try[j]; + } + /* build subset of variables lying strictly between their bounds + and order it by nondecreasing values of |x[j] - u[j]/2| */ + nv = 0; + for (j = 1; j <= n; j++) + { /* if x[j] is close to its bounds, skip it */ + eps = 1e-9 * (1.0 + fabs(u[j])); + if (x[j] < eps || x[j] > u[j] - eps) continue; + /* add x[j] to the subset */ + nv++; + vset[nv].j = j; + vset[nv].v = fabs(x[j] - 0.5 * u[j]); + } + qsort(&vset[1], nv, sizeof(struct vset), cmir_cmp); + /* try to increase violation by successively complementing each + variable in the subset */ + for (v = 1; v <= nv; v++) + { j = vset[v].j; + /* replace x[j] by its complement or vice versa */ + cset[j] = (char)!cset[j]; + /* construct c-MIR inequality */ + fail = cmir_ineq(n, a, b, u, cset, delta, alpha, beta, gamma); + /* restore the variable */ + cset[j] = (char)!cset[j]; + /* do not replace the variable in case of failure */ + if (fail) continue; + /* compute violation */ + r = - (*beta) - (*gamma) * s; + for (k = 1; k <= n; k++) r += alpha[k] * x[k]; + if (r_best < r) r_best = r, cset[j] = (char)!cset[j]; + } + /* construct the best c-MIR inequality chosen */ + fail = cmir_ineq(n, a, b, u, cset, delta, alpha, beta, gamma); + xassert(!fail); +done: /* free working arrays */ + xfree(cset); + xfree(vset); + /* return to the calling routine */ + return r_best; +} + +static double generate(struct MIR *mir) +{ /* try to generate violated c-MIR cut for modified constraint */ + int m = mir->m; + int n = mir->n; + int j, k, kk, nint; + double s, *u, *x, *alpha, r_best = 0.0, b, beta, gamma; + ios_copy_vec(mir->cut_vec, mir->mod_vec); + mir->cut_rhs = mir->mod_rhs; + /* remove small terms, which can appear due to substitution of + variable bounds */ + ios_clean_vec(mir->cut_vec, DBL_EPSILON); +#if _MIR_DEBUG + ios_check_vec(mir->cut_vec); +#endif + /* remove positive continuous terms to obtain MK relaxation */ + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (!mir->isint[k] && mir->cut_vec->val[j] > 0.0) + mir->cut_vec->val[j] = 0.0; + } + ios_clean_vec(mir->cut_vec, 0.0); +#if _MIR_DEBUG + ios_check_vec(mir->cut_vec); +#endif + /* move integer terms to the beginning of the sparse vector and + determine the number of integer variables */ + nint = 0; + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->isint[k]) + { double temp; + nint++; + /* interchange elements [nint] and [j] */ + kk = mir->cut_vec->ind[nint]; + mir->cut_vec->pos[k] = nint; + mir->cut_vec->pos[kk] = j; + mir->cut_vec->ind[nint] = k; + mir->cut_vec->ind[j] = kk; + temp = mir->cut_vec->val[nint]; + mir->cut_vec->val[nint] = mir->cut_vec->val[j]; + mir->cut_vec->val[j] = temp; + } + } +#if _MIR_DEBUG + ios_check_vec(mir->cut_vec); +#endif + /* if there is no integer variable, nothing to generate */ + if (nint == 0) goto done; + /* allocate working arrays */ + u = xcalloc(1+nint, sizeof(double)); + x = xcalloc(1+nint, sizeof(double)); + alpha = xcalloc(1+nint, sizeof(double)); + /* determine u and x */ + for (j = 1; j <= nint; j++) + { k = mir->cut_vec->ind[j]; + xassert(m+1 <= k && k <= m+n); + xassert(mir->isint[k]); + u[j] = mir->ub[k] - mir->lb[k]; + xassert(u[j] >= 1.0); + if (mir->subst[k] == 'L') + x[j] = mir->x[k] - mir->lb[k]; + else if (mir->subst[k] == 'U') + x[j] = mir->ub[k] - mir->x[k]; + else + xassert(k != k); + xassert(x[j] >= -0.001); + if (x[j] < 0.0) x[j] = 0.0; + } + /* compute s = - sum of continuous terms */ + s = 0.0; + for (j = nint+1; j <= mir->cut_vec->nnz; j++) + { double x; + k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + /* must be continuous */ + xassert(!mir->isint[k]); + if (mir->subst[k] == 'L') + { xassert(mir->lb[k] != -DBL_MAX); + kk = mir->vlb[k]; + if (kk == 0) + x = mir->x[k] - mir->lb[k]; + else + x = mir->x[k] - mir->lb[k] * mir->x[kk]; + } + else if (mir->subst[k] == 'U') + { xassert(mir->ub[k] != +DBL_MAX); + kk = mir->vub[k]; + if (kk == 0) + x = mir->ub[k] - mir->x[k]; + else + x = mir->ub[k] * mir->x[kk] - mir->x[k]; + } + else + xassert(k != k); + xassert(x >= -0.001); + if (x < 0.0) x = 0.0; + s -= mir->cut_vec->val[j] * x; + } + xassert(s >= 0.0); + /* apply heuristic to obtain most violated c-MIR inequality */ + b = mir->cut_rhs; + r_best = cmir_sep(nint, mir->cut_vec->val, b, u, x, s, alpha, + &beta, &gamma); + if (r_best == 0.0) goto skip; + xassert(r_best > 0.0); + /* convert to raw cut */ + /* sum alpha[j] * x[j] <= beta + gamma * s */ + for (j = 1; j <= nint; j++) + mir->cut_vec->val[j] = alpha[j]; + for (j = nint+1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + if (k <= m+n) mir->cut_vec->val[j] *= gamma; + } + mir->cut_rhs = beta; +#if _MIR_DEBUG + ios_check_vec(mir->cut_vec); +#endif +skip: /* free working arrays */ + xfree(u); + xfree(x); + xfree(alpha); +done: return r_best; +} + +#if _MIR_DEBUG +static void check_raw_cut(struct MIR *mir, double r_best) +{ /* check raw cut before back bound substitution */ + int m = mir->m; + int n = mir->n; + int j, k, kk; + double r, big, x; + /* compute the residual r = sum a[k] * x[k] - b and determine + big = max(1, |a[k]|, |b|) */ + r = 0.0, big = 1.0; + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->subst[k] == 'L') + { xassert(mir->lb[k] != -DBL_MAX); + kk = mir->vlb[k]; + if (kk == 0) + x = mir->x[k] - mir->lb[k]; + else + x = mir->x[k] - mir->lb[k] * mir->x[kk]; + } + else if (mir->subst[k] == 'U') + { xassert(mir->ub[k] != +DBL_MAX); + kk = mir->vub[k]; + if (kk == 0) + x = mir->ub[k] - mir->x[k]; + else + x = mir->ub[k] * mir->x[kk] - mir->x[k]; + } + else + xassert(k != k); + r += mir->cut_vec->val[j] * x; + if (big < fabs(mir->cut_vec->val[j])) + big = fabs(mir->cut_vec->val[j]); + } + r -= mir->cut_rhs; + if (big < fabs(mir->cut_rhs)) + big = fabs(mir->cut_rhs); + /* the residual must be close to r_best */ + xassert(fabs(r - r_best) <= 1e-6 * big); + return; +} +#endif + +static void back_subst(struct MIR *mir) +{ /* back substitution of original bounds */ + int m = mir->m; + int n = mir->n; + int j, jj, k, kk; + /* at first, restore bounds of integer variables (because on + restoring variable bounds of continuous variables we need + original, not shifted, bounds of integer variables) */ + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (!mir->isint[k]) continue; /* skip continuous */ + if (mir->subst[k] == 'L') + { /* x'[k] = x[k] - lb[k] */ + xassert(mir->lb[k] != -DBL_MAX); + xassert(mir->vlb[k] == 0); + mir->cut_rhs += mir->cut_vec->val[j] * mir->lb[k]; + } + else if (mir->subst[k] == 'U') + { /* x'[k] = ub[k] - x[k] */ + xassert(mir->ub[k] != +DBL_MAX); + xassert(mir->vub[k] == 0); + mir->cut_rhs -= mir->cut_vec->val[j] * mir->ub[k]; + mir->cut_vec->val[j] = - mir->cut_vec->val[j]; + } + else + xassert(k != k); + } + /* now restore bounds of continuous variables */ + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->isint[k]) continue; /* skip integer */ + if (mir->subst[k] == 'L') + { /* x'[k] = x[k] - (lower bound) */ + xassert(mir->lb[k] != -DBL_MAX); + kk = mir->vlb[k]; + if (kk == 0) + { /* x'[k] = x[k] - lb[k] */ + mir->cut_rhs += mir->cut_vec->val[j] * mir->lb[k]; + } + else + { /* x'[k] = x[k] - lb[k] * x[kk] */ + jj = mir->cut_vec->pos[kk]; +#if 0 + xassert(jj != 0); +#else + if (jj == 0) + { ios_set_vj(mir->cut_vec, kk, 1.0); + jj = mir->cut_vec->pos[kk]; + xassert(jj != 0); + mir->cut_vec->val[jj] = 0.0; + } +#endif + mir->cut_vec->val[jj] -= mir->cut_vec->val[j] * + mir->lb[k]; + } + } + else if (mir->subst[k] == 'U') + { /* x'[k] = (upper bound) - x[k] */ + xassert(mir->ub[k] != +DBL_MAX); + kk = mir->vub[k]; + if (kk == 0) + { /* x'[k] = ub[k] - x[k] */ + mir->cut_rhs -= mir->cut_vec->val[j] * mir->ub[k]; + } + else + { /* x'[k] = ub[k] * x[kk] - x[k] */ + jj = mir->cut_vec->pos[kk]; + if (jj == 0) + { ios_set_vj(mir->cut_vec, kk, 1.0); + jj = mir->cut_vec->pos[kk]; + xassert(jj != 0); + mir->cut_vec->val[jj] = 0.0; + } + mir->cut_vec->val[jj] += mir->cut_vec->val[j] * + mir->ub[k]; + } + mir->cut_vec->val[j] = - mir->cut_vec->val[j]; + } + else + xassert(k != k); + } +#if _MIR_DEBUG + ios_check_vec(mir->cut_vec); +#endif + return; +} + +#if _MIR_DEBUG +static void check_cut_row(struct MIR *mir, double r_best) +{ /* check the cut after back bound substitution or elimination of + auxiliary variables */ + int m = mir->m; + int n = mir->n; + int j, k; + double r, big; + /* compute the residual r = sum a[k] * x[k] - b and determine + big = max(1, |a[k]|, |b|) */ + r = 0.0, big = 1.0; + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + r += mir->cut_vec->val[j] * mir->x[k]; + if (big < fabs(mir->cut_vec->val[j])) + big = fabs(mir->cut_vec->val[j]); + } + r -= mir->cut_rhs; + if (big < fabs(mir->cut_rhs)) + big = fabs(mir->cut_rhs); + /* the residual must be close to r_best */ + xassert(fabs(r - r_best) <= 1e-6 * big); + return; +} +#endif + +static void subst_aux_vars(glp_tree *tree, struct MIR *mir) +{ /* final substitution to eliminate auxiliary variables */ + glp_prob *mip = tree->mip; + int m = mir->m; + int n = mir->n; + GLPAIJ *aij; + int j, k, kk, jj; + for (j = mir->cut_vec->nnz; j >= 1; j--) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (k > m) continue; /* skip structurals */ + for (aij = mip->row[k]->ptr; aij != NULL; aij = aij->r_next) + { kk = m + aij->col->j; /* structural */ + jj = mir->cut_vec->pos[kk]; + if (jj == 0) + { ios_set_vj(mir->cut_vec, kk, 1.0); + jj = mir->cut_vec->pos[kk]; + mir->cut_vec->val[jj] = 0.0; + } + mir->cut_vec->val[jj] += mir->cut_vec->val[j] * aij->val; + } + mir->cut_vec->val[j] = 0.0; + } + ios_clean_vec(mir->cut_vec, 0.0); + return; +} + +static void add_cut(glp_tree *tree, struct MIR *mir) +{ /* add constructed cut inequality to the cut pool */ + int m = mir->m; + int n = mir->n; + int j, k, len; + int *ind = xcalloc(1+n, sizeof(int)); + double *val = xcalloc(1+n, sizeof(double)); + len = 0; + for (j = mir->cut_vec->nnz; j >= 1; j--) + { k = mir->cut_vec->ind[j]; + xassert(m+1 <= k && k <= m+n); + len++, ind[len] = k - m, val[len] = mir->cut_vec->val[j]; + } +#if 0 + ios_add_cut_row(tree, pool, GLP_RF_MIR, len, ind, val, GLP_UP, + mir->cut_rhs); +#else + glp_ios_add_row(tree, NULL, GLP_RF_MIR, 0, len, ind, val, GLP_UP, + mir->cut_rhs); +#endif + xfree(ind); + xfree(val); + return; +} + +static int aggregate_row(glp_tree *tree, struct MIR *mir) +{ /* try to aggregate another row */ + glp_prob *mip = tree->mip; + int m = mir->m; + int n = mir->n; + GLPAIJ *aij; + IOSVEC *v; + int ii, j, jj, k, kk, kappa = 0, ret = 0; + double d1, d2, d, d_max = 0.0; + /* choose appropriate structural variable in the aggregated row + to be substituted */ + for (j = 1; j <= mir->agg_vec->nnz; j++) + { k = mir->agg_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (k <= m) continue; /* skip auxiliary var */ + if (mir->isint[k]) continue; /* skip integer var */ + if (fabs(mir->agg_vec->val[j]) < 0.001) continue; + /* compute distance from x[k] to its lower bound */ + kk = mir->vlb[k]; + if (kk == 0) + { if (mir->lb[k] == -DBL_MAX) + d1 = DBL_MAX; + else + d1 = mir->x[k] - mir->lb[k]; + } + else + { xassert(1 <= kk && kk <= m+n); + xassert(mir->isint[kk]); + xassert(mir->lb[k] != -DBL_MAX); + d1 = mir->x[k] - mir->lb[k] * mir->x[kk]; + } + /* compute distance from x[k] to its upper bound */ + kk = mir->vub[k]; + if (kk == 0) + { if (mir->vub[k] == +DBL_MAX) + d2 = DBL_MAX; + else + d2 = mir->ub[k] - mir->x[k]; + } + else + { xassert(1 <= kk && kk <= m+n); + xassert(mir->isint[kk]); + xassert(mir->ub[k] != +DBL_MAX); + d2 = mir->ub[k] * mir->x[kk] - mir->x[k]; + } + /* x[k] cannot be free */ + xassert(d1 != DBL_MAX || d2 != DBL_MAX); + /* d = min(d1, d2) */ + d = (d1 <= d2 ? d1 : d2); + xassert(d != DBL_MAX); + /* should not be close to corresponding bound */ + if (d < 0.001) continue; + if (d_max < d) d_max = d, kappa = k; + } + if (kappa == 0) + { /* nothing chosen */ + ret = 1; + goto done; + } + /* x[kappa] has been chosen */ + xassert(m+1 <= kappa && kappa <= m+n); + xassert(!mir->isint[kappa]); + /* find another row, which have not been used yet, to eliminate + x[kappa] from the aggregated row */ + for (ii = 1; ii <= m; ii++) + { if (mir->skip[ii]) continue; + for (aij = mip->row[ii]->ptr; aij != NULL; aij = aij->r_next) + if (aij->col->j == kappa - m) break; + if (aij != NULL && fabs(aij->val) >= 0.001) break; + } + if (ii > m) + { /* nothing found */ + ret = 2; + goto done; + } + /* row ii has been found; include it in the aggregated list */ + mir->agg_cnt++; + xassert(mir->agg_cnt <= MAXAGGR); + mir->agg_row[mir->agg_cnt] = ii; + mir->skip[ii] = 2; + /* v := new row */ + v = ios_create_vec(m+n); + ios_set_vj(v, ii, 1.0); + for (aij = mip->row[ii]->ptr; aij != NULL; aij = aij->r_next) + ios_set_vj(v, m + aij->col->j, - aij->val); +#if _MIR_DEBUG + ios_check_vec(v); +#endif + /* perform gaussian elimination to remove x[kappa] */ + j = mir->agg_vec->pos[kappa]; + xassert(j != 0); + jj = v->pos[kappa]; + xassert(jj != 0); + ios_linear_comb(mir->agg_vec, + - mir->agg_vec->val[j] / v->val[jj], v); + ios_delete_vec(v); + ios_set_vj(mir->agg_vec, kappa, 0.0); +#if _MIR_DEBUG + ios_check_vec(mir->agg_vec); +#endif +done: return ret; +} + +void ios_mir_gen(glp_tree *tree, void *gen) +{ /* main routine to generate MIR cuts */ + glp_prob *mip = tree->mip; + struct MIR *mir = gen; + int m = mir->m; + int n = mir->n; + int i; + double r_best; + xassert(mip->m >= m); + xassert(mip->n == n); + /* obtain current point */ + get_current_point(tree, mir); +#if _MIR_DEBUG + /* check current point */ + check_current_point(mir); +#endif + /* reset bound substitution flags */ + memset(&mir->subst[1], '?', m+n); + /* try to generate a set of violated MIR cuts */ + for (i = 1; i <= m; i++) + { if (mir->skip[i]) continue; + /* use original i-th row as initial aggregated constraint */ + initial_agg_row(tree, mir, i); +loop: ; +#if _MIR_DEBUG + /* check aggregated row */ + check_agg_row(mir); +#endif + /* substitute fixed variables into aggregated constraint */ + subst_fixed_vars(mir); +#if _MIR_DEBUG + /* check aggregated row */ + check_agg_row(mir); +#endif +#if _MIR_DEBUG + /* check bound substitution flags */ + { int k; + for (k = 1; k <= m+n; k++) + xassert(mir->subst[k] == '?'); + } +#endif + /* apply bound substitution heuristic */ + bound_subst_heur(mir); + /* substitute bounds and build modified constraint */ + build_mod_row(mir); +#if _MIR_DEBUG + /* check modified row */ + check_mod_row(mir); +#endif + /* try to generate violated c-MIR cut for modified row */ + r_best = generate(mir); + if (r_best > 0.0) + { /* success */ +#if _MIR_DEBUG + /* check raw cut before back bound substitution */ + check_raw_cut(mir, r_best); +#endif + /* back substitution of original bounds */ + back_subst(mir); +#if _MIR_DEBUG + /* check the cut after back bound substitution */ + check_cut_row(mir, r_best); +#endif + /* final substitution to eliminate auxiliary variables */ + subst_aux_vars(tree, mir); +#if _MIR_DEBUG + /* check the cut after elimination of auxiliaries */ + check_cut_row(mir, r_best); +#endif + /* add constructed cut inequality to the cut pool */ + add_cut(tree, mir); + } + /* reset bound substitution flags */ + { int j, k; + for (j = 1; j <= mir->mod_vec->nnz; j++) + { k = mir->mod_vec->ind[j]; + xassert(1 <= k && k <= m+n); + xassert(mir->subst[k] != '?'); + mir->subst[k] = '?'; + } + } + if (r_best == 0.0) + { /* failure */ + if (mir->agg_cnt < MAXAGGR) + { /* try to aggregate another row */ + if (aggregate_row(tree, mir) == 0) goto loop; + } + } + /* unmark rows used in the aggregated constraint */ + { int k, ii; + for (k = 1; k <= mir->agg_cnt; k++) + { ii = mir->agg_row[k]; + xassert(1 <= ii && ii <= m); + xassert(mir->skip[ii] == 2); + mir->skip[ii] = 0; + } + } + } + return; +} + +/*********************************************************************** +* NAME +* +* ios_mir_term - terminate MIR cut generator +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_mir_term(void *gen); +* +* DESCRIPTION +* +* The routine ios_mir_term deletes the MIR cut generator working area +* freeing all the memory allocated to it. */ + +void ios_mir_term(void *gen) +{ struct MIR *mir = gen; + xfree(mir->skip); + xfree(mir->isint); + xfree(mir->lb); + xfree(mir->vlb); + xfree(mir->ub); + xfree(mir->vub); + xfree(mir->x); + xfree(mir->agg_row); + ios_delete_vec(mir->agg_vec); + xfree(mir->subst); + ios_delete_vec(mir->mod_vec); + ios_delete_vec(mir->cut_vec); + xfree(mir); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios07.c b/resources/3rdparty/glpk-4.53/src/glpios07.c new file mode 100644 index 000000000..3ea515b67 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios07.c @@ -0,0 +1,551 @@ +/* glpios07.c (mixed cover cut generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" + +/*---------------------------------------------------------------------- +-- COVER INEQUALITIES +-- +-- Consider the set of feasible solutions to 0-1 knapsack problem: +-- +-- sum a[j]*x[j] <= b, (1) +-- j in J +-- +-- x[j] is binary, (2) +-- +-- where, wlog, we assume that a[j] > 0 (since 0-1 variables can be +-- complemented) and a[j] <= b (since a[j] > b implies x[j] = 0). +-- +-- A set C within J is called a cover if +-- +-- sum a[j] > b. (3) +-- j in C +-- +-- For any cover C the inequality +-- +-- sum x[j] <= |C| - 1 (4) +-- j in C +-- +-- is called a cover inequality and is valid for (1)-(2). +-- +-- MIXED COVER INEQUALITIES +-- +-- Consider the set of feasible solutions to mixed knapsack problem: +-- +-- sum a[j]*x[j] + y <= b, (5) +-- j in J +-- +-- x[j] is binary, (6) +-- +-- 0 <= y <= u is continuous, (7) +-- +-- where again we assume that a[j] > 0. +-- +-- Let C within J be some set. From (1)-(4) it follows that +-- +-- sum a[j] > b - y (8) +-- j in C +-- +-- implies +-- +-- sum x[j] <= |C| - 1. (9) +-- j in C +-- +-- Thus, we need to modify the inequality (9) in such a way that it be +-- a constraint only if the condition (8) is satisfied. +-- +-- Consider the following inequality: +-- +-- sum x[j] <= |C| - t. (10) +-- j in C +-- +-- If 0 < t <= 1, then (10) is equivalent to (9), because all x[j] are +-- binary variables. On the other hand, if t <= 0, (10) being satisfied +-- for any values of x[j] is not a constraint. +-- +-- Let +-- +-- t' = sum a[j] + y - b. (11) +-- j in C +-- +-- It is understood that the condition t' > 0 is equivalent to (8). +-- Besides, from (6)-(7) it follows that t' has an implied upper bound: +-- +-- t'max = sum a[j] + u - b. (12) +-- j in C +-- +-- This allows to express the parameter t having desired properties: +-- +-- t = t' / t'max. (13) +-- +-- In fact, t <= 1 by definition, and t > 0 being equivalent to t' > 0 +-- is equivalent to (8). +-- +-- Thus, the inequality (10), where t is given by formula (13) is valid +-- for (5)-(7). +-- +-- Note that if u = 0, then y = 0, so t = 1, and the conditions (8) and +-- (10) is transformed to the conditions (3) and (4). +-- +-- GENERATING MIXED COVER CUTS +-- +-- To generate a mixed cover cut in the form (10) we need to find such +-- set C which satisfies to the inequality (8) and for which, in turn, +-- the inequality (10) is violated in the current point. +-- +-- Substituting t from (13) to (10) gives: +-- +-- 1 +-- sum x[j] <= |C| - ----- (sum a[j] + y - b), (14) +-- j in C t'max j in C +-- +-- and finally we have the cut inequality in the standard form: +-- +-- sum x[j] + alfa * y <= beta, (15) +-- j in C +-- +-- where: +-- +-- alfa = 1 / t'max, (16) +-- +-- beta = |C| - alfa * (sum a[j] - b). (17) +-- j in C */ + +#if 1 +#define MAXTRY 1000 +#else +#define MAXTRY 10000 +#endif + +static int cover2(int n, double a[], double b, double u, double x[], + double y, int cov[], double *_alfa, double *_beta) +{ /* try to generate mixed cover cut using two-element cover */ + int i, j, try = 0, ret = 0; + double eps, alfa, beta, temp, rmax = 0.001; + eps = 0.001 * (1.0 + fabs(b)); + for (i = 0+1; i <= n; i++) + for (j = i+1; j <= n; j++) + { /* C = {i, j} */ + try++; + if (try > MAXTRY) goto done; + /* check if condition (8) is satisfied */ + if (a[i] + a[j] + y > b + eps) + { /* compute parameters for inequality (15) */ + temp = a[i] + a[j] - b; + alfa = 1.0 / (temp + u); + beta = 2.0 - alfa * temp; + /* compute violation of inequality (15) */ + temp = x[i] + x[j] + alfa * y - beta; + /* choose C providing maximum violation */ + if (rmax < temp) + { rmax = temp; + cov[1] = i; + cov[2] = j; + *_alfa = alfa; + *_beta = beta; + ret = 1; + } + } + } +done: return ret; +} + +static int cover3(int n, double a[], double b, double u, double x[], + double y, int cov[], double *_alfa, double *_beta) +{ /* try to generate mixed cover cut using three-element cover */ + int i, j, k, try = 0, ret = 0; + double eps, alfa, beta, temp, rmax = 0.001; + eps = 0.001 * (1.0 + fabs(b)); + for (i = 0+1; i <= n; i++) + for (j = i+1; j <= n; j++) + for (k = j+1; k <= n; k++) + { /* C = {i, j, k} */ + try++; + if (try > MAXTRY) goto done; + /* check if condition (8) is satisfied */ + if (a[i] + a[j] + a[k] + y > b + eps) + { /* compute parameters for inequality (15) */ + temp = a[i] + a[j] + a[k] - b; + alfa = 1.0 / (temp + u); + beta = 3.0 - alfa * temp; + /* compute violation of inequality (15) */ + temp = x[i] + x[j] + x[k] + alfa * y - beta; + /* choose C providing maximum violation */ + if (rmax < temp) + { rmax = temp; + cov[1] = i; + cov[2] = j; + cov[3] = k; + *_alfa = alfa; + *_beta = beta; + ret = 1; + } + } + } +done: return ret; +} + +static int cover4(int n, double a[], double b, double u, double x[], + double y, int cov[], double *_alfa, double *_beta) +{ /* try to generate mixed cover cut using four-element cover */ + int i, j, k, l, try = 0, ret = 0; + double eps, alfa, beta, temp, rmax = 0.001; + eps = 0.001 * (1.0 + fabs(b)); + for (i = 0+1; i <= n; i++) + for (j = i+1; j <= n; j++) + for (k = j+1; k <= n; k++) + for (l = k+1; l <= n; l++) + { /* C = {i, j, k, l} */ + try++; + if (try > MAXTRY) goto done; + /* check if condition (8) is satisfied */ + if (a[i] + a[j] + a[k] + a[l] + y > b + eps) + { /* compute parameters for inequality (15) */ + temp = a[i] + a[j] + a[k] + a[l] - b; + alfa = 1.0 / (temp + u); + beta = 4.0 - alfa * temp; + /* compute violation of inequality (15) */ + temp = x[i] + x[j] + x[k] + x[l] + alfa * y - beta; + /* choose C providing maximum violation */ + if (rmax < temp) + { rmax = temp; + cov[1] = i; + cov[2] = j; + cov[3] = k; + cov[4] = l; + *_alfa = alfa; + *_beta = beta; + ret = 1; + } + } + } +done: return ret; +} + +static int cover(int n, double a[], double b, double u, double x[], + double y, int cov[], double *alfa, double *beta) +{ /* try to generate mixed cover cut; + input (see (5)): + n is the number of binary variables; + a[1:n] are coefficients at binary variables; + b is the right-hand side; + u is upper bound of continuous variable; + x[1:n] are values of binary variables at current point; + y is value of continuous variable at current point; + output (see (15), (16), (17)): + cov[1:r] are indices of binary variables included in cover C, + where r is the set cardinality returned on exit; + alfa coefficient at continuous variable; + beta is the right-hand side; */ + int j; + /* perform some sanity checks */ + xassert(n >= 2); + for (j = 1; j <= n; j++) xassert(a[j] > 0.0); +#if 1 /* ??? */ + xassert(b > -1e-5); +#else + xassert(b > 0.0); +#endif + xassert(u >= 0.0); + for (j = 1; j <= n; j++) xassert(0.0 <= x[j] && x[j] <= 1.0); + xassert(0.0 <= y && y <= u); + /* try to generate mixed cover cut */ + if (cover2(n, a, b, u, x, y, cov, alfa, beta)) return 2; + if (cover3(n, a, b, u, x, y, cov, alfa, beta)) return 3; + if (cover4(n, a, b, u, x, y, cov, alfa, beta)) return 4; + return 0; +} + +/*---------------------------------------------------------------------- +-- lpx_cover_cut - generate mixed cover cut. +-- +-- SYNOPSIS +-- +-- int lpx_cover_cut(LPX *lp, int len, int ind[], double val[], +-- double work[]); +-- +-- DESCRIPTION +-- +-- The routine lpx_cover_cut generates a mixed cover cut for a given +-- row of the MIP problem. +-- +-- The given row of the MIP problem should be explicitly specified in +-- the form: +-- +-- sum{j in J} a[j]*x[j] <= b. (1) +-- +-- On entry indices (ordinal numbers) of structural variables, which +-- have non-zero constraint coefficients, should be placed in locations +-- ind[1], ..., ind[len], and corresponding constraint coefficients +-- should be placed in locations val[1], ..., val[len]. The right-hand +-- side b should be stored in location val[0]. +-- +-- The working array work should have at least nb locations, where nb +-- is the number of binary variables in (1). +-- +-- The routine generates a mixed cover cut in the same form as (1) and +-- stores the cut coefficients and right-hand side in the same way as +-- just described above. +-- +-- RETURNS +-- +-- If the cutting plane has been successfully generated, the routine +-- returns 1 <= len' <= n, which is the number of non-zero coefficients +-- in the inequality constraint. Otherwise, the routine returns zero. */ + +static int lpx_cover_cut(glp_prob *lp, int len, int ind[], + double val[], double work[]) +{ int cov[1+4], j, k, nb, newlen, r; + double f_min, f_max, alfa, beta, u, *x = work, y; + /* substitute and remove fixed variables */ + newlen = 0; + for (k = 1; k <= len; k++) + { j = ind[k]; + if (glp_get_col_type(lp, j) == GLP_FX) + val[0] -= val[k] * glp_get_col_lb(lp, j); + else + { newlen++; + ind[newlen] = ind[k]; + val[newlen] = val[k]; + } + } + len = newlen; + /* move binary variables to the beginning of the list so that + elements 1, 2, ..., nb correspond to binary variables, and + elements nb+1, nb+2, ..., len correspond to rest variables */ + nb = 0; + for (k = 1; k <= len; k++) + { j = ind[k]; + if (glp_get_col_kind(lp, j) == GLP_BV) + { /* binary variable */ + int ind_k; + double val_k; + nb++; + ind_k = ind[nb], val_k = val[nb]; + ind[nb] = ind[k], val[nb] = val[k]; + ind[k] = ind_k, val[k] = val_k; + } + } + /* now the specified row has the form: + sum a[j]*x[j] + sum a[j]*y[j] <= b, + where x[j] are binary variables, y[j] are rest variables */ + /* at least two binary variables are needed */ + if (nb < 2) return 0; + /* compute implied lower and upper bounds for sum a[j]*y[j] */ + f_min = f_max = 0.0; + for (k = nb+1; k <= len; k++) + { j = ind[k]; + /* both bounds must be finite */ + if (glp_get_col_type(lp, j) != GLP_DB) return 0; + if (val[k] > 0.0) + { f_min += val[k] * glp_get_col_lb(lp, j); + f_max += val[k] * glp_get_col_ub(lp, j); + } + else + { f_min += val[k] * glp_get_col_ub(lp, j); + f_max += val[k] * glp_get_col_lb(lp, j); + } + } + /* sum a[j]*x[j] + sum a[j]*y[j] <= b ===> + sum a[j]*x[j] + (sum a[j]*y[j] - f_min) <= b - f_min ===> + sum a[j]*x[j] + y <= b - f_min, + where y = sum a[j]*y[j] - f_min; + note that 0 <= y <= u, u = f_max - f_min */ + /* determine upper bound of y */ + u = f_max - f_min; + /* determine value of y at the current point */ + y = 0.0; + for (k = nb+1; k <= len; k++) + { j = ind[k]; + y += val[k] * glp_get_col_prim(lp, j); + } + y -= f_min; + if (y < 0.0) y = 0.0; + if (y > u) y = u; + /* modify the right-hand side b */ + val[0] -= f_min; + /* now the transformed row has the form: + sum a[j]*x[j] + y <= b, where 0 <= y <= u */ + /* determine values of x[j] at the current point */ + for (k = 1; k <= nb; k++) + { j = ind[k]; + x[k] = glp_get_col_prim(lp, j); + if (x[k] < 0.0) x[k] = 0.0; + if (x[k] > 1.0) x[k] = 1.0; + } + /* if a[j] < 0, replace x[j] by its complement 1 - x'[j] */ + for (k = 1; k <= nb; k++) + { if (val[k] < 0.0) + { ind[k] = - ind[k]; + val[k] = - val[k]; + val[0] += val[k]; + x[k] = 1.0 - x[k]; + } + } + /* try to generate a mixed cover cut for the transformed row */ + r = cover(nb, val, val[0], u, x, y, cov, &alfa, &beta); + if (r == 0) return 0; + xassert(2 <= r && r <= 4); + /* now the cut is in the form: + sum{j in C} x[j] + alfa * y <= beta */ + /* store the right-hand side beta */ + ind[0] = 0, val[0] = beta; + /* restore the original ordinal numbers of x[j] */ + for (j = 1; j <= r; j++) cov[j] = ind[cov[j]]; + /* store cut coefficients at binary variables complementing back + the variables having negative row coefficients */ + xassert(r <= nb); + for (k = 1; k <= r; k++) + { if (cov[k] > 0) + { ind[k] = +cov[k]; + val[k] = +1.0; + } + else + { ind[k] = -cov[k]; + val[k] = -1.0; + val[0] -= 1.0; + } + } + /* substitute y = sum a[j]*y[j] - f_min */ + for (k = nb+1; k <= len; k++) + { r++; + ind[r] = ind[k]; + val[r] = alfa * val[k]; + } + val[0] += alfa * f_min; + xassert(r <= len); + len = r; + return len; +} + +/*---------------------------------------------------------------------- +-- lpx_eval_row - compute explictily specified row. +-- +-- SYNOPSIS +-- +-- double lpx_eval_row(LPX *lp, int len, int ind[], double val[]); +-- +-- DESCRIPTION +-- +-- The routine lpx_eval_row computes the primal value of an explicitly +-- specified row using current values of structural variables. +-- +-- The explicitly specified row may be thought as a linear form: +-- +-- y = a[1]*x[m+1] + a[2]*x[m+2] + ... + a[n]*x[m+n], +-- +-- where y is an auxiliary variable for this row, a[j] are coefficients +-- of the linear form, x[m+j] are structural variables. +-- +-- On entry column indices and numerical values of non-zero elements of +-- the row should be stored in locations ind[1], ..., ind[len] and +-- val[1], ..., val[len], where len is the number of non-zero elements. +-- The array ind and val are not changed on exit. +-- +-- RETURNS +-- +-- The routine returns a computed value of y, the auxiliary variable of +-- the specified row. */ + +static double lpx_eval_row(glp_prob *lp, int len, int ind[], + double val[]) +{ int n = glp_get_num_cols(lp); + int j, k; + double sum = 0.0; + if (len < 0) + xerror("lpx_eval_row: len = %d; invalid row length\n", len); + for (k = 1; k <= len; k++) + { j = ind[k]; + if (!(1 <= j && j <= n)) + xerror("lpx_eval_row: j = %d; column number out of range\n", + j); + sum += val[k] * glp_get_col_prim(lp, j); + } + return sum; +} + +/*********************************************************************** +* NAME +* +* ios_cov_gen - generate mixed cover cuts +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_cov_gen(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_cov_gen generates mixed cover cuts for the current +* point and adds them to the cut pool. */ + +void ios_cov_gen(glp_tree *tree) +{ glp_prob *prob = tree->mip; + int m = glp_get_num_rows(prob); + int n = glp_get_num_cols(prob); + int i, k, type, kase, len, *ind; + double r, *val, *work; + xassert(glp_get_status(prob) == GLP_OPT); + /* allocate working arrays */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + work = xcalloc(1+n, sizeof(double)); + /* look through all rows */ + for (i = 1; i <= m; i++) + for (kase = 1; kase <= 2; kase++) + { type = glp_get_row_type(prob, i); + if (kase == 1) + { /* consider rows of '<=' type */ + if (!(type == GLP_UP || type == GLP_DB)) continue; + len = glp_get_mat_row(prob, i, ind, val); + val[0] = glp_get_row_ub(prob, i); + } + else + { /* consider rows of '>=' type */ + if (!(type == GLP_LO || type == GLP_DB)) continue; + len = glp_get_mat_row(prob, i, ind, val); + for (k = 1; k <= len; k++) val[k] = - val[k]; + val[0] = - glp_get_row_lb(prob, i); + } + /* generate mixed cover cut: + sum{j in J} a[j] * x[j] <= b */ + len = lpx_cover_cut(prob, len, ind, val, work); + if (len == 0) continue; + /* at the current point the cut inequality is violated, i.e. + sum{j in J} a[j] * x[j] - b > 0 */ + r = lpx_eval_row(prob, len, ind, val) - val[0]; + if (r < 1e-3) continue; + /* add the cut to the cut pool */ + glp_ios_add_row(tree, NULL, GLP_RF_COV, 0, len, ind, val, + GLP_UP, val[0]); + } + /* free working arrays */ + xfree(ind); + xfree(val); + xfree(work); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios08.c b/resources/3rdparty/glpk-4.53/src/glpios08.c new file mode 100644 index 000000000..d165492f7 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios08.c @@ -0,0 +1,147 @@ +/* glpios08.c (clique cut generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "cfg.h" +#include "env.h" +#include "glpios.h" + +void *ios_clq_init(glp_tree *T) +{ /* initialize clique cut generator */ + glp_prob *P = T->mip; + CFG *G; + int j, n1, n2; + xprintf("Constructing conflict graph...\n"); + G = cfg_build_graph(P); + n1 = n2 = 0; + for (j = 1; j <= P->n; j++) + { if (G->pos[j]) + n1 ++; + if (G->neg[j]) + n2++; + } + if (n1 == 0 && n2 == 0) + { xprintf("No conflicts found\n"); + cfg_delete_graph(G); + G = NULL; + } + else + xprintf("Conflict graph has %d + %d = %d vertices\n", + n1, n2, G->nv); + return G; +} + +void ios_clq_gen(glp_tree *T, void *G_) +{ /* attempt to generate clique cut */ + glp_prob *P = T->mip; + int n = P->n; + CFG *G = G_; + int *pos = G->pos; + int *neg = G->neg; + int nv = G->nv; + int *ref = G->ref; + int j, k, v, len, *ind; + double rhs, sum, *val; + xassert(G->n == n); + /* allocate working arrays */ + ind = talloc(1+n, int); + val = talloc(1+n, double); + /* find maximum weight clique in conflict graph */ + len = cfg_find_clique(P, G, ind, &sum); +#ifdef GLP_DEBUG + xprintf("len = %d; sum = %g\n", len, sum); + cfg_check_clique(G, len, ind); +#endif + /* check if clique inequality is violated */ + if (sum < 1.07) + goto skip; + /* expand clique to maximal one */ + len = cfg_expand_clique(G, len, ind); +#ifdef GLP_DEBUG + xprintf("maximal clique size = %d\n", len); + cfg_check_clique(G, len, ind); +#endif + /* construct clique cut (fixed binary variables are removed, so + this cut is only locally valid) */ + rhs = 1.0; + for (j = 1; j <= n; j++) + val[j] = 0.0; + for (k = 1; k <= len; k++) + { /* v is clique vertex */ + v = ind[k]; + xassert(1 <= v && v <= nv); + /* j is number of corresponding binary variable */ + j = ref[v]; + xassert(1 <= j && j <= n); + if (pos[j] == v) + { /* v corresponds to x[j] */ + if (P->col[j]->type == GLP_FX) + { /* x[j] is fixed */ + rhs -= P->col[j]->prim; + } + else + { /* x[j] is not fixed */ + val[j] += 1.0; + } + } + else if (neg[j] == v) + { /* v corresponds to (1 - x[j]) */ + if (P->col[j]->type == GLP_FX) + { /* x[j] is fixed */ + rhs -= (1.0 - P->col[j]->prim); + } + else + { /* x[j] is not fixed */ + val[j] -= 1.0; + rhs -= 1.0; + } + } + else + xassert(v != v); + } + /* convert cut inequality to sparse format */ + len = 0; + for (j = 1; j <= n; j++) + { if (val[j] != 0.0) + { len++; + ind[len] = j; + val[len] = val[j]; + } + } + /* add cut inequality to local cut pool */ + glp_ios_add_row(T, NULL, GLP_RF_CLQ, 0, len, ind, val, GLP_UP, + rhs); +skip: /* free working arrays */ + tfree(ind); + tfree(val); + return; +} + +void ios_clq_term(void *G_) +{ /* terminate clique cut generator */ + CFG *G = G_; + xassert(G != NULL); + cfg_delete_graph(G); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios09.c b/resources/3rdparty/glpk-4.53/src/glpios09.c new file mode 100644 index 000000000..d87578cbc --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios09.c @@ -0,0 +1,664 @@ +/* glpios09.c (branching heuristics) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" + +/*********************************************************************** +* NAME +* +* ios_choose_var - select variable to branch on +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_choose_var(glp_tree *T, int *next); +* +* The routine ios_choose_var chooses a variable from the candidate +* list to branch on. Additionally the routine provides a flag stored +* in the location next to suggests which of the child subproblems +* should be solved next. +* +* RETURNS +* +* The routine ios_choose_var returns the ordinal number of the column +* choosen. */ + +static int branch_first(glp_tree *T, int *next); +static int branch_last(glp_tree *T, int *next); +static int branch_mostf(glp_tree *T, int *next); +static int branch_drtom(glp_tree *T, int *next); + +int ios_choose_var(glp_tree *T, int *next) +{ int j; + if (T->parm->br_tech == GLP_BR_FFV) + { /* branch on first fractional variable */ + j = branch_first(T, next); + } + else if (T->parm->br_tech == GLP_BR_LFV) + { /* branch on last fractional variable */ + j = branch_last(T, next); + } + else if (T->parm->br_tech == GLP_BR_MFV) + { /* branch on most fractional variable */ + j = branch_mostf(T, next); + } + else if (T->parm->br_tech == GLP_BR_DTH) + { /* branch using the heuristic by Dreebeck and Tomlin */ + j = branch_drtom(T, next); + } + else if (T->parm->br_tech == GLP_BR_PCH) + { /* hybrid pseudocost heuristic */ + j = ios_pcost_branch(T, next); + } + else + xassert(T != T); + return j; +} + +/*********************************************************************** +* branch_first - choose first branching variable +* +* This routine looks up the list of structural variables and chooses +* the first one, which is of integer kind and has fractional value in +* optimal solution to the current LP relaxation. +* +* This routine also selects the branch to be solved next where integer +* infeasibility of the chosen variable is less than in other one. */ + +static int branch_first(glp_tree *T, int *_next) +{ int j, next; + double beta; + /* choose the column to branch on */ + for (j = 1; j <= T->n; j++) + if (T->non_int[j]) break; + xassert(1 <= j && j <= T->n); + /* select the branch to be solved next */ + beta = glp_get_col_prim(T->mip, j); + if (beta - floor(beta) < ceil(beta) - beta) + next = GLP_DN_BRNCH; + else + next = GLP_UP_BRNCH; + *_next = next; + return j; +} + +/*********************************************************************** +* branch_last - choose last branching variable +* +* This routine looks up the list of structural variables and chooses +* the last one, which is of integer kind and has fractional value in +* optimal solution to the current LP relaxation. +* +* This routine also selects the branch to be solved next where integer +* infeasibility of the chosen variable is less than in other one. */ + +static int branch_last(glp_tree *T, int *_next) +{ int j, next; + double beta; + /* choose the column to branch on */ + for (j = T->n; j >= 1; j--) + if (T->non_int[j]) break; + xassert(1 <= j && j <= T->n); + /* select the branch to be solved next */ + beta = glp_get_col_prim(T->mip, j); + if (beta - floor(beta) < ceil(beta) - beta) + next = GLP_DN_BRNCH; + else + next = GLP_UP_BRNCH; + *_next = next; + return j; +} + +/*********************************************************************** +* branch_mostf - choose most fractional branching variable +* +* This routine looks up the list of structural variables and chooses +* that one, which is of integer kind and has most fractional value in +* optimal solution to the current LP relaxation. +* +* This routine also selects the branch to be solved next where integer +* infeasibility of the chosen variable is less than in other one. +* +* (Alexander Martin notices that "...most infeasible is as good as +* random...".) */ + +static int branch_mostf(glp_tree *T, int *_next) +{ int j, jj, next; + double beta, most, temp; + /* choose the column to branch on */ + jj = 0, most = DBL_MAX; + for (j = 1; j <= T->n; j++) + { if (T->non_int[j]) + { beta = glp_get_col_prim(T->mip, j); + temp = floor(beta) + 0.5; + if (most > fabs(beta - temp)) + { jj = j, most = fabs(beta - temp); + if (beta < temp) + next = GLP_DN_BRNCH; + else + next = GLP_UP_BRNCH; + } + } + } + *_next = next; + return jj; +} + +/*********************************************************************** +* branch_drtom - choose branching var using Driebeck-Tomlin heuristic +* +* This routine chooses a structural variable, which is required to be +* integral and has fractional value in optimal solution of the current +* LP relaxation, using a heuristic proposed by Driebeck and Tomlin. +* +* The routine also selects the branch to be solved next, again due to +* Driebeck and Tomlin. +* +* This routine is based on the heuristic proposed in: +* +* Driebeck N.J. An algorithm for the solution of mixed-integer +* programming problems, Management Science, 12: 576-87 (1966); +* +* and improved in: +* +* Tomlin J.A. Branch and bound methods for integer and non-convex +* programming, in J.Abadie (ed.), Integer and Nonlinear Programming, +* North-Holland, Amsterdam, pp. 437-50 (1970). +* +* Must note that this heuristic is time-expensive, because computing +* one-step degradation (see the routine below) requires one BTRAN for +* each fractional-valued structural variable. */ + +static int branch_drtom(glp_tree *T, int *_next) +{ glp_prob *mip = T->mip; + int m = mip->m; + int n = mip->n; + unsigned char *non_int = T->non_int; + int j, jj, k, t, next, kase, len, stat, *ind; + double x, dk, alfa, delta_j, delta_k, delta_z, dz_dn, dz_up, + dd_dn, dd_up, degrad, *val; + /* basic solution of LP relaxation must be optimal */ + xassert(glp_get_status(mip) == GLP_OPT); + /* allocate working arrays */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + /* nothing has been chosen so far */ + jj = 0, degrad = -1.0; + /* walk through the list of columns (structural variables) */ + for (j = 1; j <= n; j++) + { /* if j-th column is not marked as fractional, skip it */ + if (!non_int[j]) continue; + /* obtain (fractional) value of j-th column in basic solution + of LP relaxation */ + x = glp_get_col_prim(mip, j); + /* since the value of j-th column is fractional, the column is + basic; compute corresponding row of the simplex table */ + len = glp_eval_tab_row(mip, m+j, ind, val); + /* the following fragment computes a change in the objective + function: delta Z = new Z - old Z, where old Z is the + objective value in the current optimal basis, and new Z is + the objective value in the adjacent basis, for two cases: + 1) if new upper bound ub' = floor(x[j]) is introduced for + j-th column (down branch); + 2) if new lower bound lb' = ceil(x[j]) is introduced for + j-th column (up branch); + since in both cases the solution remaining dual feasible + becomes primal infeasible, one implicit simplex iteration + is performed to determine the change delta Z; + it is obvious that new Z, which is never better than old Z, + is a lower (minimization) or upper (maximization) bound of + the objective function for down- and up-branches. */ + for (kase = -1; kase <= +1; kase += 2) + { /* if kase < 0, the new upper bound of x[j] is introduced; + in this case x[j] should decrease in order to leave the + basis and go to its new upper bound */ + /* if kase > 0, the new lower bound of x[j] is introduced; + in this case x[j] should increase in order to leave the + basis and go to its new lower bound */ + /* apply the dual ratio test in order to determine which + auxiliary or structural variable should enter the basis + to keep dual feasibility */ + k = glp_dual_rtest(mip, len, ind, val, kase, 1e-9); + if (k != 0) k = ind[k]; + /* if no non-basic variable has been chosen, LP relaxation + of corresponding branch being primal infeasible and dual + unbounded has no primal feasible solution; in this case + the change delta Z is formally set to infinity */ + if (k == 0) + { delta_z = + (T->mip->dir == GLP_MIN ? +DBL_MAX : -DBL_MAX); + goto skip; + } + /* row of the simplex table that corresponds to non-basic + variable x[k] choosen by the dual ratio test is: + x[j] = ... + alfa * x[k] + ... + where alfa is the influence coefficient (an element of + the simplex table row) */ + /* determine the coefficient alfa */ + for (t = 1; t <= len; t++) if (ind[t] == k) break; + xassert(1 <= t && t <= len); + alfa = val[t]; + /* since in the adjacent basis the variable x[j] becomes + non-basic, knowing its value in the current basis we can + determine its change delta x[j] = new x[j] - old x[j] */ + delta_j = (kase < 0 ? floor(x) : ceil(x)) - x; + /* and knowing the coefficient alfa we can determine the + corresponding change delta x[k] = new x[k] - old x[k], + where old x[k] is a value of x[k] in the current basis, + and new x[k] is a value of x[k] in the adjacent basis */ + delta_k = delta_j / alfa; + /* Tomlin noticed that if the variable x[k] is of integer + kind, its change cannot be less (eventually) than one in + the magnitude */ + if (k > m && glp_get_col_kind(mip, k-m) != GLP_CV) + { /* x[k] is structural integer variable */ + if (fabs(delta_k - floor(delta_k + 0.5)) > 1e-3) + { if (delta_k > 0.0) + delta_k = ceil(delta_k); /* +3.14 -> +4 */ + else + delta_k = floor(delta_k); /* -3.14 -> -4 */ + } + } + /* now determine the status and reduced cost of x[k] in the + current basis */ + if (k <= m) + { stat = glp_get_row_stat(mip, k); + dk = glp_get_row_dual(mip, k); + } + else + { stat = glp_get_col_stat(mip, k-m); + dk = glp_get_col_dual(mip, k-m); + } + /* if the current basis is dual degenerate, some reduced + costs which are close to zero may have wrong sign due to + round-off errors, so correct the sign of d[k] */ + switch (T->mip->dir) + { case GLP_MIN: + if (stat == GLP_NL && dk < 0.0 || + stat == GLP_NU && dk > 0.0 || + stat == GLP_NF) dk = 0.0; + break; + case GLP_MAX: + if (stat == GLP_NL && dk > 0.0 || + stat == GLP_NU && dk < 0.0 || + stat == GLP_NF) dk = 0.0; + break; + default: + xassert(T != T); + } + /* now knowing the change of x[k] and its reduced cost d[k] + we can compute the corresponding change in the objective + function delta Z = new Z - old Z = d[k] * delta x[k]; + note that due to Tomlin's modification new Z can be even + worse than in the adjacent basis */ + delta_z = dk * delta_k; +skip: /* new Z is never better than old Z, therefore the change + delta Z is always non-negative (in case of minimization) + or non-positive (in case of maximization) */ + switch (T->mip->dir) + { case GLP_MIN: xassert(delta_z >= 0.0); break; + case GLP_MAX: xassert(delta_z <= 0.0); break; + default: xassert(T != T); + } + /* save the change in the objective fnction for down- and + up-branches, respectively */ + if (kase < 0) dz_dn = delta_z; else dz_up = delta_z; + } + /* thus, in down-branch no integer feasible solution can be + better than Z + dz_dn, and in up-branch no integer feasible + solution can be better than Z + dz_up, where Z is value of + the objective function in the current basis */ + /* following the heuristic by Driebeck and Tomlin we choose a + column (i.e. structural variable) which provides largest + degradation of the objective function in some of branches; + besides, we select the branch with smaller degradation to + be solved next and keep other branch with larger degradation + in the active list hoping to minimize the number of further + backtrackings */ + if (degrad < fabs(dz_dn) || degrad < fabs(dz_up)) + { jj = j; + if (fabs(dz_dn) < fabs(dz_up)) + { /* select down branch to be solved next */ + next = GLP_DN_BRNCH; + degrad = fabs(dz_up); + } + else + { /* select up branch to be solved next */ + next = GLP_UP_BRNCH; + degrad = fabs(dz_dn); + } + /* save the objective changes for printing */ + dd_dn = dz_dn, dd_up = dz_up; + /* if down- or up-branch has no feasible solution, we does + not need to consider other candidates (in principle, the + corresponding branch could be pruned right now) */ + if (degrad == DBL_MAX) break; + } + } + /* free working arrays */ + xfree(ind); + xfree(val); + /* something must be chosen */ + xassert(1 <= jj && jj <= n); +#if 1 /* 02/XI-2009 */ + if (degrad < 1e-6 * (1.0 + 0.001 * fabs(mip->obj_val))) + { jj = branch_mostf(T, &next); + goto done; + } +#endif + if (T->parm->msg_lev >= GLP_MSG_DBG) + { xprintf("branch_drtom: column %d chosen to branch on\n", jj); + if (fabs(dd_dn) == DBL_MAX) + xprintf("branch_drtom: down-branch is infeasible\n"); + else + xprintf("branch_drtom: down-branch bound is %.9e\n", + glp_get_obj_val(mip) + dd_dn); + if (fabs(dd_up) == DBL_MAX) + xprintf("branch_drtom: up-branch is infeasible\n"); + else + xprintf("branch_drtom: up-branch bound is %.9e\n", + glp_get_obj_val(mip) + dd_up); + } +done: *_next = next; + return jj; +} + +/**********************************************************************/ + +struct csa +{ /* common storage area */ + int *dn_cnt; /* int dn_cnt[1+n]; */ + /* dn_cnt[j] is the number of subproblems, whose LP relaxations + have been solved and which are down-branches for variable x[j]; + dn_cnt[j] = 0 means the down pseudocost is uninitialized */ + double *dn_sum; /* double dn_sum[1+n]; */ + /* dn_sum[j] is the sum of per unit degradations of the objective + over all dn_cnt[j] subproblems */ + int *up_cnt; /* int up_cnt[1+n]; */ + /* up_cnt[j] is the number of subproblems, whose LP relaxations + have been solved and which are up-branches for variable x[j]; + up_cnt[j] = 0 means the up pseudocost is uninitialized */ + double *up_sum; /* double up_sum[1+n]; */ + /* up_sum[j] is the sum of per unit degradations of the objective + over all up_cnt[j] subproblems */ +}; + +void *ios_pcost_init(glp_tree *tree) +{ /* initialize working data used on pseudocost branching */ + struct csa *csa; + int n = tree->n, j; + csa = xmalloc(sizeof(struct csa)); + csa->dn_cnt = xcalloc(1+n, sizeof(int)); + csa->dn_sum = xcalloc(1+n, sizeof(double)); + csa->up_cnt = xcalloc(1+n, sizeof(int)); + csa->up_sum = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) + { csa->dn_cnt[j] = csa->up_cnt[j] = 0; + csa->dn_sum[j] = csa->up_sum[j] = 0.0; + } + return csa; +} + +static double eval_degrad(glp_prob *P, int j, double bnd) +{ /* compute degradation of the objective on fixing x[j] at given + value with a limited number of dual simplex iterations */ + /* this routine fixes column x[j] at specified value bnd, + solves resulting LP, and returns a lower bound to degradation + of the objective, degrad >= 0 */ + glp_prob *lp; + glp_smcp parm; + int ret; + double degrad; + /* the current basis must be optimal */ + xassert(glp_get_status(P) == GLP_OPT); + /* create a copy of P */ + lp = glp_create_prob(); + glp_copy_prob(lp, P, 0); + /* fix column x[j] at specified value */ + glp_set_col_bnds(lp, j, GLP_FX, bnd, bnd); + /* try to solve resulting LP */ + glp_init_smcp(&parm); + parm.msg_lev = GLP_MSG_OFF; + parm.meth = GLP_DUAL; + parm.it_lim = 30; + parm.out_dly = 1000; + parm.meth = GLP_DUAL; + ret = glp_simplex(lp, &parm); + if (ret == 0 || ret == GLP_EITLIM) + { if (glp_get_prim_stat(lp) == GLP_NOFEAS) + { /* resulting LP has no primal feasible solution */ + degrad = DBL_MAX; + } + else if (glp_get_dual_stat(lp) == GLP_FEAS) + { /* resulting basis is optimal or at least dual feasible, + so we have the correct lower bound to degradation */ + if (P->dir == GLP_MIN) + degrad = lp->obj_val - P->obj_val; + else if (P->dir == GLP_MAX) + degrad = P->obj_val - lp->obj_val; + else + xassert(P != P); + /* degradation cannot be negative by definition */ + /* note that the lower bound to degradation may be close + to zero even if its exact value is zero due to round-off + errors on computing the objective value */ + if (degrad < 1e-6 * (1.0 + 0.001 * fabs(P->obj_val))) + degrad = 0.0; + } + else + { /* the final basis reported by the simplex solver is dual + infeasible, so we cannot determine a non-trivial lower + bound to degradation */ + degrad = 0.0; + } + } + else + { /* the simplex solver failed */ + degrad = 0.0; + } + /* delete the copy of P */ + glp_delete_prob(lp); + return degrad; +} + +void ios_pcost_update(glp_tree *tree) +{ /* update history information for pseudocost branching */ + /* this routine is called every time when LP relaxation of the + current subproblem has been solved to optimality with all lazy + and cutting plane constraints included */ + int j; + double dx, dz, psi; + struct csa *csa = tree->pcost; + xassert(csa != NULL); + xassert(tree->curr != NULL); + /* if the current subproblem is the root, skip updating */ + if (tree->curr->up == NULL) goto skip; + /* determine branching variable x[j], which was used in the + parent subproblem to create the current subproblem */ + j = tree->curr->up->br_var; + xassert(1 <= j && j <= tree->n); + /* determine the change dx[j] = new x[j] - old x[j], + where new x[j] is a value of x[j] in optimal solution to LP + relaxation of the current subproblem, old x[j] is a value of + x[j] in optimal solution to LP relaxation of the parent + subproblem */ + dx = tree->mip->col[j]->prim - tree->curr->up->br_val; + xassert(dx != 0.0); + /* determine corresponding change dz = new dz - old dz in the + objective function value */ + dz = tree->mip->obj_val - tree->curr->up->lp_obj; + /* determine per unit degradation of the objective function */ + psi = fabs(dz / dx); + /* update history information */ + if (dx < 0.0) + { /* the current subproblem is down-branch */ + csa->dn_cnt[j]++; + csa->dn_sum[j] += psi; + } + else /* dx > 0.0 */ + { /* the current subproblem is up-branch */ + csa->up_cnt[j]++; + csa->up_sum[j] += psi; + } +skip: return; +} + +void ios_pcost_free(glp_tree *tree) +{ /* free working area used on pseudocost branching */ + struct csa *csa = tree->pcost; + xassert(csa != NULL); + xfree(csa->dn_cnt); + xfree(csa->dn_sum); + xfree(csa->up_cnt); + xfree(csa->up_sum); + xfree(csa); + tree->pcost = NULL; + return; +} + +static double eval_psi(glp_tree *T, int j, int brnch) +{ /* compute estimation of pseudocost of variable x[j] for down- + or up-branch */ + struct csa *csa = T->pcost; + double beta, degrad, psi; + xassert(csa != NULL); + xassert(1 <= j && j <= T->n); + if (brnch == GLP_DN_BRNCH) + { /* down-branch */ + if (csa->dn_cnt[j] == 0) + { /* initialize down pseudocost */ + beta = T->mip->col[j]->prim; + degrad = eval_degrad(T->mip, j, floor(beta)); + if (degrad == DBL_MAX) + { psi = DBL_MAX; + goto done; + } + csa->dn_cnt[j] = 1; + csa->dn_sum[j] = degrad / (beta - floor(beta)); + } + psi = csa->dn_sum[j] / (double)csa->dn_cnt[j]; + } + else if (brnch == GLP_UP_BRNCH) + { /* up-branch */ + if (csa->up_cnt[j] == 0) + { /* initialize up pseudocost */ + beta = T->mip->col[j]->prim; + degrad = eval_degrad(T->mip, j, ceil(beta)); + if (degrad == DBL_MAX) + { psi = DBL_MAX; + goto done; + } + csa->up_cnt[j] = 1; + csa->up_sum[j] = degrad / (ceil(beta) - beta); + } + psi = csa->up_sum[j] / (double)csa->up_cnt[j]; + } + else + xassert(brnch != brnch); +done: return psi; +} + +static void progress(glp_tree *T) +{ /* display progress of pseudocost initialization */ + struct csa *csa = T->pcost; + int j, nv = 0, ni = 0; + for (j = 1; j <= T->n; j++) + { if (glp_ios_can_branch(T, j)) + { nv++; + if (csa->dn_cnt[j] > 0 && csa->up_cnt[j] > 0) ni++; + } + } + xprintf("Pseudocosts initialized for %d of %d variables\n", + ni, nv); + return; +} + +int ios_pcost_branch(glp_tree *T, int *_next) +{ /* choose branching variable with pseudocost branching */ +#if 0 /* 10/VI-2013 */ + glp_long t = xtime(); +#else + double t = xtime(); +#endif + int j, jjj, sel; + double beta, psi, d1, d2, d, dmax; + /* initialize the working arrays */ + if (T->pcost == NULL) + T->pcost = ios_pcost_init(T); + /* nothing has been chosen so far */ + jjj = 0, dmax = -1.0; + /* go through the list of branching candidates */ + for (j = 1; j <= T->n; j++) + { if (!glp_ios_can_branch(T, j)) continue; + /* determine primal value of x[j] in optimal solution to LP + relaxation of the current subproblem */ + beta = T->mip->col[j]->prim; + /* estimate pseudocost of x[j] for down-branch */ + psi = eval_psi(T, j, GLP_DN_BRNCH); + if (psi == DBL_MAX) + { /* down-branch has no primal feasible solution */ + jjj = j, sel = GLP_DN_BRNCH; + goto done; + } + /* estimate degradation of the objective for down-branch */ + d1 = psi * (beta - floor(beta)); + /* estimate pseudocost of x[j] for up-branch */ + psi = eval_psi(T, j, GLP_UP_BRNCH); + if (psi == DBL_MAX) + { /* up-branch has no primal feasible solution */ + jjj = j, sel = GLP_UP_BRNCH; + goto done; + } + /* estimate degradation of the objective for up-branch */ + d2 = psi * (ceil(beta) - beta); + /* determine d = max(d1, d2) */ + d = (d1 > d2 ? d1 : d2); + /* choose x[j] which provides maximal estimated degradation of + the objective either in down- or up-branch */ + if (dmax < d) + { dmax = d; + jjj = j; + /* continue the search from a subproblem, where degradation + is less than in other one */ + sel = (d1 <= d2 ? GLP_DN_BRNCH : GLP_UP_BRNCH); + } + /* display progress of pseudocost initialization */ + if (T->parm->msg_lev >= GLP_ON) + { if (xdifftime(xtime(), t) >= 10.0) + { progress(T); + t = xtime(); + } + } + } + if (dmax == 0.0) + { /* no degradation is indicated; choose a variable having most + fractional value */ + jjj = branch_mostf(T, &sel); + } +done: *_next = sel; + return jjj; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios10.c b/resources/3rdparty/glpk-4.53/src/glpios10.c new file mode 100644 index 000000000..e67625795 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios10.c @@ -0,0 +1,355 @@ +/* glpios10.c (feasibility pump heuristic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" +#include "rng.h" + +/*********************************************************************** +* NAME +* +* ios_feas_pump - feasibility pump heuristic +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_feas_pump(glp_tree *T); +* +* DESCRIPTION +* +* The routine ios_feas_pump is a simple implementation of the Feasi- +* bility Pump heuristic. +* +* REFERENCES +* +* M.Fischetti, F.Glover, and A.Lodi. "The feasibility pump." Math. +* Program., Ser. A 104, pp. 91-104 (2005). */ + +struct VAR +{ /* binary variable */ + int j; + /* ordinal number */ + int x; + /* value in the rounded solution (0 or 1) */ + double d; + /* sorting key */ +}; + +static int fcmp(const void *x, const void *y) +{ /* comparison routine */ + const struct VAR *vx = x, *vy = y; + if (vx->d > vy->d) + return -1; + else if (vx->d < vy->d) + return +1; + else + return 0; +} + +void ios_feas_pump(glp_tree *T) +{ glp_prob *P = T->mip; + int n = P->n; + glp_prob *lp = NULL; + struct VAR *var = NULL; + RNG *rand = NULL; + GLPCOL *col; + glp_smcp parm; + int j, k, new_x, nfail, npass, nv, ret, stalling; + double dist, tol; + xassert(glp_get_status(P) == GLP_OPT); + /* this heuristic is applied only once on the root level */ + if (!(T->curr->level == 0 && T->curr->solved == 1)) goto done; + /* determine number of binary variables */ + nv = 0; + for (j = 1; j <= n; j++) + { col = P->col[j]; + /* if x[j] is continuous, skip it */ + if (col->kind == GLP_CV) continue; + /* if x[j] is fixed, skip it */ + if (col->type == GLP_FX) continue; + /* x[j] is non-fixed integer */ + xassert(col->kind == GLP_IV); + if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0) + { /* x[j] is binary */ + nv++; + } + else + { /* x[j] is general integer */ + if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("FPUMP heuristic cannot be applied due to genera" + "l integer variables\n"); + goto done; + } + } + /* there must be at least one binary variable */ + if (nv == 0) goto done; + if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Applying FPUMP heuristic...\n"); + /* build the list of binary variables */ + var = xcalloc(1+nv, sizeof(struct VAR)); + k = 0; + for (j = 1; j <= n; j++) + { col = P->col[j]; + if (col->kind == GLP_IV && col->type == GLP_DB) + var[++k].j = j; + } + xassert(k == nv); + /* create working problem object */ + lp = glp_create_prob(); +more: /* copy the original problem object to keep it intact */ + glp_copy_prob(lp, P, GLP_OFF); + /* we are interested to find an integer feasible solution, which + is better than the best known one */ + if (P->mip_stat == GLP_FEAS) + { int *ind; + double *val, bnd; + /* add a row and make it identical to the objective row */ + glp_add_rows(lp, 1); + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) + { ind[j] = j; + val[j] = P->col[j]->coef; + } + glp_set_mat_row(lp, lp->m, n, ind, val); + xfree(ind); + xfree(val); + /* introduce upper (minimization) or lower (maximization) + bound to the original objective function; note that this + additional constraint is not violated at the optimal point + to LP relaxation */ +#if 0 /* modified by xypron <xypron.glpk@gmx.de> */ + if (P->dir == GLP_MIN) + { bnd = P->mip_obj - 0.10 * (1.0 + fabs(P->mip_obj)); + if (bnd < P->obj_val) bnd = P->obj_val; + glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0); + } + else if (P->dir == GLP_MAX) + { bnd = P->mip_obj + 0.10 * (1.0 + fabs(P->mip_obj)); + if (bnd > P->obj_val) bnd = P->obj_val; + glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0); + } + else + xassert(P != P); +#else + bnd = 0.1 * P->obj_val + 0.9 * P->mip_obj; + /* xprintf("bnd = %f\n", bnd); */ + if (P->dir == GLP_MIN) + glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0); + else if (P->dir == GLP_MAX) + glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0); + else + xassert(P != P); +#endif + } + /* reset pass count */ + npass = 0; + /* invalidate the rounded point */ + for (k = 1; k <= nv; k++) + var[k].x = -1; +pass: /* next pass starts here */ + npass++; + if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Pass %d\n", npass); + /* initialize minimal distance between the basic point and the + rounded one obtained during this pass */ + dist = DBL_MAX; + /* reset failure count (the number of succeeded iterations failed + to improve the distance) */ + nfail = 0; + /* if it is not the first pass, perturb the last rounded point + rather than construct it from the basic solution */ + if (npass > 1) + { double rho, temp; + if (rand == NULL) + rand = rng_create_rand(); + for (k = 1; k <= nv; k++) + { j = var[k].j; + col = lp->col[j]; + rho = rng_uniform(rand, -0.3, 0.7); + if (rho < 0.0) rho = 0.0; + temp = fabs((double)var[k].x - col->prim); + if (temp + rho > 0.5) var[k].x = 1 - var[k].x; + } + goto skip; + } +loop: /* innermost loop begins here */ + /* round basic solution (which is assumed primal feasible) */ + stalling = 1; + for (k = 1; k <= nv; k++) + { col = lp->col[var[k].j]; + if (col->prim < 0.5) + { /* rounded value is 0 */ + new_x = 0; + } + else + { /* rounded value is 1 */ + new_x = 1; + } + if (var[k].x != new_x) + { stalling = 0; + var[k].x = new_x; + } + } + /* if the rounded point has not changed (stalling), choose and + flip some its entries heuristically */ + if (stalling) + { /* compute d[j] = |x[j] - round(x[j])| */ + for (k = 1; k <= nv; k++) + { col = lp->col[var[k].j]; + var[k].d = fabs(col->prim - (double)var[k].x); + } + /* sort the list of binary variables by descending d[j] */ + qsort(&var[1], nv, sizeof(struct VAR), fcmp); + /* choose and flip some rounded components */ + for (k = 1; k <= nv; k++) + { if (k >= 5 && var[k].d < 0.35 || k >= 10) break; + var[k].x = 1 - var[k].x; + } + } +skip: /* check if the time limit has been exhausted */ + if (T->parm->tm_lim < INT_MAX && + (double)(T->parm->tm_lim - 1) <= + 1000.0 * xdifftime(xtime(), T->tm_beg)) goto done; + /* build the objective, which is the distance between the current + (basic) point and the rounded one */ + lp->dir = GLP_MIN; + lp->c0 = 0.0; + for (j = 1; j <= n; j++) + lp->col[j]->coef = 0.0; + for (k = 1; k <= nv; k++) + { j = var[k].j; + if (var[k].x == 0) + lp->col[j]->coef = +1.0; + else + { lp->col[j]->coef = -1.0; + lp->c0 += 1.0; + } + } + /* minimize the distance with the simplex method */ + glp_init_smcp(&parm); + if (T->parm->msg_lev <= GLP_MSG_ERR) + parm.msg_lev = T->parm->msg_lev; + else if (T->parm->msg_lev <= GLP_MSG_ALL) + { parm.msg_lev = GLP_MSG_ON; + parm.out_dly = 10000; + } + ret = glp_simplex(lp, &parm); + if (ret != 0) + { if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: glp_simplex returned %d\n", ret); + goto done; + } + ret = glp_get_status(lp); + if (ret != GLP_OPT) + { if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: glp_get_status returned %d\n", ret); + goto done; + } + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("delta = %g\n", lp->obj_val); + /* check if the basic solution is integer feasible; note that it + may be so even if the minimial distance is positive */ + tol = 0.3 * T->parm->tol_int; + for (k = 1; k <= nv; k++) + { col = lp->col[var[k].j]; + if (tol < col->prim && col->prim < 1.0 - tol) break; + } + if (k > nv) + { /* okay; the basic solution seems to be integer feasible */ + double *x = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) + { x[j] = lp->col[j]->prim; + if (P->col[j]->kind == GLP_IV) x[j] = floor(x[j] + 0.5); + } +#if 1 /* modified by xypron <xypron.glpk@gmx.de> */ + /* reset direction and right-hand side of objective */ + lp->c0 = P->c0; + lp->dir = P->dir; + /* fix integer variables */ + for (k = 1; k <= nv; k++) +#if 0 /* 18/VI-2013; fixed by mao + * this bug causes numerical instability, because column statuses + * are not changed appropriately */ + { lp->col[var[k].j]->lb = x[var[k].j]; + lp->col[var[k].j]->ub = x[var[k].j]; + lp->col[var[k].j]->type = GLP_FX; + } +#else + glp_set_col_bnds(lp, var[k].j, GLP_FX, x[var[k].j], 0.); +#endif + /* copy original objective function */ + for (j = 1; j <= n; j++) + lp->col[j]->coef = P->col[j]->coef; + /* solve original LP and copy result */ + ret = glp_simplex(lp, &parm); + if (ret != 0) + { if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: glp_simplex returned %d\n", ret); + goto done; + } + ret = glp_get_status(lp); + if (ret != GLP_OPT) + { if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: glp_get_status returned %d\n", ret); + goto done; + } + for (j = 1; j <= n; j++) + if (P->col[j]->kind != GLP_IV) x[j] = lp->col[j]->prim; +#endif + ret = glp_ios_heur_sol(T, x); + xfree(x); + if (ret == 0) + { /* the integer solution is accepted */ + if (ios_is_hopeful(T, T->curr->bound)) + { /* it is reasonable to apply the heuristic once again */ + goto more; + } + else + { /* the best known integer feasible solution just found + is close to optimal solution to LP relaxation */ + goto done; + } + } + } + /* the basic solution is fractional */ + if (dist == DBL_MAX || + lp->obj_val <= dist - 1e-6 * (1.0 + dist)) + { /* the distance is reducing */ + nfail = 0, dist = lp->obj_val; + } + else + { /* improving the distance failed */ + nfail++; + } + if (nfail < 3) goto loop; + if (npass < 5) goto pass; +done: /* delete working objects */ + if (lp != NULL) glp_delete_prob(lp); + if (var != NULL) xfree(var); + if (rand != NULL) rng_delete_rand(rand); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios11.c b/resources/3rdparty/glpk-4.53/src/glpios11.c new file mode 100644 index 000000000..a9f4854d8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios11.c @@ -0,0 +1,282 @@ +/* glpios11.c (process cuts stored in the local cut pool) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "draft.h" +#include "env.h" +#include "glpios.h" + +/*********************************************************************** +* NAME +* +* ios_process_cuts - process cuts stored in the local cut pool +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_process_cuts(glp_tree *T); +* +* DESCRIPTION +* +* The routine ios_process_cuts analyzes each cut currently stored in +* the local cut pool, which must be non-empty, and either adds the cut +* to the current subproblem or just discards it. All cuts are assumed +* to be locally valid. On exit the local cut pool remains unchanged. +* +* REFERENCES +* +* 1. E.Balas, S.Ceria, G.Cornuejols, "Mixed 0-1 Programming by +* Lift-and-Project in a Branch-and-Cut Framework", Management Sc., +* 42 (1996) 1229-1246. +* +* 2. G.Andreello, A.Caprara, and M.Fischetti, "Embedding Cuts in +* a Branch&Cut Framework: a Computational Study with {0,1/2}-Cuts", +* Preliminary Draft, October 28, 2003, pp.6-8. */ + +struct info +{ /* estimated cut efficiency */ + IOSCUT *cut; + /* pointer to cut in the cut pool */ + char flag; + /* if this flag is set, the cut is included into the current + subproblem */ + double eff; + /* cut efficacy (normalized residual) */ + double deg; + /* lower bound to objective degradation */ +}; + +static int fcmp(const void *arg1, const void *arg2) +{ const struct info *info1 = arg1, *info2 = arg2; + if (info1->deg == 0.0 && info2->deg == 0.0) + { if (info1->eff > info2->eff) return -1; + if (info1->eff < info2->eff) return +1; + } + else + { if (info1->deg > info2->deg) return -1; + if (info1->deg < info2->deg) return +1; + } + return 0; +} + +static double parallel(IOSCUT *a, IOSCUT *b, double work[]); + +void ios_process_cuts(glp_tree *T) +{ IOSPOOL *pool; + IOSCUT *cut; + IOSAIJ *aij; + struct info *info; + int k, kk, max_cuts, len, ret, *ind; + double *val, *work; + /* the current subproblem must exist */ + xassert(T->curr != NULL); + /* the pool must exist and be non-empty */ + pool = T->local; + xassert(pool != NULL); + xassert(pool->size > 0); + /* allocate working arrays */ + info = xcalloc(1+pool->size, sizeof(struct info)); + ind = xcalloc(1+T->n, sizeof(int)); + val = xcalloc(1+T->n, sizeof(double)); + work = xcalloc(1+T->n, sizeof(double)); + for (k = 1; k <= T->n; k++) work[k] = 0.0; + /* build the list of cuts stored in the cut pool */ + for (k = 0, cut = pool->head; cut != NULL; cut = cut->next) + k++, info[k].cut = cut, info[k].flag = 0; + xassert(k == pool->size); + /* estimate efficiency of all cuts in the cut pool */ + for (k = 1; k <= pool->size; k++) + { double temp, dy, dz; + cut = info[k].cut; + /* build the vector of cut coefficients and compute its + Euclidean norm */ + len = 0; temp = 0.0; + for (aij = cut->ptr; aij != NULL; aij = aij->next) + { xassert(1 <= aij->j && aij->j <= T->n); + len++, ind[len] = aij->j, val[len] = aij->val; + temp += aij->val * aij->val; + } + if (temp < DBL_EPSILON * DBL_EPSILON) temp = DBL_EPSILON; + /* transform the cut to express it only through non-basic + (auxiliary and structural) variables */ + len = glp_transform_row(T->mip, len, ind, val); + /* determine change in the cut value and in the objective + value for the adjacent basis by simulating one step of the + dual simplex */ + ret = _glp_analyze_row(T->mip, len, ind, val, cut->type, + cut->rhs, 1e-9, NULL, NULL, NULL, NULL, &dy, &dz); + /* determine normalized residual and lower bound to objective + degradation */ + if (ret == 0) + { info[k].eff = fabs(dy) / sqrt(temp); + /* if some reduced costs violates (slightly) their zero + bounds (i.e. have wrong signs) due to round-off errors, + dz also may have wrong sign being close to zero */ + if (T->mip->dir == GLP_MIN) + { if (dz < 0.0) dz = 0.0; + info[k].deg = + dz; + } + else /* GLP_MAX */ + { if (dz > 0.0) dz = 0.0; + info[k].deg = - dz; + } + } + else if (ret == 1) + { /* the constraint is not violated at the current point */ + info[k].eff = info[k].deg = 0.0; + } + else if (ret == 2) + { /* no dual feasible adjacent basis exists */ + info[k].eff = 1.0; + info[k].deg = DBL_MAX; + } + else + xassert(ret != ret); + /* if the degradation is too small, just ignore it */ + if (info[k].deg < 0.01) info[k].deg = 0.0; + } + /* sort the list of cuts by decreasing objective degradation and + then by decreasing efficacy */ + qsort(&info[1], pool->size, sizeof(struct info), fcmp); + /* only first (most efficient) max_cuts in the list are qualified + as candidates to be added to the current subproblem */ + max_cuts = (T->curr->level == 0 ? 90 : 10); + if (max_cuts > pool->size) max_cuts = pool->size; + /* add cuts to the current subproblem */ +#if 0 + xprintf("*** adding cuts ***\n"); +#endif + for (k = 1; k <= max_cuts; k++) + { int i, len; + /* if this cut seems to be inefficient, skip it */ + if (info[k].deg < 0.01 && info[k].eff < 0.01) continue; + /* if the angle between this cut and every other cut included + in the current subproblem is small, skip this cut */ + for (kk = 1; kk < k; kk++) + { if (info[kk].flag) + { if (parallel(info[k].cut, info[kk].cut, work) > 0.90) + break; + } + } + if (kk < k) continue; + /* add this cut to the current subproblem */ +#if 0 + xprintf("eff = %g; deg = %g\n", info[k].eff, info[k].deg); +#endif + cut = info[k].cut, info[k].flag = 1; + i = glp_add_rows(T->mip, 1); + if (cut->name != NULL) + glp_set_row_name(T->mip, i, cut->name); + xassert(T->mip->row[i]->origin == GLP_RF_CUT); + T->mip->row[i]->klass = cut->klass; + len = 0; + for (aij = cut->ptr; aij != NULL; aij = aij->next) + len++, ind[len] = aij->j, val[len] = aij->val; + glp_set_mat_row(T->mip, i, len, ind, val); + xassert(cut->type == GLP_LO || cut->type == GLP_UP); + glp_set_row_bnds(T->mip, i, cut->type, cut->rhs, cut->rhs); + } + /* free working arrays */ + xfree(info); + xfree(ind); + xfree(val); + xfree(work); + return; +} + +#if 0 +/*********************************************************************** +* Given a cut a * x >= b (<= b) the routine efficacy computes the cut +* efficacy as follows: +* +* eff = d * (a * x~ - b) / ||a||, +* +* where d is -1 (in case of '>= b') or +1 (in case of '<= b'), x~ is +* the vector of values of structural variables in optimal solution to +* LP relaxation of the current subproblem, ||a|| is the Euclidean norm +* of the vector of cut coefficients. +* +* If the cut is violated at point x~, the efficacy eff is positive, +* and its value is the Euclidean distance between x~ and the cut plane +* a * x = b in the space of structural variables. +* +* Following geometrical intuition, it is quite natural to consider +* this distance as a first-order measure of the expected efficacy of +* the cut: the larger the distance the better the cut [1]. */ + +static double efficacy(glp_tree *T, IOSCUT *cut) +{ glp_prob *mip = T->mip; + IOSAIJ *aij; + double s = 0.0, t = 0.0, temp; + for (aij = cut->ptr; aij != NULL; aij = aij->next) + { xassert(1 <= aij->j && aij->j <= mip->n); + s += aij->val * mip->col[aij->j]->prim; + t += aij->val * aij->val; + } + temp = sqrt(t); + if (temp < DBL_EPSILON) temp = DBL_EPSILON; + if (cut->type == GLP_LO) + temp = (s >= cut->rhs ? 0.0 : (cut->rhs - s) / temp); + else if (cut->type == GLP_UP) + temp = (s <= cut->rhs ? 0.0 : (s - cut->rhs) / temp); + else + xassert(cut != cut); + return temp; +} +#endif + +/*********************************************************************** +* Given two cuts a1 * x >= b1 (<= b1) and a2 * x >= b2 (<= b2) the +* routine parallel computes the cosine of angle between the cut planes +* a1 * x = b1 and a2 * x = b2 (which is the acute angle between two +* normals to these planes) in the space of structural variables as +* follows: +* +* cos phi = (a1' * a2) / (||a1|| * ||a2||), +* +* where (a1' * a2) is a dot product of vectors of cut coefficients, +* ||a1|| and ||a2|| are Euclidean norms of vectors a1 and a2. +* +* Note that requirement cos phi = 0 forces the cuts to be orthogonal, +* i.e. with disjoint support, while requirement cos phi <= 0.999 means +* only avoiding duplicate (parallel) cuts [1]. */ + +static double parallel(IOSCUT *a, IOSCUT *b, double work[]) +{ IOSAIJ *aij; + double s = 0.0, sa = 0.0, sb = 0.0, temp; + for (aij = a->ptr; aij != NULL; aij = aij->next) + { work[aij->j] = aij->val; + sa += aij->val * aij->val; + } + for (aij = b->ptr; aij != NULL; aij = aij->next) + { s += work[aij->j] * aij->val; + sb += aij->val * aij->val; + } + for (aij = a->ptr; aij != NULL; aij = aij->next) + work[aij->j] = 0.0; + temp = sqrt(sa) * sqrt(sb); + if (temp < DBL_EPSILON * DBL_EPSILON) temp = DBL_EPSILON; + return s / temp; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpios12.c b/resources/3rdparty/glpk-4.53/src/glpios12.c new file mode 100644 index 000000000..d5cf302a8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpios12.c @@ -0,0 +1,177 @@ +/* glpios12.c (node selection heuristics) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpios.h" + +/*********************************************************************** +* NAME +* +* ios_choose_node - select subproblem to continue the search +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_choose_node(glp_tree *T); +* +* DESCRIPTION +* +* The routine ios_choose_node selects a subproblem from the active +* list to continue the search. The choice depends on the backtracking +* technique option. +* +* RETURNS +* +* The routine ios_choose_node return the reference number of the +* subproblem selected. */ + +static int most_feas(glp_tree *T); +static int best_proj(glp_tree *T); +static int best_node(glp_tree *T); + +int ios_choose_node(glp_tree *T) +{ int p; + if (T->parm->bt_tech == GLP_BT_DFS) + { /* depth first search */ + xassert(T->tail != NULL); + p = T->tail->p; + } + else if (T->parm->bt_tech == GLP_BT_BFS) + { /* breadth first search */ + xassert(T->head != NULL); + p = T->head->p; + } + else if (T->parm->bt_tech == GLP_BT_BLB) + { /* select node with best local bound */ + p = best_node(T); + } + else if (T->parm->bt_tech == GLP_BT_BPH) + { if (T->mip->mip_stat == GLP_UNDEF) + { /* "most integer feasible" subproblem */ + p = most_feas(T); + } + else + { /* best projection heuristic */ + p = best_proj(T); + } + } + else + xassert(T != T); + return p; +} + +static int most_feas(glp_tree *T) +{ /* select subproblem whose parent has minimal sum of integer + infeasibilities */ + IOSNPD *node; + int p; + double best; + p = 0, best = DBL_MAX; + for (node = T->head; node != NULL; node = node->next) + { xassert(node->up != NULL); + if (best > node->up->ii_sum) + p = node->p, best = node->up->ii_sum; + } + return p; +} + +static int best_proj(glp_tree *T) +{ /* select subproblem using the best projection heuristic */ + IOSNPD *root, *node; + int p; + double best, deg, obj; + /* the global bound must exist */ + xassert(T->mip->mip_stat == GLP_FEAS); + /* obtain pointer to the root node, which must exist */ + root = T->slot[1].node; + xassert(root != NULL); + /* deg estimates degradation of the objective function per unit + of the sum of integer infeasibilities */ + xassert(root->ii_sum > 0.0); + deg = (T->mip->mip_obj - root->bound) / root->ii_sum; + /* nothing has been selected so far */ + p = 0, best = DBL_MAX; + /* walk through the list of active subproblems */ + for (node = T->head; node != NULL; node = node->next) + { xassert(node->up != NULL); + /* obj estimates optimal objective value if the sum of integer + infeasibilities were zero */ + obj = node->up->bound + deg * node->up->ii_sum; + if (T->mip->dir == GLP_MAX) obj = - obj; + /* select the subproblem which has the best estimated optimal + objective value */ + if (best > obj) p = node->p, best = obj; + } + return p; +} + +static int best_node(glp_tree *T) +{ /* select subproblem with best local bound */ + IOSNPD *node, *best = NULL; + double bound, eps; + switch (T->mip->dir) + { case GLP_MIN: + bound = +DBL_MAX; + for (node = T->head; node != NULL; node = node->next) + if (bound > node->bound) bound = node->bound; + xassert(bound != +DBL_MAX); + eps = 1e-10 * (1.0 + fabs(bound)); + for (node = T->head; node != NULL; node = node->next) + { if (node->bound <= bound + eps) + { xassert(node->up != NULL); + if (best == NULL || +#if 1 + best->up->ii_sum > node->up->ii_sum) best = node; +#else + best->lp_obj > node->lp_obj) best = node; +#endif + } + } + break; + case GLP_MAX: + bound = -DBL_MAX; + for (node = T->head; node != NULL; node = node->next) + if (bound < node->bound) bound = node->bound; + xassert(bound != -DBL_MAX); + eps = 1e-10 * (1.0 + fabs(bound)); + for (node = T->head; node != NULL; node = node->next) + { if (node->bound >= bound - eps) + { xassert(node->up != NULL); + if (best == NULL || +#if 1 + best->up->ii_sum > node->up->ii_sum) best = node; +#else + best->lp_obj < node->lp_obj) best = node; +#endif + } + } + break; + default: + xassert(T != T); + } + xassert(best != NULL); + return best->p; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpipm.c b/resources/3rdparty/glpk-4.53/src/glpipm.c new file mode 100644 index 000000000..2b3a81762 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpipm.c @@ -0,0 +1,1144 @@ +/* glpipm.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpipm.h" +#include "glpmat.h" + +#define ITER_MAX 100 +/* maximal number of iterations */ + +struct csa +{ /* common storage area */ + /*--------------------------------------------------------------*/ + /* LP data */ + int m; + /* number of rows (equality constraints) */ + int n; + /* number of columns (structural variables) */ + int *A_ptr; /* int A_ptr[1+m+1]; */ + int *A_ind; /* int A_ind[A_ptr[m+1]]; */ + double *A_val; /* double A_val[A_ptr[m+1]]; */ + /* mxn-matrix A in storage-by-rows format */ + double *b; /* double b[1+m]; */ + /* m-vector b of right-hand sides */ + double *c; /* double c[1+n]; */ + /* n-vector c of objective coefficients; c[0] is constant term of + the objective function */ + /*--------------------------------------------------------------*/ + /* LP solution */ + double *x; /* double x[1+n]; */ + double *y; /* double y[1+m]; */ + double *z; /* double z[1+n]; */ + /* current point in primal-dual space; the best point on exit */ + /*--------------------------------------------------------------*/ + /* control parameters */ + const glp_iptcp *parm; + /*--------------------------------------------------------------*/ + /* working arrays and variables */ + double *D; /* double D[1+n]; */ + /* diagonal nxn-matrix D = X*inv(Z), where X = diag(x[j]) and + Z = diag(z[j]) */ + int *P; /* int P[1+m+m]; */ + /* permutation mxm-matrix P used to minimize fill-in in Cholesky + factorization */ + int *S_ptr; /* int S_ptr[1+m+1]; */ + int *S_ind; /* int S_ind[S_ptr[m+1]]; */ + double *S_val; /* double S_val[S_ptr[m+1]]; */ + double *S_diag; /* double S_diag[1+m]; */ + /* symmetric mxm-matrix S = P*A*D*A'*P' whose upper triangular + part without diagonal elements is stored in S_ptr, S_ind, and + S_val in storage-by-rows format, diagonal elements are stored + in S_diag */ + int *U_ptr; /* int U_ptr[1+m+1]; */ + int *U_ind; /* int U_ind[U_ptr[m+1]]; */ + double *U_val; /* double U_val[U_ptr[m+1]]; */ + double *U_diag; /* double U_diag[1+m]; */ + /* upper triangular mxm-matrix U defining Cholesky factorization + S = U'*U; its non-diagonal elements are stored in U_ptr, U_ind, + U_val in storage-by-rows format, diagonal elements are stored + in U_diag */ + int iter; + /* iteration number (0, 1, 2, ...); iter = 0 corresponds to the + initial point */ + double obj; + /* current value of the objective function */ + double rpi; + /* relative primal infeasibility rpi = ||A*x-b||/(1+||b||) */ + double rdi; + /* relative dual infeasibility rdi = ||A'*y+z-c||/(1+||c||) */ + double gap; + /* primal-dual gap = |c'*x-b'*y|/(1+|c'*x|) which is a relative + difference between primal and dual objective functions */ + double phi; + /* merit function phi = ||A*x-b||/max(1,||b||) + + + ||A'*y+z-c||/max(1,||c||) + + + |c'*x-b'*y|/max(1,||b||,||c||) */ + double mu; + /* duality measure mu = x'*z/n (used as barrier parameter) */ + double rmu; + /* rmu = max(||A*x-b||,||A'*y+z-c||)/mu */ + double rmu0; + /* the initial value of rmu on iteration 0 */ + double *phi_min; /* double phi_min[1+ITER_MAX]; */ + /* phi_min[k] = min(phi[k]), where phi[k] is the value of phi on + k-th iteration, 0 <= k <= iter */ + int best_iter; + /* iteration number, on which the value of phi reached its best + (minimal) value */ + double *best_x; /* double best_x[1+n]; */ + double *best_y; /* double best_y[1+m]; */ + double *best_z; /* double best_z[1+n]; */ + /* best point (in the sense of the merit function phi) which has + been reached on iteration iter_best */ + double best_obj; + /* objective value at the best point */ + double *dx_aff; /* double dx_aff[1+n]; */ + double *dy_aff; /* double dy_aff[1+m]; */ + double *dz_aff; /* double dz_aff[1+n]; */ + /* affine scaling direction */ + double alfa_aff_p, alfa_aff_d; + /* maximal primal and dual stepsizes in affine scaling direction, + on which x and z are still non-negative */ + double mu_aff; + /* duality measure mu_aff = x_aff'*z_aff/n in the boundary point + x_aff' = x+alfa_aff_p*dx_aff, z_aff' = z+alfa_aff_d*dz_aff */ + double sigma; + /* Mehrotra's heuristic parameter (0 <= sigma <= 1) */ + double *dx_cc; /* double dx_cc[1+n]; */ + double *dy_cc; /* double dy_cc[1+m]; */ + double *dz_cc; /* double dz_cc[1+n]; */ + /* centering corrector direction */ + double *dx; /* double dx[1+n]; */ + double *dy; /* double dy[1+m]; */ + double *dz; /* double dz[1+n]; */ + /* final combined direction dx = dx_aff+dx_cc, dy = dy_aff+dy_cc, + dz = dz_aff+dz_cc */ + double alfa_max_p; + double alfa_max_d; + /* maximal primal and dual stepsizes in combined direction, on + which x and z are still non-negative */ +}; + +/*********************************************************************** +* initialize - allocate and initialize common storage area +* +* This routine allocates and initializes the common storage area (CSA) +* used by interior-point method routines. */ + +static void initialize(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + int i; + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Matrix A has %d non-zeros\n", csa->A_ptr[m+1]-1); + csa->D = xcalloc(1+n, sizeof(double)); + /* P := I */ + csa->P = xcalloc(1+m+m, sizeof(int)); + for (i = 1; i <= m; i++) csa->P[i] = csa->P[m+i] = i; + /* S := A*A', symbolically */ + csa->S_ptr = xcalloc(1+m+1, sizeof(int)); + csa->S_ind = adat_symbolic(m, n, csa->P, csa->A_ptr, csa->A_ind, + csa->S_ptr); + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Matrix S = A*A' has %d non-zeros (upper triangle)\n", + csa->S_ptr[m+1]-1 + m); + /* determine P using specified ordering algorithm */ + if (csa->parm->ord_alg == GLP_ORD_NONE) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Original ordering is being used\n"); + for (i = 1; i <= m; i++) + csa->P[i] = csa->P[m+i] = i; + } + else if (csa->parm->ord_alg == GLP_ORD_QMD) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Minimum degree ordering (QMD)...\n"); + min_degree(m, csa->S_ptr, csa->S_ind, csa->P); + } + else if (csa->parm->ord_alg == GLP_ORD_AMD) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Approximate minimum degree ordering (AMD)...\n"); + amd_order1(m, csa->S_ptr, csa->S_ind, csa->P); + } + else if (csa->parm->ord_alg == GLP_ORD_SYMAMD) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Approximate minimum degree ordering (SYMAMD)...\n") + ; + symamd_ord(m, csa->S_ptr, csa->S_ind, csa->P); + } + else + xassert(csa != csa); + /* S := P*A*A'*P', symbolically */ + xfree(csa->S_ind); + csa->S_ind = adat_symbolic(m, n, csa->P, csa->A_ptr, csa->A_ind, + csa->S_ptr); + csa->S_val = xcalloc(csa->S_ptr[m+1], sizeof(double)); + csa->S_diag = xcalloc(1+m, sizeof(double)); + /* compute Cholesky factorization S = U'*U, symbolically */ + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Computing Cholesky factorization S = L*L'...\n"); + csa->U_ptr = xcalloc(1+m+1, sizeof(int)); + csa->U_ind = chol_symbolic(m, csa->S_ptr, csa->S_ind, csa->U_ptr); + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Matrix L has %d non-zeros\n", csa->U_ptr[m+1]-1 + m); + csa->U_val = xcalloc(csa->U_ptr[m+1], sizeof(double)); + csa->U_diag = xcalloc(1+m, sizeof(double)); + csa->iter = 0; + csa->obj = 0.0; + csa->rpi = 0.0; + csa->rdi = 0.0; + csa->gap = 0.0; + csa->phi = 0.0; + csa->mu = 0.0; + csa->rmu = 0.0; + csa->rmu0 = 0.0; + csa->phi_min = xcalloc(1+ITER_MAX, sizeof(double)); + csa->best_iter = 0; + csa->best_x = xcalloc(1+n, sizeof(double)); + csa->best_y = xcalloc(1+m, sizeof(double)); + csa->best_z = xcalloc(1+n, sizeof(double)); + csa->best_obj = 0.0; + csa->dx_aff = xcalloc(1+n, sizeof(double)); + csa->dy_aff = xcalloc(1+m, sizeof(double)); + csa->dz_aff = xcalloc(1+n, sizeof(double)); + csa->alfa_aff_p = 0.0; + csa->alfa_aff_d = 0.0; + csa->mu_aff = 0.0; + csa->sigma = 0.0; + csa->dx_cc = xcalloc(1+n, sizeof(double)); + csa->dy_cc = xcalloc(1+m, sizeof(double)); + csa->dz_cc = xcalloc(1+n, sizeof(double)); + csa->dx = csa->dx_aff; + csa->dy = csa->dy_aff; + csa->dz = csa->dz_aff; + csa->alfa_max_p = 0.0; + csa->alfa_max_d = 0.0; + return; +} + +/*********************************************************************** +* A_by_vec - compute y = A*x +* +* This routine computes matrix-vector product y = A*x, where A is the +* constraint matrix. */ + +static void A_by_vec(struct csa *csa, double x[], double y[]) +{ /* compute y = A*x */ + int m = csa->m; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int i, t, beg, end; + double temp; + for (i = 1; i <= m; i++) + { temp = 0.0; + beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) temp += A_val[t] * x[A_ind[t]]; + y[i] = temp; + } + return; +} + +/*********************************************************************** +* AT_by_vec - compute y = A'*x +* +* This routine computes matrix-vector product y = A'*x, where A' is a +* matrix transposed to the constraint matrix A. */ + +static void AT_by_vec(struct csa *csa, double x[], double y[]) +{ /* compute y = A'*x, where A' is transposed to A */ + int m = csa->m; + int n = csa->n; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int i, j, t, beg, end; + double temp; + for (j = 1; j <= n; j++) y[j] = 0.0; + for (i = 1; i <= m; i++) + { temp = x[i]; + if (temp == 0.0) continue; + beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) y[A_ind[t]] += A_val[t] * temp; + } + return; +} + +/*********************************************************************** +* decomp_NE - numeric factorization of matrix S = P*A*D*A'*P' +* +* This routine implements numeric phase of Cholesky factorization of +* the matrix S = P*A*D*A'*P', which is a permuted matrix of the normal +* equation system. Matrix D is assumed to be already computed. */ + +static void decomp_NE(struct csa *csa) +{ adat_numeric(csa->m, csa->n, csa->P, csa->A_ptr, csa->A_ind, + csa->A_val, csa->D, csa->S_ptr, csa->S_ind, csa->S_val, + csa->S_diag); + chol_numeric(csa->m, csa->S_ptr, csa->S_ind, csa->S_val, + csa->S_diag, csa->U_ptr, csa->U_ind, csa->U_val, csa->U_diag); + return; +} + +/*********************************************************************** +* solve_NE - solve normal equation system +* +* This routine solves the normal equation system: +* +* A*D*A'*y = h. +* +* It is assumed that the matrix A*D*A' has been previously factorized +* by the routine decomp_NE. +* +* On entry the array y contains the vector of right-hand sides h. On +* exit this array contains the computed vector of unknowns y. +* +* Once the vector y has been computed the routine checks for numeric +* stability. If the residual vector: +* +* r = A*D*A'*y - h +* +* is relatively small, the routine returns zero, otherwise non-zero is +* returned. */ + +static int solve_NE(struct csa *csa, double y[]) +{ int m = csa->m; + int n = csa->n; + int *P = csa->P; + int i, j, ret = 0; + double *h, *r, *w; + /* save vector of right-hand sides h */ + h = xcalloc(1+m, sizeof(double)); + for (i = 1; i <= m; i++) h[i] = y[i]; + /* solve normal equation system (A*D*A')*y = h */ + /* since S = P*A*D*A'*P' = U'*U, then A*D*A' = P'*U'*U*P, so we + have inv(A*D*A') = P'*inv(U)*inv(U')*P */ + /* w := P*h */ + w = xcalloc(1+m, sizeof(double)); + for (i = 1; i <= m; i++) w[i] = y[P[i]]; + /* w := inv(U')*w */ + ut_solve(m, csa->U_ptr, csa->U_ind, csa->U_val, csa->U_diag, w); + /* w := inv(U)*w */ + u_solve(m, csa->U_ptr, csa->U_ind, csa->U_val, csa->U_diag, w); + /* y := P'*w */ + for (i = 1; i <= m; i++) y[i] = w[P[m+i]]; + xfree(w); + /* compute residual vector r = A*D*A'*y - h */ + r = xcalloc(1+m, sizeof(double)); + /* w := A'*y */ + w = xcalloc(1+n, sizeof(double)); + AT_by_vec(csa, y, w); + /* w := D*w */ + for (j = 1; j <= n; j++) w[j] *= csa->D[j]; + /* r := A*w */ + A_by_vec(csa, w, r); + xfree(w); + /* r := r - h */ + for (i = 1; i <= m; i++) r[i] -= h[i]; + /* check for numeric stability */ + for (i = 1; i <= m; i++) + { if (fabs(r[i]) / (1.0 + fabs(h[i])) > 1e-4) + { ret = 1; + break; + } + } + xfree(h); + xfree(r); + return ret; +} + +/*********************************************************************** +* solve_NS - solve Newtonian system +* +* This routine solves the Newtonian system: +* +* A*dx = p +* +* A'*dy + dz = q +* +* Z*dx + X*dz = r +* +* where X = diag(x[j]), Z = diag(z[j]), by reducing it to the normal +* equation system: +* +* (A*inv(Z)*X*A')*dy = A*inv(Z)*(X*q-r)+p +* +* (it is assumed that the matrix A*inv(Z)*X*A' has been factorized by +* the routine decomp_NE). +* +* Once vector dy has been computed the routine computes vectors dx and +* dz as follows: +* +* dx = inv(Z)*(X*(A'*dy-q)+r) +* +* dz = inv(X)*(r-Z*dx) +* +* The routine solve_NS returns the same code which was reported by the +* routine solve_NE (see above). */ + +static int solve_NS(struct csa *csa, double p[], double q[], double r[], + double dx[], double dy[], double dz[]) +{ int m = csa->m; + int n = csa->n; + double *x = csa->x; + double *z = csa->z; + int i, j, ret; + double *w = dx; + /* compute the vector of right-hand sides A*inv(Z)*(X*q-r)+p for + the normal equation system */ + for (j = 1; j <= n; j++) + w[j] = (x[j] * q[j] - r[j]) / z[j]; + A_by_vec(csa, w, dy); + for (i = 1; i <= m; i++) dy[i] += p[i]; + /* solve the normal equation system to compute vector dy */ + ret = solve_NE(csa, dy); + /* compute vectors dx and dz */ + AT_by_vec(csa, dy, dx); + for (j = 1; j <= n; j++) + { dx[j] = (x[j] * (dx[j] - q[j]) + r[j]) / z[j]; + dz[j] = (r[j] - z[j] * dx[j]) / x[j]; + } + return ret; +} + +/*********************************************************************** +* initial_point - choose initial point using Mehrotra's heuristic +* +* This routine chooses a starting point using a heuristic proposed in +* the paper: +* +* S. Mehrotra. On the implementation of a primal-dual interior point +* method. SIAM J. on Optim., 2(4), pp. 575-601, 1992. +* +* The starting point x in the primal space is chosen as a solution of +* the following least squares problem: +* +* minimize ||x|| +* +* subject to A*x = b +* +* which can be computed explicitly as follows: +* +* x = A'*inv(A*A')*b +* +* Similarly, the starting point (y, z) in the dual space is chosen as +* a solution of the following least squares problem: +* +* minimize ||z|| +* +* subject to A'*y + z = c +* +* which can be computed explicitly as follows: +* +* y = inv(A*A')*A*c +* +* z = c - A'*y +* +* However, some components of the vectors x and z may be non-positive +* or close to zero, so the routine uses a Mehrotra's heuristic to find +* a more appropriate starting point. */ + +static void initial_point(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + double *b = csa->b; + double *c = csa->c; + double *x = csa->x; + double *y = csa->y; + double *z = csa->z; + double *D = csa->D; + int i, j; + double dp, dd, ex, ez, xz; + /* factorize A*A' */ + for (j = 1; j <= n; j++) D[j] = 1.0; + decomp_NE(csa); + /* x~ = A'*inv(A*A')*b */ + for (i = 1; i <= m; i++) y[i] = b[i]; + solve_NE(csa, y); + AT_by_vec(csa, y, x); + /* y~ = inv(A*A')*A*c */ + A_by_vec(csa, c, y); + solve_NE(csa, y); + /* z~ = c - A'*y~ */ + AT_by_vec(csa, y,z); + for (j = 1; j <= n; j++) z[j] = c[j] - z[j]; + /* use Mehrotra's heuristic in order to choose more appropriate + starting point with positive components of vectors x and z */ + dp = dd = 0.0; + for (j = 1; j <= n; j++) + { if (dp < -1.5 * x[j]) dp = -1.5 * x[j]; + if (dd < -1.5 * z[j]) dd = -1.5 * z[j]; + } + /* note that b = 0 involves x = 0, and c = 0 involves y = 0 and + z = 0, so we need to be careful */ + if (dp == 0.0) dp = 1.5; + if (dd == 0.0) dd = 1.5; + ex = ez = xz = 0.0; + for (j = 1; j <= n; j++) + { ex += (x[j] + dp); + ez += (z[j] + dd); + xz += (x[j] + dp) * (z[j] + dd); + } + dp += 0.5 * (xz / ez); + dd += 0.5 * (xz / ex); + for (j = 1; j <= n; j++) + { x[j] += dp; + z[j] += dd; + xassert(x[j] > 0.0 && z[j] > 0.0); + } + return; +} + +/*********************************************************************** +* basic_info - perform basic computations at the current point +* +* This routine computes the following quantities at the current point: +* +* 1) value of the objective function: +* +* F = c'*x + c[0] +* +* 2) relative primal infeasibility: +* +* rpi = ||A*x-b|| / (1+||b||) +* +* 3) relative dual infeasibility: +* +* rdi = ||A'*y+z-c|| / (1+||c||) +* +* 4) primal-dual gap (relative difference between the primal and the +* dual objective function values): +* +* gap = |c'*x-b'*y| / (1+|c'*x|) +* +* 5) merit function: +* +* phi = ||A*x-b|| / max(1,||b||) + ||A'*y+z-c|| / max(1,||c||) + +* +* + |c'*x-b'*y| / max(1,||b||,||c||) +* +* 6) duality measure: +* +* mu = x'*z / n +* +* 7) the ratio of infeasibility to mu: +* +* rmu = max(||A*x-b||,||A'*y+z-c||) / mu +* +* where ||*|| denotes euclidian norm, *' denotes transposition. */ + +static void basic_info(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + double *b = csa->b; + double *c = csa->c; + double *x = csa->x; + double *y = csa->y; + double *z = csa->z; + int i, j; + double norm1, bnorm, norm2, cnorm, cx, by, *work, temp; + /* compute value of the objective function */ + temp = c[0]; + for (j = 1; j <= n; j++) temp += c[j] * x[j]; + csa->obj = temp; + /* norm1 = ||A*x-b|| */ + work = xcalloc(1+m, sizeof(double)); + A_by_vec(csa, x, work); + norm1 = 0.0; + for (i = 1; i <= m; i++) + norm1 += (work[i] - b[i]) * (work[i] - b[i]); + norm1 = sqrt(norm1); + xfree(work); + /* bnorm = ||b|| */ + bnorm = 0.0; + for (i = 1; i <= m; i++) bnorm += b[i] * b[i]; + bnorm = sqrt(bnorm); + /* compute relative primal infeasibility */ + csa->rpi = norm1 / (1.0 + bnorm); + /* norm2 = ||A'*y+z-c|| */ + work = xcalloc(1+n, sizeof(double)); + AT_by_vec(csa, y, work); + norm2 = 0.0; + for (j = 1; j <= n; j++) + norm2 += (work[j] + z[j] - c[j]) * (work[j] + z[j] - c[j]); + norm2 = sqrt(norm2); + xfree(work); + /* cnorm = ||c|| */ + cnorm = 0.0; + for (j = 1; j <= n; j++) cnorm += c[j] * c[j]; + cnorm = sqrt(cnorm); + /* compute relative dual infeasibility */ + csa->rdi = norm2 / (1.0 + cnorm); + /* by = b'*y */ + by = 0.0; + for (i = 1; i <= m; i++) by += b[i] * y[i]; + /* cx = c'*x */ + cx = 0.0; + for (j = 1; j <= n; j++) cx += c[j] * x[j]; + /* compute primal-dual gap */ + csa->gap = fabs(cx - by) / (1.0 + fabs(cx)); + /* compute merit function */ + csa->phi = 0.0; + csa->phi += norm1 / (bnorm > 1.0 ? bnorm : 1.0); + csa->phi += norm2 / (cnorm > 1.0 ? cnorm : 1.0); + temp = 1.0; + if (temp < bnorm) temp = bnorm; + if (temp < cnorm) temp = cnorm; + csa->phi += fabs(cx - by) / temp; + /* compute duality measure */ + temp = 0.0; + for (j = 1; j <= n; j++) temp += x[j] * z[j]; + csa->mu = temp / (double)n; + /* compute the ratio of infeasibility to mu */ + csa->rmu = (norm1 > norm2 ? norm1 : norm2) / csa->mu; + return; +} + +/*********************************************************************** +* make_step - compute next point using Mehrotra's technique +* +* This routine computes the next point using the predictor-corrector +* technique proposed in the paper: +* +* S. Mehrotra. On the implementation of a primal-dual interior point +* method. SIAM J. on Optim., 2(4), pp. 575-601, 1992. +* +* At first, the routine computes so called affine scaling (predictor) +* direction (dx_aff,dy_aff,dz_aff) which is a solution of the system: +* +* A*dx_aff = b - A*x +* +* A'*dy_aff + dz_aff = c - A'*y - z +* +* Z*dx_aff + X*dz_aff = - X*Z*e +* +* where (x,y,z) is the current point, X = diag(x[j]), Z = diag(z[j]), +* e = (1,...,1)'. +* +* Then, the routine computes the centering parameter sigma, using the +* following Mehrotra's heuristic: +* +* alfa_aff_p = inf{0 <= alfa <= 1 | x+alfa*dx_aff >= 0} +* +* alfa_aff_d = inf{0 <= alfa <= 1 | z+alfa*dz_aff >= 0} +* +* mu_aff = (x+alfa_aff_p*dx_aff)'*(z+alfa_aff_d*dz_aff)/n +* +* sigma = (mu_aff/mu)^3 +* +* where alfa_aff_p is the maximal stepsize along the affine scaling +* direction in the primal space, alfa_aff_d is the maximal stepsize +* along the same direction in the dual space. +* +* After determining sigma the routine computes so called centering +* (corrector) direction (dx_cc,dy_cc,dz_cc) which is the solution of +* the system: +* +* A*dx_cc = 0 +* +* A'*dy_cc + dz_cc = 0 +* +* Z*dx_cc + X*dz_cc = sigma*mu*e - X*Z*e +* +* Finally, the routine computes the combined direction +* +* (dx,dy,dz) = (dx_aff,dy_aff,dz_aff) + (dx_cc,dy_cc,dz_cc) +* +* and determines maximal primal and dual stepsizes along the combined +* direction: +* +* alfa_max_p = inf{0 <= alfa <= 1 | x+alfa*dx >= 0} +* +* alfa_max_d = inf{0 <= alfa <= 1 | z+alfa*dz >= 0} +* +* In order to prevent the next point to be too close to the boundary +* of the positive ortant, the routine decreases maximal stepsizes: +* +* alfa_p = gamma_p * alfa_max_p +* +* alfa_d = gamma_d * alfa_max_d +* +* where gamma_p and gamma_d are scaling factors, and computes the next +* point: +* +* x_new = x + alfa_p * dx +* +* y_new = y + alfa_d * dy +* +* z_new = z + alfa_d * dz +* +* which becomes the current point on the next iteration. */ + +static int make_step(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + double *b = csa->b; + double *c = csa->c; + double *x = csa->x; + double *y = csa->y; + double *z = csa->z; + double *dx_aff = csa->dx_aff; + double *dy_aff = csa->dy_aff; + double *dz_aff = csa->dz_aff; + double *dx_cc = csa->dx_cc; + double *dy_cc = csa->dy_cc; + double *dz_cc = csa->dz_cc; + double *dx = csa->dx; + double *dy = csa->dy; + double *dz = csa->dz; + int i, j, ret = 0; + double temp, gamma_p, gamma_d, *p, *q, *r; + /* allocate working arrays */ + p = xcalloc(1+m, sizeof(double)); + q = xcalloc(1+n, sizeof(double)); + r = xcalloc(1+n, sizeof(double)); + /* p = b - A*x */ + A_by_vec(csa, x, p); + for (i = 1; i <= m; i++) p[i] = b[i] - p[i]; + /* q = c - A'*y - z */ + AT_by_vec(csa, y,q); + for (j = 1; j <= n; j++) q[j] = c[j] - q[j] - z[j]; + /* r = - X * Z * e */ + for (j = 1; j <= n; j++) r[j] = - x[j] * z[j]; + /* solve the first Newtonian system */ + if (solve_NS(csa, p, q, r, dx_aff, dy_aff, dz_aff)) + { ret = 1; + goto done; + } + /* alfa_aff_p = inf{0 <= alfa <= 1 | x + alfa*dx_aff >= 0} */ + /* alfa_aff_d = inf{0 <= alfa <= 1 | z + alfa*dz_aff >= 0} */ + csa->alfa_aff_p = csa->alfa_aff_d = 1.0; + for (j = 1; j <= n; j++) + { if (dx_aff[j] < 0.0) + { temp = - x[j] / dx_aff[j]; + if (csa->alfa_aff_p > temp) csa->alfa_aff_p = temp; + } + if (dz_aff[j] < 0.0) + { temp = - z[j] / dz_aff[j]; + if (csa->alfa_aff_d > temp) csa->alfa_aff_d = temp; + } + } + /* mu_aff = (x+alfa_aff_p*dx_aff)' * (z+alfa_aff_d*dz_aff) / n */ + temp = 0.0; + for (j = 1; j <= n; j++) + temp += (x[j] + csa->alfa_aff_p * dx_aff[j]) * + (z[j] + csa->alfa_aff_d * dz_aff[j]); + csa->mu_aff = temp / (double)n; + /* sigma = (mu_aff/mu)^3 */ + temp = csa->mu_aff / csa->mu; + csa->sigma = temp * temp * temp; + /* p = 0 */ + for (i = 1; i <= m; i++) p[i] = 0.0; + /* q = 0 */ + for (j = 1; j <= n; j++) q[j] = 0.0; + /* r = sigma * mu * e - X * Z * e */ + for (j = 1; j <= n; j++) + r[j] = csa->sigma * csa->mu - dx_aff[j] * dz_aff[j]; + /* solve the second Newtonian system with the same coefficients + but with altered right-hand sides */ + if (solve_NS(csa, p, q, r, dx_cc, dy_cc, dz_cc)) + { ret = 1; + goto done; + } + /* (dx,dy,dz) = (dx_aff,dy_aff,dz_aff) + (dx_cc,dy_cc,dz_cc) */ + for (j = 1; j <= n; j++) dx[j] = dx_aff[j] + dx_cc[j]; + for (i = 1; i <= m; i++) dy[i] = dy_aff[i] + dy_cc[i]; + for (j = 1; j <= n; j++) dz[j] = dz_aff[j] + dz_cc[j]; + /* alfa_max_p = inf{0 <= alfa <= 1 | x + alfa*dx >= 0} */ + /* alfa_max_d = inf{0 <= alfa <= 1 | z + alfa*dz >= 0} */ + csa->alfa_max_p = csa->alfa_max_d = 1.0; + for (j = 1; j <= n; j++) + { if (dx[j] < 0.0) + { temp = - x[j] / dx[j]; + if (csa->alfa_max_p > temp) csa->alfa_max_p = temp; + } + if (dz[j] < 0.0) + { temp = - z[j] / dz[j]; + if (csa->alfa_max_d > temp) csa->alfa_max_d = temp; + } + } + /* determine scale factors (not implemented yet) */ + gamma_p = 0.90; + gamma_d = 0.90; + /* compute the next point */ + for (j = 1; j <= n; j++) + { x[j] += gamma_p * csa->alfa_max_p * dx[j]; + xassert(x[j] > 0.0); + } + for (i = 1; i <= m; i++) + y[i] += gamma_d * csa->alfa_max_d * dy[i]; + for (j = 1; j <= n; j++) + { z[j] += gamma_d * csa->alfa_max_d * dz[j]; + xassert(z[j] > 0.0); + } +done: /* free working arrays */ + xfree(p); + xfree(q); + xfree(r); + return ret; +} + +/*********************************************************************** +* terminate - deallocate common storage area +* +* This routine frees all memory allocated to the common storage area +* used by interior-point method routines. */ + +static void terminate(struct csa *csa) +{ xfree(csa->D); + xfree(csa->P); + xfree(csa->S_ptr); + xfree(csa->S_ind); + xfree(csa->S_val); + xfree(csa->S_diag); + xfree(csa->U_ptr); + xfree(csa->U_ind); + xfree(csa->U_val); + xfree(csa->U_diag); + xfree(csa->phi_min); + xfree(csa->best_x); + xfree(csa->best_y); + xfree(csa->best_z); + xfree(csa->dx_aff); + xfree(csa->dy_aff); + xfree(csa->dz_aff); + xfree(csa->dx_cc); + xfree(csa->dy_cc); + xfree(csa->dz_cc); + return; +} + +/*********************************************************************** +* ipm_main - main interior-point method routine +* +* This is a main routine of the primal-dual interior-point method. +* +* The routine ipm_main returns one of the following codes: +* +* 0 - optimal solution found; +* 1 - problem has no feasible (primal or dual) solution; +* 2 - no convergence; +* 3 - iteration limit exceeded; +* 4 - numeric instability on solving Newtonian system. +* +* In case of non-zero return code the routine returns the best point, +* which has been reached during optimization. */ + +static int ipm_main(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + int i, j, status; + double temp; + /* choose initial point using Mehrotra's heuristic */ + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Guessing initial point...\n"); + initial_point(csa); + /* main loop starts here */ + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Optimization begins...\n"); + for (;;) + { /* perform basic computations at the current point */ + basic_info(csa); + /* save initial value of rmu */ + if (csa->iter == 0) csa->rmu0 = csa->rmu; + /* accumulate values of min(phi[k]) and save the best point */ + xassert(csa->iter <= ITER_MAX); + if (csa->iter == 0 || csa->phi_min[csa->iter-1] > csa->phi) + { csa->phi_min[csa->iter] = csa->phi; + csa->best_iter = csa->iter; + for (j = 1; j <= n; j++) csa->best_x[j] = csa->x[j]; + for (i = 1; i <= m; i++) csa->best_y[i] = csa->y[i]; + for (j = 1; j <= n; j++) csa->best_z[j] = csa->z[j]; + csa->best_obj = csa->obj; + } + else + csa->phi_min[csa->iter] = csa->phi_min[csa->iter-1]; + /* display information at the current point */ + if (csa->parm->msg_lev >= GLP_MSG_ON) + xprintf("%3d: obj = %17.9e; rpi = %8.1e; rdi = %8.1e; gap =" + " %8.1e\n", csa->iter, csa->obj, csa->rpi, csa->rdi, + csa->gap); + /* check if the current point is optimal */ + if (csa->rpi < 1e-8 && csa->rdi < 1e-8 && csa->gap < 1e-8) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("OPTIMAL SOLUTION FOUND\n"); + status = 0; + break; + } + /* check if the problem has no feasible solution */ + temp = 1e5 * csa->phi_min[csa->iter]; + if (temp < 1e-8) temp = 1e-8; + if (csa->phi >= temp) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("PROBLEM HAS NO FEASIBLE PRIMAL/DUAL SOLUTION\n") + ; + status = 1; + break; + } + /* check for very slow convergence or divergence */ + if (((csa->rpi >= 1e-8 || csa->rdi >= 1e-8) && csa->rmu / + csa->rmu0 >= 1e6) || + (csa->iter >= 30 && csa->phi_min[csa->iter] >= 0.5 * + csa->phi_min[csa->iter - 30])) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("NO CONVERGENCE; SEARCH TERMINATED\n"); + status = 2; + break; + } + /* check for maximal number of iterations */ + if (csa->iter == ITER_MAX) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); + status = 3; + break; + } + /* start the next iteration */ + csa->iter++; + /* factorize normal equation system */ + for (j = 1; j <= n; j++) csa->D[j] = csa->x[j] / csa->z[j]; + decomp_NE(csa); + /* compute the next point using Mehrotra's predictor-corrector + technique */ + if (make_step(csa)) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("NUMERIC INSTABILITY; SEARCH TERMINATED\n"); + status = 4; + break; + } + } + /* restore the best point */ + if (status != 0) + { for (j = 1; j <= n; j++) csa->x[j] = csa->best_x[j]; + for (i = 1; i <= m; i++) csa->y[i] = csa->best_y[i]; + for (j = 1; j <= n; j++) csa->z[j] = csa->best_z[j]; + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Best point %17.9e was reached on iteration %d\n", + csa->best_obj, csa->best_iter); + } + /* return to the calling program */ + return status; +} + +/*********************************************************************** +* NAME +* +* ipm_solve - core LP solver based on the interior-point method +* +* SYNOPSIS +* +* #include "glpipm.h" +* int ipm_solve(glp_prob *P, const glp_iptcp *parm); +* +* DESCRIPTION +* +* The routine ipm_solve is a core LP solver based on the primal-dual +* interior-point method. +* +* The routine assumes the following standard formulation of LP problem +* to be solved: +* +* minimize +* +* F = c[0] + c[1]*x[1] + c[2]*x[2] + ... + c[n]*x[n] +* +* subject to linear constraints +* +* a[1,1]*x[1] + a[1,2]*x[2] + ... + a[1,n]*x[n] = b[1] +* +* a[2,1]*x[1] + a[2,2]*x[2] + ... + a[2,n]*x[n] = b[2] +* +* . . . . . . +* +* a[m,1]*x[1] + a[m,2]*x[2] + ... + a[m,n]*x[n] = b[m] +* +* and non-negative variables +* +* x[1] >= 0, x[2] >= 0, ..., x[n] >= 0 +* +* where: +* F is the objective function; +* x[1], ..., x[n] are (structural) variables; +* c[0] is a constant term of the objective function; +* c[1], ..., c[n] are objective coefficients; +* a[1,1], ..., a[m,n] are constraint coefficients; +* b[1], ..., b[n] are right-hand sides. +* +* The solution is three vectors x, y, and z, which are stored by the +* routine in the arrays x, y, and z, respectively. These vectors +* correspond to the best primal-dual point found during optimization. +* They are approximate solution of the following system (which is the +* Karush-Kuhn-Tucker optimality conditions): +* +* A*x = b (primal feasibility condition) +* +* A'*y + z = c (dual feasibility condition) +* +* x'*z = 0 (primal-dual complementarity condition) +* +* x >= 0, z >= 0 (non-negativity condition) +* +* where: +* x[1], ..., x[n] are primal (structural) variables; +* y[1], ..., y[m] are dual variables (Lagrange multipliers) for +* equality constraints; +* z[1], ..., z[n] are dual variables (Lagrange multipliers) for +* non-negativity constraints. +* +* RETURNS +* +* 0 LP has been successfully solved. +* +* GLP_ENOCVG +* No convergence. +* +* GLP_EITLIM +* Iteration limit exceeded. +* +* GLP_EINSTAB +* Numeric instability on solving Newtonian system. +* +* In case of non-zero return code the routine returns the best point, +* which has been reached during optimization. */ + +int ipm_solve(glp_prob *P, const glp_iptcp *parm) +{ struct csa _dsa, *csa = &_dsa; + int m = P->m; + int n = P->n; + int nnz = P->nnz; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, j, loc, ret, *A_ind, *A_ptr; + double dir, *A_val, *b, *c, *x, *y, *z; + xassert(m > 0); + xassert(n > 0); + /* allocate working arrays */ + A_ptr = xcalloc(1+m+1, sizeof(int)); + A_ind = xcalloc(1+nnz, sizeof(int)); + A_val = xcalloc(1+nnz, sizeof(double)); + b = xcalloc(1+m, sizeof(double)); + c = xcalloc(1+n, sizeof(double)); + x = xcalloc(1+n, sizeof(double)); + y = xcalloc(1+m, sizeof(double)); + z = xcalloc(1+n, sizeof(double)); + /* prepare rows and constraint coefficients */ + loc = 1; + for (i = 1; i <= m; i++) + { row = P->row[i]; + xassert(row->type == GLP_FX); + b[i] = row->lb * row->rii; + A_ptr[i] = loc; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { A_ind[loc] = aij->col->j; + A_val[loc] = row->rii * aij->val * aij->col->sjj; + loc++; + } + } + A_ptr[m+1] = loc; + xassert(loc-1 == nnz); + /* prepare columns and objective coefficients */ + if (P->dir == GLP_MIN) + dir = +1.0; + else if (P->dir == GLP_MAX) + dir = -1.0; + else + xassert(P != P); + c[0] = dir * P->c0; + for (j = 1; j <= n; j++) + { col = P->col[j]; + xassert(col->type == GLP_LO && col->lb == 0.0); + c[j] = dir * col->coef * col->sjj; + } + /* allocate and initialize the common storage area */ + csa->m = m; + csa->n = n; + csa->A_ptr = A_ptr; + csa->A_ind = A_ind; + csa->A_val = A_val; + csa->b = b; + csa->c = c; + csa->x = x; + csa->y = y; + csa->z = z; + csa->parm = parm; + initialize(csa); + /* solve LP with the interior-point method */ + ret = ipm_main(csa); + /* deallocate the common storage area */ + terminate(csa); + /* determine solution status */ + if (ret == 0) + { /* optimal solution found */ + P->ipt_stat = GLP_OPT; + ret = 0; + } + else if (ret == 1) + { /* problem has no feasible (primal or dual) solution */ + P->ipt_stat = GLP_NOFEAS; + ret = 0; + } + else if (ret == 2) + { /* no convergence */ + P->ipt_stat = GLP_INFEAS; + ret = GLP_ENOCVG; + } + else if (ret == 3) + { /* iteration limit exceeded */ + P->ipt_stat = GLP_INFEAS; + ret = GLP_EITLIM; + } + else if (ret == 4) + { /* numeric instability on solving Newtonian system */ + P->ipt_stat = GLP_INFEAS; + ret = GLP_EINSTAB; + } + else + xassert(ret != ret); + /* store row solution components */ + for (i = 1; i <= m; i++) + { row = P->row[i]; + row->pval = row->lb; + row->dval = dir * y[i] * row->rii; + } + /* store column solution components */ + P->ipt_obj = P->c0; + for (j = 1; j <= n; j++) + { col = P->col[j]; + col->pval = x[j] * col->sjj; + col->dval = dir * z[j] / col->sjj; + P->ipt_obj += col->coef * col->pval; + } + /* free working arrays */ + xfree(A_ptr); + xfree(A_ind); + xfree(A_val); + xfree(b); + xfree(c); + xfree(x); + xfree(y); + xfree(z); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpipm.h b/resources/3rdparty/glpk-4.53/src/glpipm.h new file mode 100644 index 000000000..a5f94fec1 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpipm.h @@ -0,0 +1,36 @@ +/* glpipm.h (primal-dual interior-point method) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPIPM_H +#define GLPIPM_H + +#include "prob.h" + +#define ipm_solve _glp_ipm_solve +int ipm_solve(glp_prob *P, const glp_iptcp *parm); +/* core LP solver based on the interior-point method */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpk.h b/resources/3rdparty/glpk-4.53/src/glpk.h new file mode 100644 index 000000000..86b8b913b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpk.h @@ -0,0 +1,1076 @@ +/* glpk.h (GLPK API) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPK_H +#define GLPK_H + +#include <stdarg.h> +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* library version numbers: */ +#define GLP_MAJOR_VERSION 4 +#define GLP_MINOR_VERSION 53 + +typedef struct glp_prob glp_prob; +/* LP/MIP problem object */ + +/* optimization direction flag: */ +#define GLP_MIN 1 /* minimization */ +#define GLP_MAX 2 /* maximization */ + +/* kind of structural variable: */ +#define GLP_CV 1 /* continuous variable */ +#define GLP_IV 2 /* integer variable */ +#define GLP_BV 3 /* binary variable */ + +/* type of auxiliary/structural variable: */ +#define GLP_FR 1 /* free (unbounded) variable */ +#define GLP_LO 2 /* variable with lower bound */ +#define GLP_UP 3 /* variable with upper bound */ +#define GLP_DB 4 /* double-bounded variable */ +#define GLP_FX 5 /* fixed variable */ + +/* status of auxiliary/structural variable: */ +#define GLP_BS 1 /* basic variable */ +#define GLP_NL 2 /* non-basic variable on lower bound */ +#define GLP_NU 3 /* non-basic variable on upper bound */ +#define GLP_NF 4 /* non-basic free (unbounded) variable */ +#define GLP_NS 5 /* non-basic fixed variable */ + +/* scaling options: */ +#define GLP_SF_GM 0x01 /* perform geometric mean scaling */ +#define GLP_SF_EQ 0x10 /* perform equilibration scaling */ +#define GLP_SF_2N 0x20 /* round scale factors to power of two */ +#define GLP_SF_SKIP 0x40 /* skip if problem is well scaled */ +#define GLP_SF_AUTO 0x80 /* choose scaling options automatically */ + +/* solution indicator: */ +#define GLP_SOL 1 /* basic solution */ +#define GLP_IPT 2 /* interior-point solution */ +#define GLP_MIP 3 /* mixed integer solution */ + +/* solution status: */ +#define GLP_UNDEF 1 /* solution is undefined */ +#define GLP_FEAS 2 /* solution is feasible */ +#define GLP_INFEAS 3 /* solution is infeasible */ +#define GLP_NOFEAS 4 /* no feasible solution exists */ +#define GLP_OPT 5 /* solution is optimal */ +#define GLP_UNBND 6 /* solution is unbounded */ + +typedef struct +{ /* basis factorization control parameters */ + int msg_lev; /* (reserved) */ + int type; /* factorization type: */ +#define GLP_BF_FT 1 /* LUF + Forrest-Tomlin */ +#define GLP_BF_BG 2 /* LUF + Schur compl. + Bartels-Golub */ +#define GLP_BF_GR 3 /* LUF + Schur compl. + Givens rotation */ + int lu_size; /* luf.sv_size */ + double piv_tol; /* luf.piv_tol */ + int piv_lim; /* luf.piv_lim */ + int suhl; /* luf.suhl */ + double eps_tol; /* luf.eps_tol */ + double max_gro; /* luf.max_gro */ + int nfs_max; /* fhv.hh_max */ + double upd_tol; /* fhv.upd_tol */ + int nrs_max; /* lpf.n_max */ + int rs_size; /* lpf.v_size */ + double foo_bar[38]; /* (reserved) */ +} glp_bfcp; + +typedef struct +{ /* simplex method control parameters */ + int msg_lev; /* message level: */ +#define GLP_MSG_OFF 0 /* no output */ +#define GLP_MSG_ERR 1 /* warning and error messages only */ +#define GLP_MSG_ON 2 /* normal output */ +#define GLP_MSG_ALL 3 /* full output */ +#define GLP_MSG_DBG 4 /* debug output */ + int meth; /* simplex method option: */ +#define GLP_PRIMAL 1 /* use primal simplex */ +#define GLP_DUALP 2 /* use dual; if it fails, use primal */ +#define GLP_DUAL 3 /* use dual simplex */ + int pricing; /* pricing technique: */ +#define GLP_PT_STD 0x11 /* standard (Dantzig rule) */ +#define GLP_PT_PSE 0x22 /* projected steepest edge */ + int r_test; /* ratio test technique: */ +#define GLP_RT_STD 0x11 /* standard (textbook) */ +#define GLP_RT_HAR 0x22 /* two-pass Harris' ratio test */ + double tol_bnd; /* spx.tol_bnd */ + double tol_dj; /* spx.tol_dj */ + double tol_piv; /* spx.tol_piv */ + double obj_ll; /* spx.obj_ll */ + double obj_ul; /* spx.obj_ul */ + int it_lim; /* spx.it_lim */ + int tm_lim; /* spx.tm_lim (milliseconds) */ + int out_frq; /* spx.out_frq */ + int out_dly; /* spx.out_dly (milliseconds) */ + int presolve; /* enable/disable using LP presolver */ + double foo_bar[36]; /* (reserved) */ +} glp_smcp; + +typedef struct +{ /* interior-point solver control parameters */ + int msg_lev; /* message level (see glp_smcp) */ + int ord_alg; /* ordering algorithm: */ +#define GLP_ORD_NONE 0 /* natural (original) ordering */ +#define GLP_ORD_QMD 1 /* quotient minimum degree (QMD) */ +#define GLP_ORD_AMD 2 /* approx. minimum degree (AMD) */ +#define GLP_ORD_SYMAMD 3 /* approx. minimum degree (SYMAMD) */ + double foo_bar[48]; /* (reserved) */ +} glp_iptcp; + +typedef struct glp_tree glp_tree; +/* branch-and-bound tree */ + +typedef struct +{ /* integer optimizer control parameters */ + int msg_lev; /* message level (see glp_smcp) */ + int br_tech; /* branching technique: */ +#define GLP_BR_FFV 1 /* first fractional variable */ +#define GLP_BR_LFV 2 /* last fractional variable */ +#define GLP_BR_MFV 3 /* most fractional variable */ +#define GLP_BR_DTH 4 /* heuristic by Driebeck and Tomlin */ +#define GLP_BR_PCH 5 /* hybrid pseudocost heuristic */ + int bt_tech; /* backtracking technique: */ +#define GLP_BT_DFS 1 /* depth first search */ +#define GLP_BT_BFS 2 /* breadth first search */ +#define GLP_BT_BLB 3 /* best local bound */ +#define GLP_BT_BPH 4 /* best projection heuristic */ + double tol_int; /* mip.tol_int */ + double tol_obj; /* mip.tol_obj */ + int tm_lim; /* mip.tm_lim (milliseconds) */ + int out_frq; /* mip.out_frq (milliseconds) */ + int out_dly; /* mip.out_dly (milliseconds) */ + void (*cb_func)(glp_tree *T, void *info); + /* mip.cb_func */ + void *cb_info; /* mip.cb_info */ + int cb_size; /* mip.cb_size */ + int pp_tech; /* preprocessing technique: */ +#define GLP_PP_NONE 0 /* disable preprocessing */ +#define GLP_PP_ROOT 1 /* preprocessing only on root level */ +#define GLP_PP_ALL 2 /* preprocessing on all levels */ + double mip_gap; /* relative MIP gap tolerance */ + int mir_cuts; /* MIR cuts (GLP_ON/GLP_OFF) */ + int gmi_cuts; /* Gomory's cuts (GLP_ON/GLP_OFF) */ + int cov_cuts; /* cover cuts (GLP_ON/GLP_OFF) */ + int clq_cuts; /* clique cuts (GLP_ON/GLP_OFF) */ + int presolve; /* enable/disable using MIP presolver */ + int binarize; /* try to binarize integer variables */ + int fp_heur; /* feasibility pump heuristic */ +#if 1 /* 25/V-2013 */ + int ps_heur; /* proximity search heuristic */ +#endif +#if 1 /* 29/VI-2013 */ + int ps_tm_lim; /* proxy time limit, milliseconds */ +#endif +#if 1 /* 11/VII-2013 */ + int use_sol; /* use existing solution */ + const char *save_sol; /* filename to save every new solution */ +#endif +#if 1 /* 28/V-2010 */ + int alien; /* use alien solver */ +#endif + double foo_bar[25]; /* (reserved) */ +} glp_iocp; + +typedef struct +{ /* additional row attributes */ + int level; + /* subproblem level at which the row was added */ + int origin; + /* row origin flag: */ +#define GLP_RF_REG 0 /* regular constraint */ +#define GLP_RF_LAZY 1 /* "lazy" constraint */ +#define GLP_RF_CUT 2 /* cutting plane constraint */ + int klass; + /* row class descriptor: */ +#define GLP_RF_GMI 1 /* Gomory's mixed integer cut */ +#define GLP_RF_MIR 2 /* mixed integer rounding cut */ +#define GLP_RF_COV 3 /* mixed cover cut */ +#define GLP_RF_CLQ 4 /* clique cut */ + double foo_bar[7]; + /* (reserved) */ +} glp_attr; + +/* enable/disable flag: */ +#define GLP_ON 1 /* enable something */ +#define GLP_OFF 0 /* disable something */ + +/* reason codes: */ +#define GLP_IROWGEN 0x01 /* request for row generation */ +#define GLP_IBINGO 0x02 /* better integer solution found */ +#define GLP_IHEUR 0x03 /* request for heuristic solution */ +#define GLP_ICUTGEN 0x04 /* request for cut generation */ +#define GLP_IBRANCH 0x05 /* request for branching */ +#define GLP_ISELECT 0x06 /* request for subproblem selection */ +#define GLP_IPREPRO 0x07 /* request for preprocessing */ + +/* branch selection indicator: */ +#define GLP_NO_BRNCH 0 /* select no branch */ +#define GLP_DN_BRNCH 1 /* select down-branch */ +#define GLP_UP_BRNCH 2 /* select up-branch */ + +/* return codes: */ +#define GLP_EBADB 0x01 /* invalid basis */ +#define GLP_ESING 0x02 /* singular matrix */ +#define GLP_ECOND 0x03 /* ill-conditioned matrix */ +#define GLP_EBOUND 0x04 /* invalid bounds */ +#define GLP_EFAIL 0x05 /* solver failed */ +#define GLP_EOBJLL 0x06 /* objective lower limit reached */ +#define GLP_EOBJUL 0x07 /* objective upper limit reached */ +#define GLP_EITLIM 0x08 /* iteration limit exceeded */ +#define GLP_ETMLIM 0x09 /* time limit exceeded */ +#define GLP_ENOPFS 0x0A /* no primal feasible solution */ +#define GLP_ENODFS 0x0B /* no dual feasible solution */ +#define GLP_EROOT 0x0C /* root LP optimum not provided */ +#define GLP_ESTOP 0x0D /* search terminated by application */ +#define GLP_EMIPGAP 0x0E /* relative mip gap tolerance reached */ +#define GLP_ENOFEAS 0x0F /* no primal/dual feasible solution */ +#define GLP_ENOCVG 0x10 /* no convergence */ +#define GLP_EINSTAB 0x11 /* numerical instability */ +#define GLP_EDATA 0x12 /* invalid data */ +#define GLP_ERANGE 0x13 /* result out of range */ + +/* condition indicator: */ +#define GLP_KKT_PE 1 /* primal equalities */ +#define GLP_KKT_PB 2 /* primal bounds */ +#define GLP_KKT_DE 3 /* dual equalities */ +#define GLP_KKT_DB 4 /* dual bounds */ +#define GLP_KKT_CS 5 /* complementary slackness */ + +/* MPS file format: */ +#define GLP_MPS_DECK 1 /* fixed (ancient) */ +#define GLP_MPS_FILE 2 /* free (modern) */ + +typedef struct +{ /* MPS format control parameters */ + int blank; + /* character code to replace blanks in symbolic names */ + char *obj_name; + /* objective row name */ + double tol_mps; + /* zero tolerance for MPS data */ + double foo_bar[17]; + /* (reserved for use in the future) */ +} glp_mpscp; + +typedef struct +{ /* CPLEX LP format control parameters */ + double foo_bar[20]; + /* (reserved for use in the future) */ +} glp_cpxcp; + +typedef struct glp_tran glp_tran; +/* MathProg translator workspace */ + +glp_prob *glp_create_prob(void); +/* create problem object */ + +void glp_set_prob_name(glp_prob *P, const char *name); +/* assign (change) problem name */ + +void glp_set_obj_name(glp_prob *P, const char *name); +/* assign (change) objective function name */ + +void glp_set_obj_dir(glp_prob *P, int dir); +/* set (change) optimization direction flag */ + +int glp_add_rows(glp_prob *P, int nrs); +/* add new rows to problem object */ + +int glp_add_cols(glp_prob *P, int ncs); +/* add new columns to problem object */ + +void glp_set_row_name(glp_prob *P, int i, const char *name); +/* assign (change) row name */ + +void glp_set_col_name(glp_prob *P, int j, const char *name); +/* assign (change) column name */ + +void glp_set_row_bnds(glp_prob *P, int i, int type, double lb, + double ub); +/* set (change) row bounds */ + +void glp_set_col_bnds(glp_prob *P, int j, int type, double lb, + double ub); +/* set (change) column bounds */ + +void glp_set_obj_coef(glp_prob *P, int j, double coef); +/* set (change) obj. coefficient or constant term */ + +void glp_set_mat_row(glp_prob *P, int i, int len, const int ind[], + const double val[]); +/* set (replace) row of the constraint matrix */ + +void glp_set_mat_col(glp_prob *P, int j, int len, const int ind[], + const double val[]); +/* set (replace) column of the constraint matrix */ + +void glp_load_matrix(glp_prob *P, int ne, const int ia[], + const int ja[], const double ar[]); +/* load (replace) the whole constraint matrix */ + +int glp_check_dup(int m, int n, int ne, const int ia[], const int ja[]); +/* check for duplicate elements in sparse matrix */ + +void glp_sort_matrix(glp_prob *P); +/* sort elements of the constraint matrix */ + +void glp_del_rows(glp_prob *P, int nrs, const int num[]); +/* delete specified rows from problem object */ + +void glp_del_cols(glp_prob *P, int ncs, const int num[]); +/* delete specified columns from problem object */ + +void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names); +/* copy problem object content */ + +void glp_erase_prob(glp_prob *P); +/* erase problem object content */ + +void glp_delete_prob(glp_prob *P); +/* delete problem object */ + +const char *glp_get_prob_name(glp_prob *P); +/* retrieve problem name */ + +const char *glp_get_obj_name(glp_prob *P); +/* retrieve objective function name */ + +int glp_get_obj_dir(glp_prob *P); +/* retrieve optimization direction flag */ + +int glp_get_num_rows(glp_prob *P); +/* retrieve number of rows */ + +int glp_get_num_cols(glp_prob *P); +/* retrieve number of columns */ + +const char *glp_get_row_name(glp_prob *P, int i); +/* retrieve row name */ + +const char *glp_get_col_name(glp_prob *P, int j); +/* retrieve column name */ + +int glp_get_row_type(glp_prob *P, int i); +/* retrieve row type */ + +double glp_get_row_lb(glp_prob *P, int i); +/* retrieve row lower bound */ + +double glp_get_row_ub(glp_prob *P, int i); +/* retrieve row upper bound */ + +int glp_get_col_type(glp_prob *P, int j); +/* retrieve column type */ + +double glp_get_col_lb(glp_prob *P, int j); +/* retrieve column lower bound */ + +double glp_get_col_ub(glp_prob *P, int j); +/* retrieve column upper bound */ + +double glp_get_obj_coef(glp_prob *P, int j); +/* retrieve obj. coefficient or constant term */ + +int glp_get_num_nz(glp_prob *P); +/* retrieve number of constraint coefficients */ + +int glp_get_mat_row(glp_prob *P, int i, int ind[], double val[]); +/* retrieve row of the constraint matrix */ + +int glp_get_mat_col(glp_prob *P, int j, int ind[], double val[]); +/* retrieve column of the constraint matrix */ + +void glp_create_index(glp_prob *P); +/* create the name index */ + +int glp_find_row(glp_prob *P, const char *name); +/* find row by its name */ + +int glp_find_col(glp_prob *P, const char *name); +/* find column by its name */ + +void glp_delete_index(glp_prob *P); +/* delete the name index */ + +void glp_set_rii(glp_prob *P, int i, double rii); +/* set (change) row scale factor */ + +void glp_set_sjj(glp_prob *P, int j, double sjj); +/* set (change) column scale factor */ + +double glp_get_rii(glp_prob *P, int i); +/* retrieve row scale factor */ + +double glp_get_sjj(glp_prob *P, int j); +/* retrieve column scale factor */ + +void glp_scale_prob(glp_prob *P, int flags); +/* scale problem data */ + +void glp_unscale_prob(glp_prob *P); +/* unscale problem data */ + +void glp_set_row_stat(glp_prob *P, int i, int stat); +/* set (change) row status */ + +void glp_set_col_stat(glp_prob *P, int j, int stat); +/* set (change) column status */ + +void glp_std_basis(glp_prob *P); +/* construct standard initial LP basis */ + +void glp_adv_basis(glp_prob *P, int flags); +/* construct advanced initial LP basis */ + +void glp_cpx_basis(glp_prob *P); +/* construct Bixby's initial LP basis */ + +int glp_simplex(glp_prob *P, const glp_smcp *parm); +/* solve LP problem with the simplex method */ + +int glp_exact(glp_prob *P, const glp_smcp *parm); +/* solve LP problem in exact arithmetic */ + +void glp_init_smcp(glp_smcp *parm); +/* initialize simplex method control parameters */ + +int glp_get_status(glp_prob *P); +/* retrieve generic status of basic solution */ + +int glp_get_prim_stat(glp_prob *P); +/* retrieve status of primal basic solution */ + +int glp_get_dual_stat(glp_prob *P); +/* retrieve status of dual basic solution */ + +double glp_get_obj_val(glp_prob *P); +/* retrieve objective value (basic solution) */ + +int glp_get_row_stat(glp_prob *P, int i); +/* retrieve row status */ + +double glp_get_row_prim(glp_prob *P, int i); +/* retrieve row primal value (basic solution) */ + +double glp_get_row_dual(glp_prob *P, int i); +/* retrieve row dual value (basic solution) */ + +int glp_get_col_stat(glp_prob *P, int j); +/* retrieve column status */ + +double glp_get_col_prim(glp_prob *P, int j); +/* retrieve column primal value (basic solution) */ + +double glp_get_col_dual(glp_prob *P, int j); +/* retrieve column dual value (basic solution) */ + +int glp_get_unbnd_ray(glp_prob *P); +/* determine variable causing unboundedness */ + +#if 1 /* 08/VIII-2013; not documented yet */ +int glp_get_it_cnt(glp_prob *P); +/* get simplex solver iteration count */ +#endif + +#if 1 /* 08/VIII-2013; not documented yet */ +int glp_set_it_cnt(glp_prob *P, int it_cnt); +/* set simplex solver iteration count */ +#endif + +int glp_interior(glp_prob *P, const glp_iptcp *parm); +/* solve LP problem with the interior-point method */ + +void glp_init_iptcp(glp_iptcp *parm); +/* initialize interior-point solver control parameters */ + +int glp_ipt_status(glp_prob *P); +/* retrieve status of interior-point solution */ + +double glp_ipt_obj_val(glp_prob *P); +/* retrieve objective value (interior point) */ + +double glp_ipt_row_prim(glp_prob *P, int i); +/* retrieve row primal value (interior point) */ + +double glp_ipt_row_dual(glp_prob *P, int i); +/* retrieve row dual value (interior point) */ + +double glp_ipt_col_prim(glp_prob *P, int j); +/* retrieve column primal value (interior point) */ + +double glp_ipt_col_dual(glp_prob *P, int j); +/* retrieve column dual value (interior point) */ + +void glp_set_col_kind(glp_prob *P, int j, int kind); +/* set (change) column kind */ + +int glp_get_col_kind(glp_prob *P, int j); +/* retrieve column kind */ + +int glp_get_num_int(glp_prob *P); +/* retrieve number of integer columns */ + +int glp_get_num_bin(glp_prob *P); +/* retrieve number of binary columns */ + +int glp_intopt(glp_prob *P, const glp_iocp *parm); +/* solve MIP problem with the branch-and-bound method */ + +void glp_init_iocp(glp_iocp *parm); +/* initialize integer optimizer control parameters */ + +int glp_mip_status(glp_prob *P); +/* retrieve status of MIP solution */ + +double glp_mip_obj_val(glp_prob *P); +/* retrieve objective value (MIP solution) */ + +double glp_mip_row_val(glp_prob *P, int i); +/* retrieve row value (MIP solution) */ + +double glp_mip_col_val(glp_prob *P, int j); +/* retrieve column value (MIP solution) */ + +void glp_check_kkt(glp_prob *P, int sol, int cond, double *ae_max, + int *ae_ind, double *re_max, int *re_ind); +/* check feasibility/optimality conditions */ + +int glp_print_sol(glp_prob *P, const char *fname); +/* write basic solution in printable format */ + +int glp_read_sol(glp_prob *P, const char *fname); +/* read basic solution from text file */ + +int glp_write_sol(glp_prob *P, const char *fname); +/* write basic solution to text file */ + +int glp_print_ranges(glp_prob *P, int len, const int list[], + int flags, const char *fname); +/* print sensitivity analysis report */ + +int glp_print_ipt(glp_prob *P, const char *fname); +/* write interior-point solution in printable format */ + +int glp_read_ipt(glp_prob *P, const char *fname); +/* read interior-point solution from text file */ + +int glp_write_ipt(glp_prob *P, const char *fname); +/* write interior-point solution to text file */ + +int glp_print_mip(glp_prob *P, const char *fname); +/* write MIP solution in printable format */ + +int glp_read_mip(glp_prob *P, const char *fname); +/* read MIP solution from text file */ + +int glp_write_mip(glp_prob *P, const char *fname); +/* write MIP solution to text file */ + +int glp_bf_exists(glp_prob *P); +/* check if the basis factorization exists */ + +int glp_factorize(glp_prob *P); +/* compute the basis factorization */ + +int glp_bf_updated(glp_prob *P); +/* check if the basis factorization has been updated */ + +void glp_get_bfcp(glp_prob *P, glp_bfcp *parm); +/* retrieve basis factorization control parameters */ + +void glp_set_bfcp(glp_prob *P, const glp_bfcp *parm); +/* change basis factorization control parameters */ + +int glp_get_bhead(glp_prob *P, int k); +/* retrieve the basis header information */ + +int glp_get_row_bind(glp_prob *P, int i); +/* retrieve row index in the basis header */ + +int glp_get_col_bind(glp_prob *P, int j); +/* retrieve column index in the basis header */ + +void glp_ftran(glp_prob *P, double x[]); +/* perform forward transformation (solve system B*x = b) */ + +void glp_btran(glp_prob *P, double x[]); +/* perform backward transformation (solve system B'*x = b) */ + +int glp_warm_up(glp_prob *P); +/* "warm up" LP basis */ + +int glp_eval_tab_row(glp_prob *P, int k, int ind[], double val[]); +/* compute row of the simplex tableau */ + +int glp_eval_tab_col(glp_prob *P, int k, int ind[], double val[]); +/* compute column of the simplex tableau */ + +int glp_transform_row(glp_prob *P, int len, int ind[], double val[]); +/* transform explicitly specified row */ + +int glp_transform_col(glp_prob *P, int len, int ind[], double val[]); +/* transform explicitly specified column */ + +int glp_prim_rtest(glp_prob *P, int len, const int ind[], + const double val[], int dir, double eps); +/* perform primal ratio test */ + +int glp_dual_rtest(glp_prob *P, int len, const int ind[], + const double val[], int dir, double eps); +/* perform dual ratio test */ + +void glp_analyze_bound(glp_prob *P, int k, double *value1, int *var1, + double *value2, int *var2); +/* analyze active bound of non-basic variable */ + +void glp_analyze_coef(glp_prob *P, int k, double *coef1, int *var1, + double *value1, double *coef2, int *var2, double *value2); +/* analyze objective coefficient at basic variable */ + +int glp_ios_reason(glp_tree *T); +/* determine reason for calling the callback routine */ + +glp_prob *glp_ios_get_prob(glp_tree *T); +/* access the problem object */ + +void glp_ios_tree_size(glp_tree *T, int *a_cnt, int *n_cnt, + int *t_cnt); +/* determine size of the branch-and-bound tree */ + +int glp_ios_curr_node(glp_tree *T); +/* determine current active subproblem */ + +int glp_ios_next_node(glp_tree *T, int p); +/* determine next active subproblem */ + +int glp_ios_prev_node(glp_tree *T, int p); +/* determine previous active subproblem */ + +int glp_ios_up_node(glp_tree *T, int p); +/* determine parent subproblem */ + +int glp_ios_node_level(glp_tree *T, int p); +/* determine subproblem level */ + +double glp_ios_node_bound(glp_tree *T, int p); +/* determine subproblem local bound */ + +int glp_ios_best_node(glp_tree *T); +/* find active subproblem with best local bound */ + +double glp_ios_mip_gap(glp_tree *T); +/* compute relative MIP gap */ + +void *glp_ios_node_data(glp_tree *T, int p); +/* access subproblem application-specific data */ + +void glp_ios_row_attr(glp_tree *T, int i, glp_attr *attr); +/* retrieve additional row attributes */ + +int glp_ios_pool_size(glp_tree *T); +/* determine current size of the cut pool */ + +int glp_ios_add_row(glp_tree *T, + const char *name, int klass, int flags, int len, const int ind[], + const double val[], int type, double rhs); +/* add row (constraint) to the cut pool */ + +void glp_ios_del_row(glp_tree *T, int i); +/* remove row (constraint) from the cut pool */ + +void glp_ios_clear_pool(glp_tree *T); +/* remove all rows (constraints) from the cut pool */ + +int glp_ios_can_branch(glp_tree *T, int j); +/* check if can branch upon specified variable */ + +void glp_ios_branch_upon(glp_tree *T, int j, int sel); +/* choose variable to branch upon */ + +void glp_ios_select_node(glp_tree *T, int p); +/* select subproblem to continue the search */ + +int glp_ios_heur_sol(glp_tree *T, const double x[]); +/* provide solution found by heuristic */ + +void glp_ios_terminate(glp_tree *T); +/* terminate the solution process */ + +void glp_init_mpscp(glp_mpscp *parm); +/* initialize MPS format control parameters */ + +int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname); +/* read problem data in MPS format */ + +int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname); +/* write problem data in MPS format */ + +void glp_init_cpxcp(glp_cpxcp *parm); +/* initialize CPLEX LP format control parameters */ + +int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname); +/* read problem data in CPLEX LP format */ + +int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname); +/* write problem data in CPLEX LP format */ + +int glp_read_prob(glp_prob *P, int flags, const char *fname); +/* read problem data in GLPK format */ + +int glp_write_prob(glp_prob *P, int flags, const char *fname); +/* write problem data in GLPK format */ + +glp_tran *glp_mpl_alloc_wksp(void); +/* allocate the MathProg translator workspace */ + +int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip); +/* read and translate model section */ + +int glp_mpl_read_data(glp_tran *tran, const char *fname); +/* read and translate data section */ + +int glp_mpl_generate(glp_tran *tran, const char *fname); +/* generate the model */ + +void glp_mpl_build_prob(glp_tran *tran, glp_prob *prob); +/* build LP/MIP problem instance from the model */ + +int glp_mpl_postsolve(glp_tran *tran, glp_prob *prob, int sol); +/* postsolve the model */ + +void glp_mpl_free_wksp(glp_tran *tran); +/* free the MathProg translator workspace */ + +int glp_main(int argc, const char *argv[]); +/* stand-alone LP/MIP solver */ + +int glp_read_cnfsat(glp_prob *P, const char *fname); +/* read CNF-SAT problem data in DIMACS format */ + +int glp_check_cnfsat(glp_prob *P); +/* check for CNF-SAT problem instance */ + +int glp_write_cnfsat(glp_prob *P, const char *fname); +/* write CNF-SAT problem data in DIMACS format */ + +int glp_minisat1(glp_prob *P); +/* solve CNF-SAT problem with MiniSat solver */ + +int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound); +/* solve integer feasibility problem */ + +int glp_init_env(void); +/* initialize GLPK environment */ + +const char *glp_version(void); +/* determine library version */ + +int glp_free_env(void); +/* free GLPK environment */ + +void glp_puts(const char *s); +/* write string on terminal */ + +void glp_printf(const char *fmt, ...); +/* write formatted output on terminal */ + +void glp_vprintf(const char *fmt, va_list arg); +/* write formatted output on terminal */ + +int glp_term_out(int flag); +/* enable/disable terminal output */ + +void glp_term_hook(int (*func)(void *info, const char *s), void *info); +/* install hook to intercept terminal output */ + +int glp_open_tee(const char *name); +/* start copying terminal output to text file */ + +int glp_close_tee(void); +/* stop copying terminal output to text file */ + +#ifndef GLP_ERRFUNC_DEFINED +#define GLP_ERRFUNC_DEFINED +typedef void (*glp_errfunc)(const char *fmt, ...); +#endif + +#define glp_error glp_error_(__FILE__, __LINE__) +glp_errfunc glp_error_(const char *file, int line); +/* display fatal error message and terminate execution */ + +#define glp_assert(expr) \ + ((void)((expr) || (glp_assert_(#expr, __FILE__, __LINE__), 1))) +void glp_assert_(const char *expr, const char *file, int line); +/* check for logical condition */ + +void glp_error_hook(void (*func)(void *info), void *info); +/* install hook to intercept abnormal termination */ + +#define glp_malloc(size) glp_alloc(1, size) +/* allocate memory block (obsolete) */ + +#define glp_calloc(n, size) glp_alloc(n, size) +/* allocate memory block (obsolete) */ + +void *glp_alloc(int n, int size); +/* allocate memory block */ + +void *glp_realloc(void *ptr, int n, int size); +/* reallocate memory block */ + +void glp_free(void *ptr); +/* free (deallocate) memory block */ + +void glp_mem_limit(int limit); +/* set memory usage limit */ + +void glp_mem_usage(int *count, int *cpeak, size_t *total, + size_t *tpeak); +/* get memory usage information */ + +typedef struct glp_graph glp_graph; +typedef struct glp_vertex glp_vertex; +typedef struct glp_arc glp_arc; + +struct glp_graph +{ /* graph descriptor */ + void *pool; /* DMP *pool; */ + /* memory pool to store graph components */ + char *name; + /* graph name (1 to 255 chars); NULL means no name is assigned + to the graph */ + int nv_max; + /* length of the vertex list (enlarged automatically) */ + int nv; + /* number of vertices in the graph, 0 <= nv <= nv_max */ + int na; + /* number of arcs in the graph, na >= 0 */ + glp_vertex **v; /* glp_vertex *v[1+nv_max]; */ + /* v[i], 1 <= i <= nv, is a pointer to i-th vertex */ + void *index; /* AVL *index; */ + /* vertex index to find vertices by their names; NULL means the + index does not exist */ + int v_size; + /* size of data associated with each vertex (0 to 256 bytes) */ + int a_size; + /* size of data associated with each arc (0 to 256 bytes) */ +}; + +struct glp_vertex +{ /* vertex descriptor */ + int i; + /* vertex ordinal number, 1 <= i <= nv */ + char *name; + /* vertex name (1 to 255 chars); NULL means no name is assigned + to the vertex */ + void *entry; /* AVLNODE *entry; */ + /* pointer to corresponding entry in the vertex index; NULL means + that either the index does not exist or the vertex has no name + assigned */ + void *data; + /* pointer to data associated with the vertex */ + void *temp; + /* working pointer */ + glp_arc *in; + /* pointer to the (unordered) list of incoming arcs */ + glp_arc *out; + /* pointer to the (unordered) list of outgoing arcs */ +}; + +struct glp_arc +{ /* arc descriptor */ + glp_vertex *tail; + /* pointer to the tail endpoint */ + glp_vertex *head; + /* pointer to the head endpoint */ + void *data; + /* pointer to data associated with the arc */ + void *temp; + /* working pointer */ + glp_arc *t_prev; + /* pointer to previous arc having the same tail endpoint */ + glp_arc *t_next; + /* pointer to next arc having the same tail endpoint */ + glp_arc *h_prev; + /* pointer to previous arc having the same head endpoint */ + glp_arc *h_next; + /* pointer to next arc having the same head endpoint */ +}; + +glp_graph *glp_create_graph(int v_size, int a_size); +/* create graph */ + +void glp_set_graph_name(glp_graph *G, const char *name); +/* assign (change) graph name */ + +int glp_add_vertices(glp_graph *G, int nadd); +/* add new vertices to graph */ + +void glp_set_vertex_name(glp_graph *G, int i, const char *name); +/* assign (change) vertex name */ + +glp_arc *glp_add_arc(glp_graph *G, int i, int j); +/* add new arc to graph */ + +void glp_del_vertices(glp_graph *G, int ndel, const int num[]); +/* delete vertices from graph */ + +void glp_del_arc(glp_graph *G, glp_arc *a); +/* delete arc from graph */ + +void glp_erase_graph(glp_graph *G, int v_size, int a_size); +/* erase graph content */ + +void glp_delete_graph(glp_graph *G); +/* delete graph */ + +void glp_create_v_index(glp_graph *G); +/* create vertex name index */ + +int glp_find_vertex(glp_graph *G, const char *name); +/* find vertex by its name */ + +void glp_delete_v_index(glp_graph *G); +/* delete vertex name index */ + +int glp_read_graph(glp_graph *G, const char *fname); +/* read graph from plain text file */ + +int glp_write_graph(glp_graph *G, const char *fname); +/* write graph to plain text file */ + +void glp_mincost_lp(glp_prob *P, glp_graph *G, int names, int v_rhs, + int a_low, int a_cap, int a_cost); +/* convert minimum cost flow problem to LP */ + +int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, double *sol, int a_x, int v_pi); +/* find minimum-cost flow with out-of-kilter algorithm */ + +int glp_mincost_relax4(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, int crash, double *sol, int a_x, int a_rc); +/* find minimum-cost flow with Bertsekas-Tseng relaxation method */ + +void glp_maxflow_lp(glp_prob *P, glp_graph *G, int names, int s, + int t, int a_cap); +/* convert maximum flow problem to LP */ + +int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap, + double *sol, int a_x, int v_cut); +/* find maximal flow with Ford-Fulkerson algorithm */ + +int glp_check_asnprob(glp_graph *G, int v_set); +/* check correctness of assignment problem data */ + +/* assignment problem formulation: */ +#define GLP_ASN_MIN 1 /* perfect matching (minimization) */ +#define GLP_ASN_MAX 2 /* perfect matching (maximization) */ +#define GLP_ASN_MMP 3 /* maximum matching */ + +int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, + int v_set, int a_cost); +/* convert assignment problem to LP */ + +int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost, + double *sol, int a_x); +/* solve assignment problem with out-of-kilter algorithm */ + +int glp_asnprob_hall(glp_graph *G, int v_set, int a_x); +/* find bipartite matching of maximum cardinality */ + +double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls); +/* solve critical path problem */ + +int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname); +/* read min-cost flow problem data in DIMACS format */ + +int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname); +/* write min-cost flow problem data in DIMACS format */ + +int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap, + const char *fname); +/* read maximum flow problem data in DIMACS format */ + +int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, + const char *fname); +/* write maximum flow problem data in DIMACS format */ + +int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char + *fname); +/* read assignment problem data in DIMACS format */ + +int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char + *fname); +/* write assignment problem data in DIMACS format */ + +int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname); +/* read graph in DIMACS clique/coloring format */ + +int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname); +/* write graph in DIMACS clique/coloring format */ + +int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, + const int parm[1+15]); +/* Klingman's network problem generator */ + +void glp_netgen_prob(int nprob, int parm[1+15]); +/* Klingman's standard network problem instance */ + +int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, + const int parm[1+14]); +/* grid-like network problem generator */ + +int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap, + const int parm[1+5]); +/* Goldfarb's maximum flow problem generator */ + +int glp_weak_comp(glp_graph *G, int v_num); +/* find all weakly connected components of graph */ + +int glp_strong_comp(glp_graph *G, int v_num); +/* find all strongly connected components of graph */ + +int glp_top_sort(glp_graph *G, int v_num); +/* topological sorting of acyclic digraph */ + +int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set); +/* find maximum weight clique with exact algorithm */ + +#ifdef __cplusplus +} +#endif + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glplpf.c b/resources/3rdparty/glpk-4.53/src/glplpf.c new file mode 100644 index 000000000..8f858531d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glplpf.c @@ -0,0 +1,1097 @@ +/* glplpf.c (LP basis factorization, Schur complement version) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glplpf.h" + +#define xfault xerror + +#define GLPLPF_DEBUG 0 + +/* CAUTION: DO NOT CHANGE THE LIMIT BELOW */ + +#define M_MAX 100000000 /* = 100*10^6 */ +/* maximal order of the basis matrix */ + +/*********************************************************************** +* NAME +* +* lpf_create_it - create LP basis factorization +* +* SYNOPSIS +* +* #include "glplpf.h" +* LPF *lpf_create_it(void); +* +* DESCRIPTION +* +* The routine lpf_create_it creates a program object, which represents +* a factorization of LP basis. +* +* RETURNS +* +* The routine lpf_create_it returns a pointer to the object created. */ + +LPF *lpf_create_it(void) +{ LPF *lpf; +#if GLPLPF_DEBUG + xprintf("lpf_create_it: warning: debug mode enabled\n"); +#endif + lpf = xmalloc(sizeof(LPF)); + lpf->valid = 0; + lpf->m0_max = lpf->m0 = 0; +#if 0 /* 06/VI-2013 */ + lpf->luf = luf_create_it(); +#else + lpf->lufint = lufint_create(); +#endif + lpf->m = 0; + lpf->B = NULL; + lpf->n_max = 50; + lpf->n = 0; + lpf->R_ptr = lpf->R_len = NULL; + lpf->S_ptr = lpf->S_len = NULL; +#if 0 /* 11/VIII-2013 */ + lpf->scf = NULL; +#else + lpf->ifu.n_max = 0; + lpf->ifu.n = 0; + lpf->ifu.f = NULL; + lpf->ifu.u = NULL; + lpf->t_opt = 0; +#endif + lpf->P_row = lpf->P_col = NULL; + lpf->Q_row = lpf->Q_col = NULL; + lpf->v_size = 1000; + lpf->v_ptr = 0; + lpf->v_ind = NULL; + lpf->v_val = NULL; + lpf->work1 = lpf->work2 = NULL; + return lpf; +} + +/*********************************************************************** +* NAME +* +* lpf_factorize - compute LP basis factorization +* +* SYNOPSIS +* +* #include "glplpf.h" +* int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col) +* (void *info, int j, int ind[], double val[]), void *info); +* +* DESCRIPTION +* +* The routine lpf_factorize computes the factorization of the basis +* matrix B specified by the routine col. +* +* The parameter lpf specified the basis factorization data structure +* created with the routine lpf_create_it. +* +* The parameter m specifies the order of B, m > 0. +* +* The array bh specifies the basis header: bh[j], 1 <= j <= m, is the +* number of j-th column of B in some original matrix. The array bh is +* optional and can be specified as NULL. +* +* The formal routine col specifies the matrix B to be factorized. To +* obtain j-th column of A the routine lpf_factorize calls the routine +* col with the parameter j (1 <= j <= n). In response the routine col +* should store row indices and numerical values of non-zero elements +* of j-th column of B to locations ind[1,...,len] and val[1,...,len], +* respectively, where len is the number of non-zeros in j-th column +* returned on exit. Neither zero nor duplicate elements are allowed. +* +* The parameter info is a transit pointer passed to the routine col. +* +* RETURNS +* +* 0 The factorization has been successfully computed. +* +* LPF_ESING +* The specified matrix is singular within the working precision. +* +* LPF_ECOND +* The specified matrix is ill-conditioned. +* +* For more details see comments to the routine luf_factorize. */ + +int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col) + (void *info, int j, int ind[], double val[]), void *info) +{ int k, ret; +#if GLPLPF_DEBUG + int i, j, len, *ind; + double *B, *val; +#endif + xassert(bh == bh); + if (m < 1) + xfault("lpf_factorize: m = %d; invalid parameter\n", m); + if (m > M_MAX) + xfault("lpf_factorize: m = %d; matrix too big\n", m); + lpf->m0 = lpf->m = m; + /* invalidate the factorization */ + lpf->valid = 0; + /* allocate/reallocate arrays, if necessary */ + if (lpf->R_ptr == NULL) + lpf->R_ptr = xcalloc(1+lpf->n_max, sizeof(int)); + if (lpf->R_len == NULL) + lpf->R_len = xcalloc(1+lpf->n_max, sizeof(int)); + if (lpf->S_ptr == NULL) + lpf->S_ptr = xcalloc(1+lpf->n_max, sizeof(int)); + if (lpf->S_len == NULL) + lpf->S_len = xcalloc(1+lpf->n_max, sizeof(int)); +#if 0 /* 11/VIII-2013 */ + if (lpf->scf == NULL) + lpf->scf = scf_create_it(lpf->n_max); +#else + if (lpf->ifu.n_max == 0) + { int n_max = lpf->n_max; + lpf->ifu.n_max = n_max; + lpf->ifu.n = 0; + xassert(n_max > 0); + xassert(lpf->ifu.f == NULL); + lpf->ifu.f = talloc(n_max * n_max, double); + xassert(lpf->ifu.u == NULL); + lpf->ifu.u = talloc(n_max * n_max, double); + lpf->t_opt = 0; + } +#endif + if (lpf->v_ind == NULL) + lpf->v_ind = xcalloc(1+lpf->v_size, sizeof(int)); + if (lpf->v_val == NULL) + lpf->v_val = xcalloc(1+lpf->v_size, sizeof(double)); + if (lpf->m0_max < m) + { if (lpf->P_row != NULL) xfree(lpf->P_row); + if (lpf->P_col != NULL) xfree(lpf->P_col); + if (lpf->Q_row != NULL) xfree(lpf->Q_row); + if (lpf->Q_col != NULL) xfree(lpf->Q_col); + if (lpf->work1 != NULL) xfree(lpf->work1); + if (lpf->work2 != NULL) xfree(lpf->work2); + lpf->m0_max = m + 100; + lpf->P_row = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); + lpf->P_col = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); + lpf->Q_row = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); + lpf->Q_col = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); + lpf->work1 = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(double)); + lpf->work2 = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(double)); + } + /* try to factorize the basis matrix */ +#if 0 /* 06/VI-2013 */ + switch (luf_factorize(lpf->luf, m, col, info)) + { case 0: + break; + case LUF_ESING: + ret = LPF_ESING; + goto done; + case LUF_ECOND: + ret = LPF_ECOND; + goto done; + default: + xassert(lpf != lpf); + } +#else + if (lufint_factorize(lpf->lufint, m, col, info) != 0) + { ret = LPF_ESING; + goto done; + } +#endif + /* the basis matrix has been successfully factorized */ + lpf->valid = 1; +#if GLPLPF_DEBUG + /* store the basis matrix for debugging */ + if (lpf->B != NULL) xfree(lpf->B); + xassert(m <= 32767); + lpf->B = B = xcalloc(1+m*m, sizeof(double)); + ind = xcalloc(1+m, sizeof(int)); + val = xcalloc(1+m, sizeof(double)); + for (k = 1; k <= m * m; k++) + B[k] = 0.0; + for (j = 1; j <= m; j++) + { len = col(info, j, ind, val); + xassert(0 <= len && len <= m); + for (k = 1; k <= len; k++) + { i = ind[k]; + xassert(1 <= i && i <= m); + xassert(B[(i - 1) * m + j] == 0.0); + xassert(val[k] != 0.0); + B[(i - 1) * m + j] = val[k]; + } + } + xfree(ind); + xfree(val); +#endif + /* B = B0, so there are no additional rows/columns */ + lpf->n = 0; + /* reset the Schur complement factorization */ +#if 0 /* 11/VIII-2013 */ + scf_reset_it(lpf->scf); +#else + lpf->ifu.n = 0; +#endif + /* P := Q := I */ + for (k = 1; k <= m; k++) + { lpf->P_row[k] = lpf->P_col[k] = k; + lpf->Q_row[k] = lpf->Q_col[k] = k; + } + /* make all SVA locations free */ + lpf->v_ptr = 1; + ret = 0; +done: /* return to the calling program */ + return ret; +} + +/*********************************************************************** +* The routine r_prod computes the product y := y + alpha * R * x, +* where x is a n-vector, alpha is a scalar, y is a m0-vector. +* +* Since matrix R is available by columns, the product is computed as +* a linear combination: +* +* y := y + alpha * (R[1] * x[1] + ... + R[n] * x[n]), +* +* where R[j] is j-th column of R. */ + +static void r_prod(LPF *lpf, double y[], double a, const double x[]) +{ int n = lpf->n; + int *R_ptr = lpf->R_ptr; + int *R_len = lpf->R_len; + int *v_ind = lpf->v_ind; + double *v_val = lpf->v_val; + int j, beg, end, ptr; + double t; + for (j = 1; j <= n; j++) + { if (x[j] == 0.0) continue; + /* y := y + alpha * R[j] * x[j] */ + t = a * x[j]; + beg = R_ptr[j]; + end = beg + R_len[j]; + for (ptr = beg; ptr < end; ptr++) + y[v_ind[ptr]] += t * v_val[ptr]; + } + return; +} + +/*********************************************************************** +* The routine rt_prod computes the product y := y + alpha * R' * x, +* where R' is a matrix transposed to R, x is a m0-vector, alpha is a +* scalar, y is a n-vector. +* +* Since matrix R is available by columns, the product components are +* computed as inner products: +* +* y[j] := y[j] + alpha * (j-th column of R) * x +* +* for j = 1, 2, ..., n. */ + +static void rt_prod(LPF *lpf, double y[], double a, const double x[]) +{ int n = lpf->n; + int *R_ptr = lpf->R_ptr; + int *R_len = lpf->R_len; + int *v_ind = lpf->v_ind; + double *v_val = lpf->v_val; + int j, beg, end, ptr; + double t; + for (j = 1; j <= n; j++) + { /* t := (j-th column of R) * x */ + t = 0.0; + beg = R_ptr[j]; + end = beg + R_len[j]; + for (ptr = beg; ptr < end; ptr++) + t += v_val[ptr] * x[v_ind[ptr]]; + /* y[j] := y[j] + alpha * t */ + y[j] += a * t; + } + return; +} + +/*********************************************************************** +* The routine s_prod computes the product y := y + alpha * S * x, +* where x is a m0-vector, alpha is a scalar, y is a n-vector. +* +* Since matrix S is available by rows, the product components are +* computed as inner products: +* +* y[i] = y[i] + alpha * (i-th row of S) * x +* +* for i = 1, 2, ..., n. */ + +static void s_prod(LPF *lpf, double y[], double a, const double x[]) +{ int n = lpf->n; + int *S_ptr = lpf->S_ptr; + int *S_len = lpf->S_len; + int *v_ind = lpf->v_ind; + double *v_val = lpf->v_val; + int i, beg, end, ptr; + double t; + for (i = 1; i <= n; i++) + { /* t := (i-th row of S) * x */ + t = 0.0; + beg = S_ptr[i]; + end = beg + S_len[i]; + for (ptr = beg; ptr < end; ptr++) + t += v_val[ptr] * x[v_ind[ptr]]; + /* y[i] := y[i] + alpha * t */ + y[i] += a * t; + } + return; +} + +/*********************************************************************** +* The routine st_prod computes the product y := y + alpha * S' * x, +* where S' is a matrix transposed to S, x is a n-vector, alpha is a +* scalar, y is m0-vector. +* +* Since matrix R is available by rows, the product is computed as a +* linear combination: +* +* y := y + alpha * (S'[1] * x[1] + ... + S'[n] * x[n]), +* +* where S'[i] is i-th row of S. */ + +static void st_prod(LPF *lpf, double y[], double a, const double x[]) +{ int n = lpf->n; + int *S_ptr = lpf->S_ptr; + int *S_len = lpf->S_len; + int *v_ind = lpf->v_ind; + double *v_val = lpf->v_val; + int i, beg, end, ptr; + double t; + for (i = 1; i <= n; i++) + { if (x[i] == 0.0) continue; + /* y := y + alpha * S'[i] * x[i] */ + t = a * x[i]; + beg = S_ptr[i]; + end = beg + S_len[i]; + for (ptr = beg; ptr < end; ptr++) + y[v_ind[ptr]] += t * v_val[ptr]; + } + return; +} + +#if GLPLPF_DEBUG +/*********************************************************************** +* The routine check_error computes the maximal relative error between +* left- and right-hand sides for the system B * x = b (if tr is zero) +* or B' * x = b (if tr is non-zero), where B' is a matrix transposed +* to B. (This routine is intended for debugging only.) */ + +static void check_error(LPF *lpf, int tr, const double x[], + const double b[]) +{ int m = lpf->m; + double *B = lpf->B; + int i, j; + double d, dmax = 0.0, s, t, tmax; + for (i = 1; i <= m; i++) + { s = 0.0; + tmax = 1.0; + for (j = 1; j <= m; j++) + { if (!tr) + t = B[m * (i - 1) + j] * x[j]; + else + t = B[m * (j - 1) + i] * x[j]; + if (tmax < fabs(t)) tmax = fabs(t); + s += t; + } + d = fabs(s - b[i]) / tmax; + if (dmax < d) dmax = d; + } + if (dmax > 1e-8) + xprintf("%s: dmax = %g; relative error too large\n", + !tr ? "lpf_ftran" : "lpf_btran", dmax); + return; +} +#endif + +/*********************************************************************** +* NAME +* +* lpf_ftran - perform forward transformation (solve system B*x = b) +* +* SYNOPSIS +* +* #include "glplpf.h" +* void lpf_ftran(LPF *lpf, double x[]); +* +* DESCRIPTION +* +* The routine lpf_ftran performs forward transformation, i.e. solves +* the system B*x = b, where B is the basis matrix, x is the vector of +* unknowns to be computed, b is the vector of right-hand sides. +* +* On entry elements of the vector b should be stored in dense format +* in locations x[1], ..., x[m], where m is the number of rows. On exit +* the routine stores elements of the vector x in the same locations. +* +* BACKGROUND +* +* Solution of the system B * x = b can be obtained by solving the +* following augmented system: +* +* ( B F^) ( x ) ( b ) +* ( ) ( ) = ( ) +* ( G^ H^) ( y ) ( 0 ) +* +* which, using the main equality, can be written as follows: +* +* ( L0 0 ) ( U0 R ) ( x ) ( b ) +* P ( ) ( ) Q ( ) = ( ) +* ( S I ) ( 0 C ) ( y ) ( 0 ) +* +* therefore, +* +* ( x ) ( U0 R )-1 ( L0 0 )-1 ( b ) +* ( ) = Q' ( ) ( ) P' ( ) +* ( y ) ( 0 C ) ( S I ) ( 0 ) +* +* Thus, computing the solution includes the following steps: +* +* 1. Compute +* +* ( f ) ( b ) +* ( ) = P' ( ) +* ( g ) ( 0 ) +* +* 2. Solve the system +* +* ( f1 ) ( L0 0 )-1 ( f ) ( L0 0 ) ( f1 ) ( f ) +* ( ) = ( ) ( ) => ( ) ( ) = ( ) +* ( g1 ) ( S I ) ( g ) ( S I ) ( g1 ) ( g ) +* +* from which it follows that: +* +* { L0 * f1 = f f1 = inv(L0) * f +* { => +* { S * f1 + g1 = g g1 = g - S * f1 +* +* 3. Solve the system +* +* ( f2 ) ( U0 R )-1 ( f1 ) ( U0 R ) ( f2 ) ( f1 ) +* ( ) = ( ) ( ) => ( ) ( ) = ( ) +* ( g2 ) ( 0 C ) ( g1 ) ( 0 C ) ( g2 ) ( g1 ) +* +* from which it follows that: +* +* { U0 * f2 + R * g2 = f1 f2 = inv(U0) * (f1 - R * g2) +* { => +* { C * g2 = g1 g2 = inv(C) * g1 +* +* 4. Compute +* +* ( x ) ( f2 ) +* ( ) = Q' ( ) +* ( y ) ( g2 ) */ + +void lpf_ftran(LPF *lpf, double x[]) +{ int m0 = lpf->m0; + int m = lpf->m; + int n = lpf->n; + int *P_col = lpf->P_col; + int *Q_col = lpf->Q_col; + double *fg = lpf->work1; + double *f = fg; + double *g = fg + m0; + int i, ii; +#if GLPLPF_DEBUG + double *b; +#endif + if (!lpf->valid) + xfault("lpf_ftran: the factorization is not valid\n"); + xassert(0 <= m && m <= m0 + n); +#if GLPLPF_DEBUG + /* save the right-hand side vector */ + b = xcalloc(1+m, sizeof(double)); + for (i = 1; i <= m; i++) b[i] = x[i]; +#endif + /* (f g) := inv(P) * (b 0) */ + for (i = 1; i <= m0 + n; i++) + fg[i] = ((ii = P_col[i]) <= m ? x[ii] : 0.0); + /* f1 := inv(L0) * f */ +#if 0 /* 06/VI-2013 */ + luf_f_solve(lpf->luf, 0, f); +#else + luf_f_solve(lpf->lufint->luf, f); +#endif + /* g1 := g - S * f1 */ + s_prod(lpf, g, -1.0, f); + /* g2 := inv(C) * g1 */ +#if 0 /* 11/VIII-2013 */ + scf_solve_it(lpf->scf, 0, g); +#else + ifu_a_solve(&lpf->ifu, g, lpf->work2); +#endif + /* f2 := inv(U0) * (f1 - R * g2) */ + r_prod(lpf, f, -1.0, g); +#if 0 /* 06/VI-2013 */ + luf_v_solve(lpf->luf, 0, f); +#else + { double *work = lpf->lufint->sgf->work; + luf_v_solve(lpf->lufint->luf, f, work); + memcpy(&f[1], &work[1], m0 * sizeof(double)); + } +#endif + /* (x y) := inv(Q) * (f2 g2) */ + for (i = 1; i <= m; i++) + x[i] = fg[Q_col[i]]; +#if GLPLPF_DEBUG + /* check relative error in solution */ + check_error(lpf, 0, x, b); + xfree(b); +#endif + return; +} + +/*********************************************************************** +* NAME +* +* lpf_btran - perform backward transformation (solve system B'*x = b) +* +* SYNOPSIS +* +* #include "glplpf.h" +* void lpf_btran(LPF *lpf, double x[]); +* +* DESCRIPTION +* +* The routine lpf_btran performs backward transformation, i.e. solves +* the system B'*x = b, where B' is a matrix transposed to the basis +* matrix B, x is the vector of unknowns to be computed, b is the vector +* of right-hand sides. +* +* On entry elements of the vector b should be stored in dense format +* in locations x[1], ..., x[m], where m is the number of rows. On exit +* the routine stores elements of the vector x in the same locations. +* +* BACKGROUND +* +* Solution of the system B' * x = b, where B' is a matrix transposed +* to B, can be obtained by solving the following augmented system: +* +* ( B F^)T ( x ) ( b ) +* ( ) ( ) = ( ) +* ( G^ H^) ( y ) ( 0 ) +* +* which, using the main equality, can be written as follows: +* +* T ( U0 R )T ( L0 0 )T T ( x ) ( b ) +* Q ( ) ( ) P ( ) = ( ) +* ( 0 C ) ( S I ) ( y ) ( 0 ) +* +* or, equivalently, as follows: +* +* ( U'0 0 ) ( L'0 S') ( x ) ( b ) +* Q' ( ) ( ) P' ( ) = ( ) +* ( R' C') ( 0 I ) ( y ) ( 0 ) +* +* therefore, +* +* ( x ) ( L'0 S')-1 ( U'0 0 )-1 ( b ) +* ( ) = P ( ) ( ) Q ( ) +* ( y ) ( 0 I ) ( R' C') ( 0 ) +* +* Thus, computing the solution includes the following steps: +* +* 1. Compute +* +* ( f ) ( b ) +* ( ) = Q ( ) +* ( g ) ( 0 ) +* +* 2. Solve the system +* +* ( f1 ) ( U'0 0 )-1 ( f ) ( U'0 0 ) ( f1 ) ( f ) +* ( ) = ( ) ( ) => ( ) ( ) = ( ) +* ( g1 ) ( R' C') ( g ) ( R' C') ( g1 ) ( g ) +* +* from which it follows that: +* +* { U'0 * f1 = f f1 = inv(U'0) * f +* { => +* { R' * f1 + C' * g1 = g g1 = inv(C') * (g - R' * f1) +* +* 3. Solve the system +* +* ( f2 ) ( L'0 S')-1 ( f1 ) ( L'0 S') ( f2 ) ( f1 ) +* ( ) = ( ) ( ) => ( ) ( ) = ( ) +* ( g2 ) ( 0 I ) ( g1 ) ( 0 I ) ( g2 ) ( g1 ) +* +* from which it follows that: +* +* { L'0 * f2 + S' * g2 = f1 +* { => f2 = inv(L'0) * ( f1 - S' * g2) +* { g2 = g1 +* +* 4. Compute +* +* ( x ) ( f2 ) +* ( ) = P ( ) +* ( y ) ( g2 ) */ + +void lpf_btran(LPF *lpf, double x[]) +{ int m0 = lpf->m0; + int m = lpf->m; + int n = lpf->n; + int *P_row = lpf->P_row; + int *Q_row = lpf->Q_row; + double *fg = lpf->work1; + double *f = fg; + double *g = fg + m0; + int i, ii; +#if GLPLPF_DEBUG + double *b; +#endif + if (!lpf->valid) + xfault("lpf_btran: the factorization is not valid\n"); + xassert(0 <= m && m <= m0 + n); +#if GLPLPF_DEBUG + /* save the right-hand side vector */ + b = xcalloc(1+m, sizeof(double)); + for (i = 1; i <= m; i++) b[i] = x[i]; +#endif + /* (f g) := Q * (b 0) */ + for (i = 1; i <= m0 + n; i++) + fg[i] = ((ii = Q_row[i]) <= m ? x[ii] : 0.0); + /* f1 := inv(U'0) * f */ +#if 0 /* 06/VI-2013 */ + luf_v_solve(lpf->luf, 1, f); +#else + { double *work = lpf->lufint->sgf->work; + luf_vt_solve(lpf->lufint->luf, f, work); + memcpy(&f[1], &work[1], m0 * sizeof(double)); + } +#endif + /* g1 := inv(C') * (g - R' * f1) */ + rt_prod(lpf, g, -1.0, f); +#if 0 /* 11/VIII-2013 */ + scf_solve_it(lpf->scf, 1, g); +#else + ifu_at_solve(&lpf->ifu, g, lpf->work2); +#endif + /* g2 := g1 */ + g = g; + /* f2 := inv(L'0) * (f1 - S' * g2) */ + st_prod(lpf, f, -1.0, g); +#if 0 /* 06/VI-2013 */ + luf_f_solve(lpf->luf, 1, f); +#else + luf_ft_solve(lpf->lufint->luf, f); +#endif + /* (x y) := P * (f2 g2) */ + for (i = 1; i <= m; i++) + x[i] = fg[P_row[i]]; +#if GLPLPF_DEBUG + /* check relative error in solution */ + check_error(lpf, 1, x, b); + xfree(b); +#endif + return; +} + +/*********************************************************************** +* The routine enlarge_sva enlarges the Sparse Vector Area to new_size +* locations by reallocating the arrays v_ind and v_val. */ + +static void enlarge_sva(LPF *lpf, int new_size) +{ int v_size = lpf->v_size; + int used = lpf->v_ptr - 1; + int *v_ind = lpf->v_ind; + double *v_val = lpf->v_val; + xassert(v_size < new_size); + while (v_size < new_size) v_size += v_size; + lpf->v_size = v_size; + lpf->v_ind = xcalloc(1+v_size, sizeof(int)); + lpf->v_val = xcalloc(1+v_size, sizeof(double)); + xassert(used >= 0); + memcpy(&lpf->v_ind[1], &v_ind[1], used * sizeof(int)); + memcpy(&lpf->v_val[1], &v_val[1], used * sizeof(double)); + xfree(v_ind); + xfree(v_val); + return; +} + +/*********************************************************************** +* NAME +* +* lpf_update_it - update LP basis factorization +* +* SYNOPSIS +* +* #include "glplpf.h" +* int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[], +* const double val[]); +* +* DESCRIPTION +* +* The routine lpf_update_it updates the factorization of the basis +* matrix B after replacing its j-th column by a new vector. +* +* The parameter j specifies the number of column of B, which has been +* replaced, 1 <= j <= m, where m is the order of B. +* +* The parameter bh specifies the basis header entry for the new column +* of B, which is the number of the new column in some original matrix. +* This parameter is optional and can be specified as 0. +* +* Row indices and numerical values of non-zero elements of the new +* column of B should be placed in locations ind[1], ..., ind[len] and +* val[1], ..., val[len], resp., where len is the number of non-zeros +* in the column. Neither zero nor duplicate elements are allowed. +* +* RETURNS +* +* 0 The factorization has been successfully updated. +* +* LPF_ESING +* New basis B is singular within the working precision. +* +* LPF_ELIMIT +* Maximal number of additional rows and columns has been reached. +* +* BACKGROUND +* +* Let j-th column of the current basis matrix B have to be replaced by +* a new column a. This replacement is equivalent to removing the old +* j-th column by fixing it at zero and introducing the new column as +* follows: +* +* ( B F^| a ) +* ( B F^) ( | ) +* ( ) ---> ( G^ H^| 0 ) +* ( G^ H^) (-------+---) +* ( e'j 0 | 0 ) +* +* where ej is a unit vector with 1 in j-th position which used to fix +* the old j-th column of B (at zero). Then using the main equality we +* have: +* +* ( B F^| a ) ( B0 F | f ) +* ( | ) ( P 0 ) ( | ) ( Q 0 ) +* ( G^ H^| 0 ) = ( ) ( G H | g ) ( ) = +* (-------+---) ( 0 1 ) (-------+---) ( 0 1 ) +* ( e'j 0 | 0 ) ( v' w'| 0 ) +* +* [ ( B0 F )| ( f ) ] [ ( B0 F ) | ( f ) ] +* [ P ( )| P ( ) ] ( Q 0 ) [ P ( ) Q| P ( ) ] +* = [ ( G H )| ( g ) ] ( ) = [ ( G H ) | ( g ) ] +* [------------+-------- ] ( 0 1 ) [-------------+---------] +* [ ( v' w')| 0 ] [ ( v' w') Q| 0 ] +* +* where: +* +* ( a ) ( f ) ( f ) ( a ) +* ( ) = P ( ) => ( ) = P' * ( ) +* ( 0 ) ( g ) ( g ) ( 0 ) +* +* ( ej ) ( v ) ( v ) ( ej ) +* ( e'j 0 ) = ( v' w' ) Q => ( ) = Q' ( ) => ( ) = Q ( ) +* ( 0 ) ( w ) ( w ) ( 0 ) +* +* On the other hand: +* +* ( B0| F f ) +* ( P 0 ) (---+------) ( Q 0 ) ( B0 new F ) +* ( ) ( G | H g ) ( ) = new P ( ) new Q +* ( 0 1 ) ( | ) ( 0 1 ) ( new G new H ) +* ( v'| w' 0 ) +* +* where: +* ( G ) ( H g ) +* new F = ( F f ), new G = ( ), new H = ( ), +* ( v') ( w' 0 ) +* +* ( P 0 ) ( Q 0 ) +* new P = ( ) , new Q = ( ) . +* ( 0 1 ) ( 0 1 ) +* +* The factorization structure for the new augmented matrix remains the +* same, therefore: +* +* ( B0 new F ) ( L0 0 ) ( U0 new R ) +* new P ( ) new Q = ( ) ( ) +* ( new G new H ) ( new S I ) ( 0 new C ) +* +* where: +* +* new F = L0 * new R => +* +* new R = inv(L0) * new F = inv(L0) * (F f) = ( R inv(L0)*f ) +* +* new G = new S * U0 => +* +* ( G ) ( S ) +* new S = new G * inv(U0) = ( ) * inv(U0) = ( ) +* ( v') ( v'*inv(U0) ) +* +* new H = new S * new R + new C => +* +* new C = new H - new S * new R = +* +* ( H g ) ( S ) +* = ( ) - ( ) * ( R inv(L0)*f ) = +* ( w' 0 ) ( v'*inv(U0) ) +* +* ( H - S*R g - S*inv(L0)*f ) ( C x ) +* = ( ) = ( ) +* ( w'- v'*inv(U0)*R -v'*inv(U0)*inv(L0)*f) ( y' z ) +* +* Note that new C is resulted by expanding old C with new column x, +* row y', and diagonal element z, where: +* +* x = g - S * inv(L0) * f = g - S * (new column of R) +* +* y = w - R'* inv(U'0)* v = w - R'* (new row of S) +* +* z = - (new row of S) * (new column of R) +* +* Finally, to replace old B by new B we have to permute j-th and last +* (just added) columns of the matrix +* +* ( B F^| a ) +* ( | ) +* ( G^ H^| 0 ) +* (-------+---) +* ( e'j 0 | 0 ) +* +* and to keep the main equality do the same for matrix Q. */ + +int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[], + const double val[]) +{ int m0 = lpf->m0; + int m = lpf->m; +#if GLPLPF_DEBUG + double *B = lpf->B; +#endif + int n = lpf->n; + int *R_ptr = lpf->R_ptr; + int *R_len = lpf->R_len; + int *S_ptr = lpf->S_ptr; + int *S_len = lpf->S_len; + int *P_row = lpf->P_row; + int *P_col = lpf->P_col; + int *Q_row = lpf->Q_row; + int *Q_col = lpf->Q_col; + int v_ptr = lpf->v_ptr; + int *v_ind = lpf->v_ind; + double *v_val = lpf->v_val; + double *a = lpf->work2; /* new column */ + double *fg = lpf->work1, *f = fg, *g = fg + m0; + double *vw = lpf->work2, *v = vw, *w = vw + m0; + double *x = g, *y = w, z; + int i, ii, k, ret; + xassert(bh == bh); + if (!lpf->valid) + xfault("lpf_update_it: the factorization is not valid\n"); + if (!(1 <= j && j <= m)) + xfault("lpf_update_it: j = %d; column number out of range\n", + j); + xassert(0 <= m && m <= m0 + n); + /* check if the basis factorization can be expanded */ + if (n == lpf->n_max) + { lpf->valid = 0; + ret = LPF_ELIMIT; + goto done; + } + /* convert new j-th column of B to dense format */ + for (i = 1; i <= m; i++) + a[i] = 0.0; + for (k = 1; k <= len; k++) + { i = ind[k]; + if (!(1 <= i && i <= m)) + xfault("lpf_update_it: ind[%d] = %d; row number out of rang" + "e\n", k, i); + if (a[i] != 0.0) + xfault("lpf_update_it: ind[%d] = %d; duplicate row index no" + "t allowed\n", k, i); + if (val[k] == 0.0) + xfault("lpf_update_it: val[%d] = %g; zero element not allow" + "ed\n", k, val[k]); + a[i] = val[k]; + } +#if GLPLPF_DEBUG + /* change column in the basis matrix for debugging */ + for (i = 1; i <= m; i++) + B[(i - 1) * m + j] = a[i]; +#endif + /* (f g) := inv(P) * (a 0) */ + for (i = 1; i <= m0+n; i++) + fg[i] = ((ii = P_col[i]) <= m ? a[ii] : 0.0); + /* (v w) := Q * (ej 0) */ + for (i = 1; i <= m0+n; i++) vw[i] = 0.0; + vw[Q_col[j]] = 1.0; + /* f1 := inv(L0) * f (new column of R) */ +#if 0 /* 06/VI-2013 */ + luf_f_solve(lpf->luf, 0, f); +#else + luf_f_solve(lpf->lufint->luf, f); +#endif + /* v1 := inv(U'0) * v (new row of S) */ +#if 0 /* 06/VI-2013 */ + luf_v_solve(lpf->luf, 1, v); +#else + { double *work = lpf->lufint->sgf->work; + luf_vt_solve(lpf->lufint->luf, v, work); + memcpy(&v[1], &work[1], m0 * sizeof(double)); + } +#endif + /* we need at most 2 * m0 available locations in the SVA to store + new column of matrix R and new row of matrix S */ + if (lpf->v_size < v_ptr + m0 + m0) + { enlarge_sva(lpf, v_ptr + m0 + m0); + v_ind = lpf->v_ind; + v_val = lpf->v_val; + } + /* store new column of R */ + R_ptr[n+1] = v_ptr; + for (i = 1; i <= m0; i++) + { if (f[i] != 0.0) + v_ind[v_ptr] = i, v_val[v_ptr] = f[i], v_ptr++; + } + R_len[n+1] = v_ptr - lpf->v_ptr; + lpf->v_ptr = v_ptr; + /* store new row of S */ + S_ptr[n+1] = v_ptr; + for (i = 1; i <= m0; i++) + { if (v[i] != 0.0) + v_ind[v_ptr] = i, v_val[v_ptr] = v[i], v_ptr++; + } + S_len[n+1] = v_ptr - lpf->v_ptr; + lpf->v_ptr = v_ptr; + /* x := g - S * f1 (new column of C) */ + s_prod(lpf, x, -1.0, f); + /* y := w - R' * v1 (new row of C) */ + rt_prod(lpf, y, -1.0, v); + /* z := - v1 * f1 (new diagonal element of C) */ + z = 0.0; + for (i = 1; i <= m0; i++) z -= v[i] * f[i]; + /* update factorization of new matrix C */ +#if 0 /* 11/VIII-2013 */ + switch (scf_update_exp(lpf->scf, x, y, z)) + { case 0: + break; + case SCF_ESING: + lpf->valid = 0; + ret = LPF_ESING; + goto done; + case SCF_ELIMIT: + xassert(lpf != lpf); + default: + xassert(lpf != lpf); + } +#else + if (lpf->t_opt == SCF_TBG) + { if (ifu_bg_update(&lpf->ifu, x, y, z) != 0) +#if 0 + { xprintf("Warning: insufficient accuracy (Bartels-Golub upda" + "te)\n"); +#else + { +#endif + lpf->valid = 0; + ret = LPF_ESING; + goto done; + } + } + else if (lpf->t_opt == SCF_TGR) + { if (ifu_gr_update(&lpf->ifu, x, y, z) != 0) +#if 0 + { xprintf("Warning: insufficient accuracy (Givens rotations u" + "pdate)\n"); +#else + { +#endif + lpf->valid = 0; + ret = LPF_ESING; + goto done; + } + } + else + xassert(lpf != lpf); +#endif + /* expand matrix P */ + P_row[m0+n+1] = P_col[m0+n+1] = m0+n+1; + /* expand matrix Q */ + Q_row[m0+n+1] = Q_col[m0+n+1] = m0+n+1; + /* permute j-th and last (just added) column of matrix Q */ + i = Q_col[j], ii = Q_col[m0+n+1]; + Q_row[i] = m0+n+1, Q_col[m0+n+1] = i; + Q_row[ii] = j, Q_col[j] = ii; + /* increase the number of additional rows and columns */ + lpf->n++; + xassert(lpf->n <= lpf->n_max); + /* the factorization has been successfully updated */ + ret = 0; +done: /* return to the calling program */ + return ret; +} + +/*********************************************************************** +* NAME +* +* lpf_delete_it - delete LP basis factorization +* +* SYNOPSIS +* +* #include "glplpf.h" +* void lpf_delete_it(LPF *lpf) +* +* DESCRIPTION +* +* The routine lpf_delete_it deletes LP basis factorization specified +* by the parameter lpf and frees all memory allocated to this program +* object. */ + +void lpf_delete_it(LPF *lpf) +#if 0 /* 06/VI-2013 */ +{ luf_delete_it(lpf->luf); +#else +{ lufint_delete(lpf->lufint); +#endif +#if GLPLPF_DEBUG + if (lpf->B != NULL) xfree(lpf->B); +#else + xassert(lpf->B == NULL); +#endif + if (lpf->R_ptr != NULL) xfree(lpf->R_ptr); + if (lpf->R_len != NULL) xfree(lpf->R_len); + if (lpf->S_ptr != NULL) xfree(lpf->S_ptr); + if (lpf->S_len != NULL) xfree(lpf->S_len); +#if 0 /* 11/VIII-2013 */ + if (lpf->scf != NULL) scf_delete_it(lpf->scf); +#else + if (lpf->ifu.f != NULL) tfree(lpf->ifu.f); + if (lpf->ifu.u != NULL) tfree(lpf->ifu.u); +#endif + if (lpf->P_row != NULL) xfree(lpf->P_row); + if (lpf->P_col != NULL) xfree(lpf->P_col); + if (lpf->Q_row != NULL) xfree(lpf->Q_row); + if (lpf->Q_col != NULL) xfree(lpf->Q_col); + if (lpf->v_ind != NULL) xfree(lpf->v_ind); + if (lpf->v_val != NULL) xfree(lpf->v_val); + if (lpf->work1 != NULL) xfree(lpf->work1); + if (lpf->work2 != NULL) xfree(lpf->work2); + xfree(lpf); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glplpf.h b/resources/3rdparty/glpk-4.53/src/glplpf.h new file mode 100644 index 000000000..e06e6c595 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glplpf.h @@ -0,0 +1,216 @@ +/* glplpf.h (LP basis factorization, Schur complement version) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPLPF_H +#define GLPLPF_H + +#if 0 /* 11/VIII-2013 */ +#include "glpscf.h" +#else +#include "ifu.h" +#endif +#if 0 /* 06/VI-2013 */ +#include "glpluf.h" +#else +#include "lufint.h" +#endif + +/*********************************************************************** +* The structure LPF defines the factorization of the basis mxm matrix +* B, where m is the number of rows in corresponding problem instance. +* +* This factorization is the following septet: +* +* [B] = (L0, U0, R, S, C, P, Q), (1) +* +* and is based on the following main equality: +* +* ( B F^) ( B0 F ) ( L0 0 ) ( U0 R ) +* ( ) = P ( ) Q = P ( ) ( ) Q, (2) +* ( G^ H^) ( G H ) ( S I ) ( 0 C ) +* +* where: +* +* B is the current basis matrix (not stored); +* +* F^, G^, H^ are some additional matrices (not stored); +* +* B0 is some initial basis matrix (not stored); +* +* F, G, H are some additional matrices (not stored); +* +* P, Q are permutation matrices (stored in both row- and column-like +* formats); +* +* L0, U0 are some matrices that defines a factorization of the initial +* basis matrix B0 = L0 * U0 (stored in an invertable form); +* +* R is a matrix defined from L0 * R = F, so R = inv(L0) * F (stored in +* a column-wise sparse format); +* +* S is a matrix defined from S * U0 = G, so S = G * inv(U0) (stored in +* a row-wise sparse format); +* +* C is the Schur complement for matrix (B0 F G H). It is defined from +* S * R + C = H, so C = H - S * R = H - G * inv(U0) * inv(L0) * F = +* = H - G * inv(B0) * F. Matrix C is stored in an invertable form. +* +* REFERENCES +* +* 1. M.A.Saunders, "LUSOL: A basis package for constrained optimiza- +* tion," SCCM, Stanford University, 2006. +* +* 2. M.A.Saunders, "Notes 5: Basis Updates," CME 318, Stanford Univer- +* sity, Spring 2006. +* +* 3. M.A.Saunders, "Notes 6: LUSOL---a Basis Factorization Package," +* ibid. */ + +typedef struct LPF LPF; + +struct LPF +{ /* LP basis factorization */ + int valid; + /* the factorization is valid only if this flag is set */ + /*--------------------------------------------------------------*/ + /* initial basis matrix B0 */ + int m0_max; + /* maximal value of m0 (increased automatically, if necessary) */ + int m0; + /* the order of B0 */ +#if 0 /* 06/VI-2013 */ + LUF *luf; +#else + LUFINT *lufint; +#endif + /* LU-factorization of B0 */ + /*--------------------------------------------------------------*/ + /* current basis matrix B */ + int m; + /* the order of B */ + double *B; /* double B[1+m*m]; */ + /* B in dense format stored by rows and used only for debugging; + normally this array is not allocated */ + /*--------------------------------------------------------------*/ + /* augmented matrix (B0 F G H) of the order m0+n */ + int n_max; + /* maximal number of additional rows and columns */ + int n; + /* current number of additional rows and columns */ + /*--------------------------------------------------------------*/ + /* m0xn matrix R in column-wise format */ + int *R_ptr; /* int R_ptr[1+n_max]; */ + /* R_ptr[j], 1 <= j <= n, is a pointer to j-th column */ + int *R_len; /* int R_len[1+n_max]; */ + /* R_len[j], 1 <= j <= n, is the length of j-th column */ + /*--------------------------------------------------------------*/ + /* nxm0 matrix S in row-wise format */ + int *S_ptr; /* int S_ptr[1+n_max]; */ + /* S_ptr[i], 1 <= i <= n, is a pointer to i-th row */ + int *S_len; /* int S_len[1+n_max]; */ + /* S_len[i], 1 <= i <= n, is the length of i-th row */ + /*--------------------------------------------------------------*/ + /* Schur complement C of the order n */ +#if 0 /* 11/VIII-2013 */ + SCF *scf; /* SCF scf[1:n_max]; */ + /* factorization of the Schur complement */ +#else + IFU ifu; + /* IFU-factorization of the Schur complement */ + int t_opt; + /* type of transformation used to restore triangular structure of + matrix U: */ +#define SCF_TBG 1 /* Bartels-Golub elimination */ +#define SCF_TGR 2 /* Givens plane rotations */ +#endif + /*--------------------------------------------------------------*/ + /* matrix P of the order m0+n */ + int *P_row; /* int P_row[1+m0_max+n_max]; */ + /* P_row[i] = j means that P[i,j] = 1 */ + int *P_col; /* int P_col[1+m0_max+n_max]; */ + /* P_col[j] = i means that P[i,j] = 1 */ + /*--------------------------------------------------------------*/ + /* matrix Q of the order m0+n */ + int *Q_row; /* int Q_row[1+m0_max+n_max]; */ + /* Q_row[i] = j means that Q[i,j] = 1 */ + int *Q_col; /* int Q_col[1+m0_max+n_max]; */ + /* Q_col[j] = i means that Q[i,j] = 1 */ + /*--------------------------------------------------------------*/ + /* Sparse Vector Area (SVA) is a set of locations intended to + store sparse vectors which represent columns of matrix R and + rows of matrix S; each location is a doublet (ind, val), where + ind is an index, val is a numerical value of a sparse vector + element; in the whole each sparse vector is a set of adjacent + locations defined by a pointer to its first element and its + length, i.e. the number of its elements */ + int v_size; + /* the SVA size, in locations; locations are numbered by integers + 1, 2, ..., v_size, and location 0 is not used */ + int v_ptr; + /* pointer to the first available location */ + int *v_ind; /* int v_ind[1+v_size]; */ + /* v_ind[k], 1 <= k <= v_size, is the index field of location k */ + double *v_val; /* double v_val[1+v_size]; */ + /* v_val[k], 1 <= k <= v_size, is the value field of location k */ + /*--------------------------------------------------------------*/ + double *work1; /* double work1[1+m0+n_max]; */ + /* working array */ + double *work2; /* double work2[1+m0+n_max]; */ + /* working array */ +}; + +/* return codes: */ +#define LPF_ESING 1 /* singular matrix */ +#define LPF_ECOND 2 /* ill-conditioned matrix */ +#define LPF_ELIMIT 3 /* update limit reached */ + +#define lpf_create_it _glp_lpf_create_it +LPF *lpf_create_it(void); +/* create LP basis factorization */ + +#define lpf_factorize _glp_lpf_factorize +int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col) + (void *info, int j, int ind[], double val[]), void *info); +/* compute LP basis factorization */ + +#define lpf_ftran _glp_lpf_ftran +void lpf_ftran(LPF *lpf, double x[]); +/* perform forward transformation (solve system B*x = b) */ + +#define lpf_btran _glp_lpf_btran +void lpf_btran(LPF *lpf, double x[]); +/* perform backward transformation (solve system B'*x = b) */ + +#define lpf_update_it _glp_lpf_update_it +int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[], + const double val[]); +/* update LP basis factorization */ + +#define lpf_delete_it _glp_lpf_delete_it +void lpf_delete_it(LPF *lpf); +/* delete LP basis factorization */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpmat.c b/resources/3rdparty/glpk-4.53/src/glpmat.c new file mode 100644 index 000000000..97d1c6515 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpmat.c @@ -0,0 +1,924 @@ +/* glpmat.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpmat.h" +#include "qmd.h" +#include "amd.h" +#include "colamd.h" + +/*---------------------------------------------------------------------- +-- check_fvs - check sparse vector in full-vector storage format. +-- +-- SYNOPSIS +-- +-- #include "glpmat.h" +-- int check_fvs(int n, int nnz, int ind[], double vec[]); +-- +-- DESCRIPTION +-- +-- The routine check_fvs checks if a given vector of dimension n in +-- full-vector storage format has correct representation. +-- +-- RETURNS +-- +-- The routine returns one of the following codes: +-- +-- 0 - the vector is correct; +-- 1 - the number of elements (n) is negative; +-- 2 - the number of non-zero elements (nnz) is negative; +-- 3 - some element index is out of range; +-- 4 - some element index is duplicate; +-- 5 - some non-zero element is out of pattern. */ + +int check_fvs(int n, int nnz, int ind[], double vec[]) +{ int i, t, ret, *flag = NULL; + /* check the number of elements */ + if (n < 0) + { ret = 1; + goto done; + } + /* check the number of non-zero elements */ + if (nnz < 0) + { ret = 2; + goto done; + } + /* check vector indices */ + flag = xcalloc(1+n, sizeof(int)); + for (i = 1; i <= n; i++) flag[i] = 0; + for (t = 1; t <= nnz; t++) + { i = ind[t]; + if (!(1 <= i && i <= n)) + { ret = 3; + goto done; + } + if (flag[i]) + { ret = 4; + goto done; + } + flag[i] = 1; + } + /* check vector elements */ + for (i = 1; i <= n; i++) + { if (!flag[i] && vec[i] != 0.0) + { ret = 5; + goto done; + } + } + /* the vector is ok */ + ret = 0; +done: if (flag != NULL) xfree(flag); + return ret; +} + +/*---------------------------------------------------------------------- +-- check_pattern - check pattern of sparse matrix. +-- +-- SYNOPSIS +-- +-- #include "glpmat.h" +-- int check_pattern(int m, int n, int A_ptr[], int A_ind[]); +-- +-- DESCRIPTION +-- +-- The routine check_pattern checks the pattern of a given mxn matrix +-- in storage-by-rows format. +-- +-- RETURNS +-- +-- The routine returns one of the following codes: +-- +-- 0 - the pattern is correct; +-- 1 - the number of rows (m) is negative; +-- 2 - the number of columns (n) is negative; +-- 3 - A_ptr[1] is not 1; +-- 4 - some column index is out of range; +-- 5 - some column indices are duplicate. */ + +int check_pattern(int m, int n, int A_ptr[], int A_ind[]) +{ int i, j, ptr, ret, *flag = NULL; + /* check the number of rows */ + if (m < 0) + { ret = 1; + goto done; + } + /* check the number of columns */ + if (n < 0) + { ret = 2; + goto done; + } + /* check location A_ptr[1] */ + if (A_ptr[1] != 1) + { ret = 3; + goto done; + } + /* check row patterns */ + flag = xcalloc(1+n, sizeof(int)); + for (j = 1; j <= n; j++) flag[j] = 0; + for (i = 1; i <= m; i++) + { /* check pattern of row i */ + for (ptr = A_ptr[i]; ptr < A_ptr[i+1]; ptr++) + { j = A_ind[ptr]; + /* check column index */ + if (!(1 <= j && j <= n)) + { ret = 4; + goto done; + } + /* check for duplication */ + if (flag[j]) + { ret = 5; + goto done; + } + flag[j] = 1; + } + /* clear flags */ + for (ptr = A_ptr[i]; ptr < A_ptr[i+1]; ptr++) + { j = A_ind[ptr]; + flag[j] = 0; + } + } + /* the pattern is ok */ + ret = 0; +done: if (flag != NULL) xfree(flag); + return ret; +} + +/*---------------------------------------------------------------------- +-- transpose - transpose sparse matrix. +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- void transpose(int m, int n, int A_ptr[], int A_ind[], +-- double A_val[], int AT_ptr[], int AT_ind[], double AT_val[]); +-- +-- *Description* +-- +-- For a given mxn sparse matrix A the routine transpose builds a nxm +-- sparse matrix A' which is a matrix transposed to A. +-- +-- The arrays A_ptr, A_ind, and A_val specify a given mxn matrix A to +-- be transposed in storage-by-rows format. The parameter A_val can be +-- NULL, in which case numeric values are not copied. The arrays A_ptr, +-- A_ind, and A_val are not changed on exit. +-- +-- On entry the arrays AT_ptr, AT_ind, and AT_val must be allocated, +-- but their content is ignored. On exit the routine stores a resultant +-- nxm matrix A' in these arrays in storage-by-rows format. Note that +-- if the parameter A_val is NULL, the array AT_val is not used. +-- +-- The routine transpose has a side effect that elements in rows of the +-- resultant matrix A' follow in ascending their column indices. */ + +void transpose(int m, int n, int A_ptr[], int A_ind[], double A_val[], + int AT_ptr[], int AT_ind[], double AT_val[]) +{ int i, j, t, beg, end, pos, len; + /* determine row lengths of resultant matrix */ + for (j = 1; j <= n; j++) AT_ptr[j] = 0; + for (i = 1; i <= m; i++) + { beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) AT_ptr[A_ind[t]]++; + } + /* set up row pointers of resultant matrix */ + pos = 1; + for (j = 1; j <= n; j++) + len = AT_ptr[j], pos += len, AT_ptr[j] = pos; + AT_ptr[n+1] = pos; + /* build resultant matrix */ + for (i = m; i >= 1; i--) + { beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) + { pos = --AT_ptr[A_ind[t]]; + AT_ind[pos] = i; + if (A_val != NULL) AT_val[pos] = A_val[t]; + } + } + return; +} + +/*---------------------------------------------------------------------- +-- adat_symbolic - compute S = P*A*D*A'*P' (symbolic phase). +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- int *adat_symbolic(int m, int n, int P_per[], int A_ptr[], +-- int A_ind[], int S_ptr[]); +-- +-- *Description* +-- +-- The routine adat_symbolic implements the symbolic phase to compute +-- symmetric matrix S = P*A*D*A'*P', where P is a permutation matrix, +-- A is a given sparse matrix, D is a diagonal matrix, A' is a matrix +-- transposed to A, P' is an inverse of P. +-- +-- The parameter m is the number of rows in A and the order of P. +-- +-- The parameter n is the number of columns in A and the order of D. +-- +-- The array P_per specifies permutation matrix P. It is not changed on +-- exit. +-- +-- The arrays A_ptr and A_ind specify the pattern of matrix A. They are +-- not changed on exit. +-- +-- On exit the routine stores the pattern of upper triangular part of +-- matrix S without diagonal elements in the arrays S_ptr and S_ind in +-- storage-by-rows format. The array S_ptr should be allocated on entry, +-- however, its content is ignored. The array S_ind is allocated by the +-- routine itself which returns a pointer to it. +-- +-- *Returns* +-- +-- The routine returns a pointer to the array S_ind. */ + +int *adat_symbolic(int m, int n, int P_per[], int A_ptr[], int A_ind[], + int S_ptr[]) +{ int i, j, t, ii, jj, tt, k, size, len; + int *S_ind, *AT_ptr, *AT_ind, *ind, *map, *temp; + /* build the pattern of A', which is a matrix transposed to A, to + efficiently access A in column-wise manner */ + AT_ptr = xcalloc(1+n+1, sizeof(int)); + AT_ind = xcalloc(A_ptr[m+1], sizeof(int)); + transpose(m, n, A_ptr, A_ind, NULL, AT_ptr, AT_ind, NULL); + /* allocate the array S_ind */ + size = A_ptr[m+1] - 1; + if (size < m) size = m; + S_ind = xcalloc(1+size, sizeof(int)); + /* allocate and initialize working arrays */ + ind = xcalloc(1+m, sizeof(int)); + map = xcalloc(1+m, sizeof(int)); + for (jj = 1; jj <= m; jj++) map[jj] = 0; + /* compute pattern of S; note that symbolically S = B*B', where + B = P*A, B' is matrix transposed to B */ + S_ptr[1] = 1; + for (ii = 1; ii <= m; ii++) + { /* compute pattern of ii-th row of S */ + len = 0; + i = P_per[ii]; /* i-th row of A = ii-th row of B */ + for (t = A_ptr[i]; t < A_ptr[i+1]; t++) + { k = A_ind[t]; + /* walk through k-th column of A */ + for (tt = AT_ptr[k]; tt < AT_ptr[k+1]; tt++) + { j = AT_ind[tt]; + jj = P_per[m+j]; /* j-th row of A = jj-th row of B */ + /* a[i,k] != 0 and a[j,k] != 0 ergo s[ii,jj] != 0 */ + if (ii < jj && !map[jj]) ind[++len] = jj, map[jj] = 1; + } + } + /* now (ind) is pattern of ii-th row of S */ + S_ptr[ii+1] = S_ptr[ii] + len; + /* at least (S_ptr[ii+1] - 1) locations should be available in + the array S_ind */ + if (S_ptr[ii+1] - 1 > size) + { temp = S_ind; + size += size; + S_ind = xcalloc(1+size, sizeof(int)); + memcpy(&S_ind[1], &temp[1], (S_ptr[ii] - 1) * sizeof(int)); + xfree(temp); + } + xassert(S_ptr[ii+1] - 1 <= size); + /* (ii-th row of S) := (ind) */ + memcpy(&S_ind[S_ptr[ii]], &ind[1], len * sizeof(int)); + /* clear the row pattern map */ + for (t = 1; t <= len; t++) map[ind[t]] = 0; + } + /* free working arrays */ + xfree(AT_ptr); + xfree(AT_ind); + xfree(ind); + xfree(map); + /* reallocate the array S_ind to free unused locations */ + temp = S_ind; + size = S_ptr[m+1] - 1; + S_ind = xcalloc(1+size, sizeof(int)); + memcpy(&S_ind[1], &temp[1], size * sizeof(int)); + xfree(temp); + return S_ind; +} + +/*---------------------------------------------------------------------- +-- adat_numeric - compute S = P*A*D*A'*P' (numeric phase). +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- void adat_numeric(int m, int n, int P_per[], +-- int A_ptr[], int A_ind[], double A_val[], double D_diag[], +-- int S_ptr[], int S_ind[], double S_val[], double S_diag[]); +-- +-- *Description* +-- +-- The routine adat_numeric implements the numeric phase to compute +-- symmetric matrix S = P*A*D*A'*P', where P is a permutation matrix, +-- A is a given sparse matrix, D is a diagonal matrix, A' is a matrix +-- transposed to A, P' is an inverse of P. +-- +-- The parameter m is the number of rows in A and the order of P. +-- +-- The parameter n is the number of columns in A and the order of D. +-- +-- The matrix P is specified in the array P_per, which is not changed +-- on exit. +-- +-- The matrix A is specified in the arrays A_ptr, A_ind, and A_val in +-- storage-by-rows format. These arrays are not changed on exit. +-- +-- Diagonal elements of the matrix D are specified in the array D_diag, +-- where D_diag[0] is not used, D_diag[i] = d[i,i] for i = 1, ..., n. +-- The array D_diag is not changed on exit. +-- +-- The pattern of the upper triangular part of the matrix S without +-- diagonal elements (previously computed by the routine adat_symbolic) +-- is specified in the arrays S_ptr and S_ind, which are not changed on +-- exit. Numeric values of non-diagonal elements of S are stored in +-- corresponding locations of the array S_val, and values of diagonal +-- elements of S are stored in locations S_diag[1], ..., S_diag[n]. */ + +void adat_numeric(int m, int n, int P_per[], + int A_ptr[], int A_ind[], double A_val[], double D_diag[], + int S_ptr[], int S_ind[], double S_val[], double S_diag[]) +{ int i, j, t, ii, jj, tt, beg, end, beg1, end1, k; + double sum, *work; + work = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) work[j] = 0.0; + /* compute S = B*D*B', where B = P*A, B' is a matrix transposed + to B */ + for (ii = 1; ii <= m; ii++) + { i = P_per[ii]; /* i-th row of A = ii-th row of B */ + /* (work) := (i-th row of A) */ + beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) + work[A_ind[t]] = A_val[t]; + /* compute ii-th row of S */ + beg = S_ptr[ii], end = S_ptr[ii+1]; + for (t = beg; t < end; t++) + { jj = S_ind[t]; + j = P_per[jj]; /* j-th row of A = jj-th row of B */ + /* s[ii,jj] := sum a[i,k] * d[k,k] * a[j,k] */ + sum = 0.0; + beg1 = A_ptr[j], end1 = A_ptr[j+1]; + for (tt = beg1; tt < end1; tt++) + { k = A_ind[tt]; + sum += work[k] * D_diag[k] * A_val[tt]; + } + S_val[t] = sum; + } + /* s[ii,ii] := sum a[i,k] * d[k,k] * a[i,k] */ + sum = 0.0; + beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) + { k = A_ind[t]; + sum += A_val[t] * D_diag[k] * A_val[t]; + work[k] = 0.0; + } + S_diag[ii] = sum; + } + xfree(work); + return; +} + +/*---------------------------------------------------------------------- +-- min_degree - minimum degree ordering. +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- void min_degree(int n, int A_ptr[], int A_ind[], int P_per[]); +-- +-- *Description* +-- +-- The routine min_degree uses the minimum degree ordering algorithm +-- to find a permutation matrix P for a given sparse symmetric positive +-- matrix A which minimizes the number of non-zeros in upper triangular +-- factor U for Cholesky factorization P*A*P' = U'*U. +-- +-- The parameter n is the order of matrices A and P. +-- +-- The pattern of the given matrix A is specified on entry in the arrays +-- A_ptr and A_ind in storage-by-rows format. Only the upper triangular +-- part without diagonal elements (which all are assumed to be non-zero) +-- should be specified as if A were upper triangular. The arrays A_ptr +-- and A_ind are not changed on exit. +-- +-- The permutation matrix P is stored by the routine in the array P_per +-- on exit. +-- +-- *Algorithm* +-- +-- The routine min_degree is based on some subroutines from the package +-- SPARSPAK (see comments in the module glpqmd). */ + +void min_degree(int n, int A_ptr[], int A_ind[], int P_per[]) +{ int i, j, ne, t, pos, len; + int *xadj, *adjncy, *deg, *marker, *rchset, *nbrhd, *qsize, + *qlink, nofsub; + /* determine number of non-zeros in complete pattern */ + ne = A_ptr[n+1] - 1; + ne += ne; + /* allocate working arrays */ + xadj = xcalloc(1+n+1, sizeof(int)); + adjncy = xcalloc(1+ne, sizeof(int)); + deg = xcalloc(1+n, sizeof(int)); + marker = xcalloc(1+n, sizeof(int)); + rchset = xcalloc(1+n, sizeof(int)); + nbrhd = xcalloc(1+n, sizeof(int)); + qsize = xcalloc(1+n, sizeof(int)); + qlink = xcalloc(1+n, sizeof(int)); + /* determine row lengths in complete pattern */ + for (i = 1; i <= n; i++) xadj[i] = 0; + for (i = 1; i <= n; i++) + { for (t = A_ptr[i]; t < A_ptr[i+1]; t++) + { j = A_ind[t]; + xassert(i < j && j <= n); + xadj[i]++, xadj[j]++; + } + } + /* set up row pointers for complete pattern */ + pos = 1; + for (i = 1; i <= n; i++) + len = xadj[i], pos += len, xadj[i] = pos; + xadj[n+1] = pos; + xassert(pos - 1 == ne); + /* construct complete pattern */ + for (i = 1; i <= n; i++) + { for (t = A_ptr[i]; t < A_ptr[i+1]; t++) + { j = A_ind[t]; + adjncy[--xadj[i]] = j, adjncy[--xadj[j]] = i; + } + } + /* call the main minimimum degree ordering routine */ + genqmd(&n, xadj, adjncy, P_per, P_per + n, deg, marker, rchset, + nbrhd, qsize, qlink, &nofsub); + /* make sure that permutation matrix P is correct */ + for (i = 1; i <= n; i++) + { j = P_per[i]; + xassert(1 <= j && j <= n); + xassert(P_per[n+j] == i); + } + /* free working arrays */ + xfree(xadj); + xfree(adjncy); + xfree(deg); + xfree(marker); + xfree(rchset); + xfree(nbrhd); + xfree(qsize); + xfree(qlink); + return; +} + +/**********************************************************************/ + +void amd_order1(int n, int A_ptr[], int A_ind[], int P_per[]) +{ /* approximate minimum degree ordering (AMD) */ + int k, ret; + double Control[AMD_CONTROL], Info[AMD_INFO]; + /* get the default parameters */ + amd_defaults(Control); +#if 0 + /* and print them */ + amd_control(Control); +#endif + /* make all indices 0-based */ + for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]--; + for (k = 1; k <= n+1; k++) A_ptr[k]--; + /* call the ordering routine */ + ret = amd_order(n, &A_ptr[1], &A_ind[1], &P_per[1], Control, Info) + ; +#if 0 + amd_info(Info); +#endif + xassert(ret == AMD_OK || ret == AMD_OK_BUT_JUMBLED); + /* retsore 1-based indices */ + for (k = 1; k <= n+1; k++) A_ptr[k]++; + for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]++; + /* patch up permutation matrix */ + memset(&P_per[n+1], 0, n * sizeof(int)); + for (k = 1; k <= n; k++) + { P_per[k]++; + xassert(1 <= P_per[k] && P_per[k] <= n); + xassert(P_per[n+P_per[k]] == 0); + P_per[n+P_per[k]] = k; + } + return; +} + +/**********************************************************************/ + +static void *allocate(size_t n, size_t size) +{ void *ptr; + ptr = xcalloc(n, size); + memset(ptr, 0, n * size); + return ptr; +} + +static void release(void *ptr) +{ xfree(ptr); + return; +} + +void symamd_ord(int n, int A_ptr[], int A_ind[], int P_per[]) +{ /* approximate minimum degree ordering (SYMAMD) */ + int k, ok; + int stats[COLAMD_STATS]; + /* make all indices 0-based */ + for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]--; + for (k = 1; k <= n+1; k++) A_ptr[k]--; + /* call the ordering routine */ + ok = symamd(n, &A_ind[1], &A_ptr[1], &P_per[1], NULL, stats, + allocate, release); +#if 0 + symamd_report(stats); +#endif + xassert(ok); + /* restore 1-based indices */ + for (k = 1; k <= n+1; k++) A_ptr[k]++; + for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]++; + /* patch up permutation matrix */ + memset(&P_per[n+1], 0, n * sizeof(int)); + for (k = 1; k <= n; k++) + { P_per[k]++; + xassert(1 <= P_per[k] && P_per[k] <= n); + xassert(P_per[n+P_per[k]] == 0); + P_per[n+P_per[k]] = k; + } + return; +} + +/*---------------------------------------------------------------------- +-- chol_symbolic - compute Cholesky factorization (symbolic phase). +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- int *chol_symbolic(int n, int A_ptr[], int A_ind[], int U_ptr[]); +-- +-- *Description* +-- +-- The routine chol_symbolic implements the symbolic phase of Cholesky +-- factorization A = U'*U, where A is a given sparse symmetric positive +-- definite matrix, U is a resultant upper triangular factor, U' is a +-- matrix transposed to U. +-- +-- The parameter n is the order of matrices A and U. +-- +-- The pattern of the given matrix A is specified on entry in the arrays +-- A_ptr and A_ind in storage-by-rows format. Only the upper triangular +-- part without diagonal elements (which all are assumed to be non-zero) +-- should be specified as if A were upper triangular. The arrays A_ptr +-- and A_ind are not changed on exit. +-- +-- The pattern of the matrix U without diagonal elements (which all are +-- assumed to be non-zero) is stored on exit from the routine in the +-- arrays U_ptr and U_ind in storage-by-rows format. The array U_ptr +-- should be allocated on entry, however, its content is ignored. The +-- array U_ind is allocated by the routine which returns a pointer to it +-- on exit. +-- +-- *Returns* +-- +-- The routine returns a pointer to the array U_ind. +-- +-- *Method* +-- +-- The routine chol_symbolic computes the pattern of the matrix U in a +-- row-wise manner. No pivoting is used. +-- +-- It is known that to compute the pattern of row k of the matrix U we +-- need to merge the pattern of row k of the matrix A and the patterns +-- of each row i of U, where u[i,k] is non-zero (these rows are already +-- computed and placed above row k). +-- +-- However, to reduce the number of rows to be merged the routine uses +-- an advanced algorithm proposed in: +-- +-- D.J.Rose, R.E.Tarjan, and G.S.Lueker. Algorithmic aspects of vertex +-- elimination on graphs. SIAM J. Comput. 5, 1976, 266-83. +-- +-- The authors of the cited paper show that we have the same result if +-- we merge row k of the matrix A and such rows of the matrix U (among +-- rows 1, ..., k-1) whose leftmost non-diagonal non-zero element is +-- placed in k-th column. This feature signficantly reduces the number +-- of rows to be merged, especially on the final steps, where rows of +-- the matrix U become quite dense. +-- +-- To determine rows, which should be merged on k-th step, for a fixed +-- time the routine uses linked lists of row numbers of the matrix U. +-- Location head[k] contains the number of a first row, whose leftmost +-- non-diagonal non-zero element is placed in column k, and location +-- next[i] contains the number of a next row with the same property as +-- row i. */ + +int *chol_symbolic(int n, int A_ptr[], int A_ind[], int U_ptr[]) +{ int i, j, k, t, len, size, beg, end, min_j, *U_ind, *head, *next, + *ind, *map, *temp; + /* initially we assume that on computing the pattern of U fill-in + will double the number of non-zeros in A */ + size = A_ptr[n+1] - 1; + if (size < n) size = n; + size += size; + U_ind = xcalloc(1+size, sizeof(int)); + /* allocate and initialize working arrays */ + head = xcalloc(1+n, sizeof(int)); + for (i = 1; i <= n; i++) head[i] = 0; + next = xcalloc(1+n, sizeof(int)); + ind = xcalloc(1+n, sizeof(int)); + map = xcalloc(1+n, sizeof(int)); + for (j = 1; j <= n; j++) map[j] = 0; + /* compute the pattern of matrix U */ + U_ptr[1] = 1; + for (k = 1; k <= n; k++) + { /* compute the pattern of k-th row of U, which is the union of + k-th row of A and those rows of U (among 1, ..., k-1) whose + leftmost non-diagonal non-zero is placed in k-th column */ + /* (ind) := (k-th row of A) */ + len = A_ptr[k+1] - A_ptr[k]; + memcpy(&ind[1], &A_ind[A_ptr[k]], len * sizeof(int)); + for (t = 1; t <= len; t++) + { j = ind[t]; + xassert(k < j && j <= n); + map[j] = 1; + } + /* walk through rows of U whose leftmost non-diagonal non-zero + is placed in k-th column */ + for (i = head[k]; i != 0; i = next[i]) + { /* (ind) := (ind) union (i-th row of U) */ + beg = U_ptr[i], end = U_ptr[i+1]; + for (t = beg; t < end; t++) + { j = U_ind[t]; + if (j > k && !map[j]) ind[++len] = j, map[j] = 1; + } + } + /* now (ind) is the pattern of k-th row of U */ + U_ptr[k+1] = U_ptr[k] + len; + /* at least (U_ptr[k+1] - 1) locations should be available in + the array U_ind */ + if (U_ptr[k+1] - 1 > size) + { temp = U_ind; + size += size; + U_ind = xcalloc(1+size, sizeof(int)); + memcpy(&U_ind[1], &temp[1], (U_ptr[k] - 1) * sizeof(int)); + xfree(temp); + } + xassert(U_ptr[k+1] - 1 <= size); + /* (k-th row of U) := (ind) */ + memcpy(&U_ind[U_ptr[k]], &ind[1], len * sizeof(int)); + /* determine column index of leftmost non-diagonal non-zero in + k-th row of U and clear the row pattern map */ + min_j = n + 1; + for (t = 1; t <= len; t++) + { j = ind[t], map[j] = 0; + if (min_j > j) min_j = j; + } + /* include k-th row into corresponding linked list */ + if (min_j <= n) next[k] = head[min_j], head[min_j] = k; + } + /* free working arrays */ + xfree(head); + xfree(next); + xfree(ind); + xfree(map); + /* reallocate the array U_ind to free unused locations */ + temp = U_ind; + size = U_ptr[n+1] - 1; + U_ind = xcalloc(1+size, sizeof(int)); + memcpy(&U_ind[1], &temp[1], size * sizeof(int)); + xfree(temp); + return U_ind; +} + +/*---------------------------------------------------------------------- +-- chol_numeric - compute Cholesky factorization (numeric phase). +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- int chol_numeric(int n, +-- int A_ptr[], int A_ind[], double A_val[], double A_diag[], +-- int U_ptr[], int U_ind[], double U_val[], double U_diag[]); +-- +-- *Description* +-- +-- The routine chol_symbolic implements the numeric phase of Cholesky +-- factorization A = U'*U, where A is a given sparse symmetric positive +-- definite matrix, U is a resultant upper triangular factor, U' is a +-- matrix transposed to U. +-- +-- The parameter n is the order of matrices A and U. +-- +-- Upper triangular part of the matrix A without diagonal elements is +-- specified in the arrays A_ptr, A_ind, and A_val in storage-by-rows +-- format. Diagonal elements of A are specified in the array A_diag, +-- where A_diag[0] is not used, A_diag[i] = a[i,i] for i = 1, ..., n. +-- The arrays A_ptr, A_ind, A_val, and A_diag are not changed on exit. +-- +-- The pattern of the matrix U without diagonal elements (previously +-- computed with the routine chol_symbolic) is specified in the arrays +-- U_ptr and U_ind, which are not changed on exit. Numeric values of +-- non-diagonal elements of U are stored in corresponding locations of +-- the array U_val, and values of diagonal elements of U are stored in +-- locations U_diag[1], ..., U_diag[n]. +-- +-- *Returns* +-- +-- The routine returns the number of non-positive diagonal elements of +-- the matrix U which have been replaced by a huge positive number (see +-- the method description below). Zero return code means the matrix A +-- has been successfully factorized. +-- +-- *Method* +-- +-- The routine chol_numeric computes the matrix U in a row-wise manner +-- using standard gaussian elimination technique. No pivoting is used. +-- +-- Initially the routine sets U = A, and before k-th elimination step +-- the matrix U is the following: +-- +-- 1 k n +-- 1 x x x x x x x x x x +-- . x x x x x x x x x +-- . . x x x x x x x x +-- . . . x x x x x x x +-- k . . . . * * * * * * +-- . . . . * * * * * * +-- . . . . * * * * * * +-- . . . . * * * * * * +-- . . . . * * * * * * +-- n . . . . * * * * * * +-- +-- where 'x' are elements of already computed rows, '*' are elements of +-- the active submatrix. (Note that the lower triangular part of the +-- active submatrix being symmetric is not stored and diagonal elements +-- are stored separately in the array U_diag.) +-- +-- The matrix A is assumed to be positive definite. However, if it is +-- close to semi-definite, on some elimination step a pivot u[k,k] may +-- happen to be non-positive due to round-off errors. In this case the +-- routine uses a technique proposed in: +-- +-- S.J.Wright. The Cholesky factorization in interior-point and barrier +-- methods. Preprint MCS-P600-0596, Mathematics and Computer Science +-- Division, Argonne National Laboratory, Argonne, Ill., May 1996. +-- +-- The routine just replaces non-positive u[k,k] by a huge positive +-- number. This involves non-diagonal elements in k-th row of U to be +-- close to zero that, in turn, involves k-th component of a solution +-- vector to be close to zero. Note, however, that this technique works +-- only if the system A*x = b is consistent. */ + +int chol_numeric(int n, + int A_ptr[], int A_ind[], double A_val[], double A_diag[], + int U_ptr[], int U_ind[], double U_val[], double U_diag[]) +{ int i, j, k, t, t1, beg, end, beg1, end1, count = 0; + double ukk, uki, *work; + work = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) work[j] = 0.0; + /* U := (upper triangle of A) */ + /* note that the upper traingle of A is a subset of U */ + for (i = 1; i <= n; i++) + { beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) + j = A_ind[t], work[j] = A_val[t]; + beg = U_ptr[i], end = U_ptr[i+1]; + for (t = beg; t < end; t++) + j = U_ind[t], U_val[t] = work[j], work[j] = 0.0; + U_diag[i] = A_diag[i]; + } + /* main elimination loop */ + for (k = 1; k <= n; k++) + { /* transform k-th row of U */ + ukk = U_diag[k]; + if (ukk > 0.0) + U_diag[k] = ukk = sqrt(ukk); + else + U_diag[k] = ukk = DBL_MAX, count++; + /* (work) := (transformed k-th row) */ + beg = U_ptr[k], end = U_ptr[k+1]; + for (t = beg; t < end; t++) + work[U_ind[t]] = (U_val[t] /= ukk); + /* transform other rows of U */ + for (t = beg; t < end; t++) + { i = U_ind[t]; + xassert(i > k); + /* (i-th row) := (i-th row) - u[k,i] * (k-th row) */ + uki = work[i]; + beg1 = U_ptr[i], end1 = U_ptr[i+1]; + for (t1 = beg1; t1 < end1; t1++) + U_val[t1] -= uki * work[U_ind[t1]]; + U_diag[i] -= uki * uki; + } + /* (work) := 0 */ + for (t = beg; t < end; t++) + work[U_ind[t]] = 0.0; + } + xfree(work); + return count; +} + +/*---------------------------------------------------------------------- +-- u_solve - solve upper triangular system U*x = b. +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- void u_solve(int n, int U_ptr[], int U_ind[], double U_val[], +-- double U_diag[], double x[]); +-- +-- *Description* +-- +-- The routine u_solve solves an linear system U*x = b, where U is an +-- upper triangular matrix. +-- +-- The parameter n is the order of matrix U. +-- +-- The matrix U without diagonal elements is specified in the arrays +-- U_ptr, U_ind, and U_val in storage-by-rows format. Diagonal elements +-- of U are specified in the array U_diag, where U_diag[0] is not used, +-- U_diag[i] = u[i,i] for i = 1, ..., n. All these four arrays are not +-- changed on exit. +-- +-- The right-hand side vector b is specified on entry in the array x, +-- where x[0] is not used, and x[i] = b[i] for i = 1, ..., n. On exit +-- the routine stores computed components of the vector of unknowns x +-- in the array x in the same manner. */ + +void u_solve(int n, int U_ptr[], int U_ind[], double U_val[], + double U_diag[], double x[]) +{ int i, t, beg, end; + double temp; + for (i = n; i >= 1; i--) + { temp = x[i]; + beg = U_ptr[i], end = U_ptr[i+1]; + for (t = beg; t < end; t++) + temp -= U_val[t] * x[U_ind[t]]; + xassert(U_diag[i] != 0.0); + x[i] = temp / U_diag[i]; + } + return; +} + +/*---------------------------------------------------------------------- +-- ut_solve - solve lower triangular system U'*x = b. +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- void ut_solve(int n, int U_ptr[], int U_ind[], double U_val[], +-- double U_diag[], double x[]); +-- +-- *Description* +-- +-- The routine ut_solve solves an linear system U'*x = b, where U is a +-- matrix transposed to an upper triangular matrix. +-- +-- The parameter n is the order of matrix U. +-- +-- The matrix U without diagonal elements is specified in the arrays +-- U_ptr, U_ind, and U_val in storage-by-rows format. Diagonal elements +-- of U are specified in the array U_diag, where U_diag[0] is not used, +-- U_diag[i] = u[i,i] for i = 1, ..., n. All these four arrays are not +-- changed on exit. +-- +-- The right-hand side vector b is specified on entry in the array x, +-- where x[0] is not used, and x[i] = b[i] for i = 1, ..., n. On exit +-- the routine stores computed components of the vector of unknowns x +-- in the array x in the same manner. */ + +void ut_solve(int n, int U_ptr[], int U_ind[], double U_val[], + double U_diag[], double x[]) +{ int i, t, beg, end; + double temp; + for (i = 1; i <= n; i++) + { xassert(U_diag[i] != 0.0); + temp = (x[i] /= U_diag[i]); + if (temp == 0.0) continue; + beg = U_ptr[i], end = U_ptr[i+1]; + for (t = beg; t < end; t++) + x[U_ind[t]] -= U_val[t] * temp; + } + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpmat.h b/resources/3rdparty/glpk-4.53/src/glpmat.h new file mode 100644 index 000000000..5b0584371 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpmat.h @@ -0,0 +1,198 @@ +/* glpmat.h (linear algebra routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPMAT_H +#define GLPMAT_H + +/*********************************************************************** +* FULL-VECTOR STORAGE +* +* For a sparse vector x having n elements, ne of which are non-zero, +* the full-vector storage format uses two arrays x_ind and x_vec, which +* are set up as follows: +* +* x_ind is an integer array of length [1+ne]. Location x_ind[0] is +* not used, and locations x_ind[1], ..., x_ind[ne] contain indices of +* non-zero elements in vector x. +* +* x_vec is a floating-point array of length [1+n]. Location x_vec[0] +* is not used, and locations x_vec[1], ..., x_vec[n] contain numeric +* values of ALL elements in vector x, including its zero elements. +* +* Let, for example, the following sparse vector x be given: +* +* (0, 1, 0, 0, 2, 3, 0, 4) +* +* Then the arrays are: +* +* x_ind = { X; 2, 5, 6, 8 } +* +* x_vec = { X; 0, 1, 0, 0, 2, 3, 0, 4 } +* +* COMPRESSED-VECTOR STORAGE +* +* For a sparse vector x having n elements, ne of which are non-zero, +* the compressed-vector storage format uses two arrays x_ind and x_vec, +* which are set up as follows: +* +* x_ind is an integer array of length [1+ne]. Location x_ind[0] is +* not used, and locations x_ind[1], ..., x_ind[ne] contain indices of +* non-zero elements in vector x. +* +* x_vec is a floating-point array of length [1+ne]. Location x_vec[0] +* is not used, and locations x_vec[1], ..., x_vec[ne] contain numeric +* values of corresponding non-zero elements in vector x. +* +* Let, for example, the following sparse vector x be given: +* +* (0, 1, 0, 0, 2, 3, 0, 4) +* +* Then the arrays are: +* +* x_ind = { X; 2, 5, 6, 8 } +* +* x_vec = { X; 1, 2, 3, 4 } +* +* STORAGE-BY-ROWS +* +* For a sparse matrix A, which has m rows, n columns, and ne non-zero +* elements the storage-by-rows format uses three arrays A_ptr, A_ind, +* and A_val, which are set up as follows: +* +* A_ptr is an integer array of length [1+m+1] also called "row pointer +* array". It contains the relative starting positions of each row of A +* in the arrays A_ind and A_val, i.e. element A_ptr[i], 1 <= i <= m, +* indicates where row i begins in the arrays A_ind and A_val. If all +* elements in row i are zero, then A_ptr[i] = A_ptr[i+1]. Location +* A_ptr[0] is not used, location A_ptr[1] must contain 1, and location +* A_ptr[m+1] must contain ne+1 that indicates the position after the +* last element in the arrays A_ind and A_val. +* +* A_ind is an integer array of length [1+ne]. Location A_ind[0] is not +* used, and locations A_ind[1], ..., A_ind[ne] contain column indices +* of (non-zero) elements in matrix A. +* +* A_val is a floating-point array of length [1+ne]. Location A_val[0] +* is not used, and locations A_val[1], ..., A_val[ne] contain numeric +* values of non-zero elements in matrix A. +* +* Non-zero elements of matrix A are stored contiguously, and the rows +* of matrix A are stored consecutively from 1 to m in the arrays A_ind +* and A_val. The elements in each row of A may be stored in any order +* in A_ind and A_val. Note that elements with duplicate column indices +* are not allowed. +* +* Let, for example, the following sparse matrix A be given: +* +* | 11 . 13 . . . | +* | 21 22 . 24 . . | +* | . 32 33 . . . | +* | . . 43 44 . 46 | +* | . . . . . . | +* | 61 62 . . . 66 | +* +* Then the arrays are: +* +* A_ptr = { X; 1, 3, 6, 8, 11, 11; 14 } +* +* A_ind = { X; 1, 3; 4, 2, 1; 2, 3; 4, 3, 6; 1, 2, 6 } +* +* A_val = { X; 11, 13; 24, 22, 21; 32, 33; 44, 43, 46; 61, 62, 66 } +* +* PERMUTATION MATRICES +* +* Let P be a permutation matrix of the order n. It is represented as +* an integer array P_per of length [1+n+n] as follows: if p[i,j] = 1, +* then P_per[i] = j and P_per[n+j] = i. Location P_per[0] is not used. +* +* Let A' = P*A. If i-th row of A corresponds to i'-th row of A', then +* P_per[i'] = i and P_per[n+i] = i'. +* +* References: +* +* 1. Gustavson F.G. Some basic techniques for solving sparse systems of +* linear equations. In Rose and Willoughby (1972), pp. 41-52. +* +* 2. Basic Linear Algebra Subprograms Technical (BLAST) Forum Standard. +* University of Tennessee (2001). */ + +#define check_fvs _glp_mat_check_fvs +int check_fvs(int n, int nnz, int ind[], double vec[]); +/* check sparse vector in full-vector storage format */ + +#define check_pattern _glp_mat_check_pattern +int check_pattern(int m, int n, int A_ptr[], int A_ind[]); +/* check pattern of sparse matrix */ + +#define transpose _glp_mat_transpose +void transpose(int m, int n, int A_ptr[], int A_ind[], double A_val[], + int AT_ptr[], int AT_ind[], double AT_val[]); +/* transpose sparse matrix */ + +#define adat_symbolic _glp_mat_adat_symbolic +int *adat_symbolic(int m, int n, int P_per[], int A_ptr[], int A_ind[], + int S_ptr[]); +/* compute S = P*A*D*A'*P' (symbolic phase) */ + +#define adat_numeric _glp_mat_adat_numeric +void adat_numeric(int m, int n, int P_per[], + int A_ptr[], int A_ind[], double A_val[], double D_diag[], + int S_ptr[], int S_ind[], double S_val[], double S_diag[]); +/* compute S = P*A*D*A'*P' (numeric phase) */ + +#define min_degree _glp_mat_min_degree +void min_degree(int n, int A_ptr[], int A_ind[], int P_per[]); +/* minimum degree ordering */ + +#define amd_order1 _glp_mat_amd_order1 +void amd_order1(int n, int A_ptr[], int A_ind[], int P_per[]); +/* approximate minimum degree ordering (AMD) */ + +#define symamd_ord _glp_mat_symamd_ord +void symamd_ord(int n, int A_ptr[], int A_ind[], int P_per[]); +/* approximate minimum degree ordering (SYMAMD) */ + +#define chol_symbolic _glp_mat_chol_symbolic +int *chol_symbolic(int n, int A_ptr[], int A_ind[], int U_ptr[]); +/* compute Cholesky factorization (symbolic phase) */ + +#define chol_numeric _glp_mat_chol_numeric +int chol_numeric(int n, + int A_ptr[], int A_ind[], double A_val[], double A_diag[], + int U_ptr[], int U_ind[], double U_val[], double U_diag[]); +/* compute Cholesky factorization (numeric phase) */ + +#define u_solve _glp_mat_u_solve +void u_solve(int n, int U_ptr[], int U_ind[], double U_val[], + double U_diag[], double x[]); +/* solve upper triangular system U*x = b */ + +#define ut_solve _glp_mat_ut_solve +void ut_solve(int n, int U_ptr[], int U_ind[], double U_val[], + double U_diag[], double x[]); +/* solve lower triangular system U'*x = b */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl.h b/resources/3rdparty/glpk-4.53/src/glpmpl.h new file mode 100644 index 000000000..34445d30a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpmpl.h @@ -0,0 +1,2594 @@ +/* glpmpl.h (GNU MathProg translator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPMPL_H +#define GLPMPL_H + +#include "avl.h" +#include "dmp.h" +#include "env.h" +#include "misc.h" +#include "rng.h" + +#if 0 /* 22/I-2013 */ +typedef struct MPL MPL; +#else +typedef struct glp_tran MPL; +#endif +typedef char STRING; +typedef struct SYMBOL SYMBOL; +typedef struct TUPLE TUPLE; +typedef struct ARRAY ELEMSET; +typedef struct ELEMVAR ELEMVAR; +typedef struct FORMULA FORMULA; +typedef struct ELEMCON ELEMCON; +typedef union VALUE VALUE; +typedef struct ARRAY ARRAY; +typedef struct MEMBER MEMBER; +#if 1 +/* many C compilers have DOMAIN declared in <math.h> :( */ +#undef DOMAIN +#define DOMAIN DOMAIN1 +#endif +typedef struct DOMAIN DOMAIN; +typedef struct DOMAIN_BLOCK DOMAIN_BLOCK; +typedef struct DOMAIN_SLOT DOMAIN_SLOT; +typedef struct SET SET; +typedef struct WITHIN WITHIN; +typedef struct GADGET GADGET; +typedef struct PARAMETER PARAMETER; +typedef struct CONDITION CONDITION; +typedef struct VARIABLE VARIABLE; +typedef struct CONSTRAINT CONSTRAINT; +typedef struct TABLE TABLE; +typedef struct TABARG TABARG; +typedef struct TABFLD TABFLD; +typedef struct TABIN TABIN; +typedef struct TABOUT TABOUT; +typedef struct TABDCA TABDCA; +typedef union OPERANDS OPERANDS; +typedef struct ARG_LIST ARG_LIST; +typedef struct CODE CODE; +typedef struct CHECK CHECK; +typedef struct DISPLAY DISPLAY; +typedef struct DISPLAY1 DISPLAY1; +typedef struct PRINTF PRINTF; +typedef struct PRINTF1 PRINTF1; +typedef struct FOR FOR; +typedef struct STATEMENT STATEMENT; +typedef struct TUPLE SLICE; + +/**********************************************************************/ +/* * * TRANSLATOR DATABASE * * */ +/**********************************************************************/ + +#define A_BINARY 101 /* something binary */ +#define A_CHECK 102 /* check statement */ +#define A_CONSTRAINT 103 /* model constraint */ +#define A_DISPLAY 104 /* display statement */ +#define A_ELEMCON 105 /* elemental constraint/objective */ +#define A_ELEMSET 106 /* elemental set */ +#define A_ELEMVAR 107 /* elemental variable */ +#define A_EXPRESSION 108 /* expression */ +#define A_FOR 109 /* for statement */ +#define A_FORMULA 110 /* formula */ +#define A_INDEX 111 /* dummy index */ +#define A_INPUT 112 /* input table */ +#define A_INTEGER 113 /* something integer */ +#define A_LOGICAL 114 /* something logical */ +#define A_MAXIMIZE 115 /* objective has to be maximized */ +#define A_MINIMIZE 116 /* objective has to be minimized */ +#define A_NONE 117 /* nothing */ +#define A_NUMERIC 118 /* something numeric */ +#define A_OUTPUT 119 /* output table */ +#define A_PARAMETER 120 /* model parameter */ +#define A_PRINTF 121 /* printf statement */ +#define A_SET 122 /* model set */ +#define A_SOLVE 123 /* solve statement */ +#define A_SYMBOLIC 124 /* something symbolic */ +#define A_TABLE 125 /* data table */ +#define A_TUPLE 126 /* n-tuple */ +#define A_VARIABLE 127 /* model variable */ + +#define MAX_LENGTH 100 +/* maximal length of any symbolic value (this includes symbolic names, + numeric and string literals, and all symbolic values that may appear + during the evaluation phase) */ + +#define CONTEXT_SIZE 60 +/* size of the context queue, in characters */ + +#define OUTBUF_SIZE 1024 +/* size of the output buffer, in characters */ + +#if 0 /* 22/I-2013 */ +struct MPL +#else +struct glp_tran +#endif +{ /* translator database */ + /*--------------------------------------------------------------*/ + /* scanning segment */ + int line; + /* number of the current text line */ + int c; + /* the current character or EOF */ + int token; + /* the current token: */ +#define T_EOF 201 /* end of file */ +#define T_NAME 202 /* symbolic name (model section only) */ +#define T_SYMBOL 203 /* symbol (data section only) */ +#define T_NUMBER 204 /* numeric literal */ +#define T_STRING 205 /* string literal */ +#define T_AND 206 /* and && */ +#define T_BY 207 /* by */ +#define T_CROSS 208 /* cross */ +#define T_DIFF 209 /* diff */ +#define T_DIV 210 /* div */ +#define T_ELSE 211 /* else */ +#define T_IF 212 /* if */ +#define T_IN 213 /* in */ +#define T_INFINITY 214 /* Infinity */ +#define T_INTER 215 /* inter */ +#define T_LESS 216 /* less */ +#define T_MOD 217 /* mod */ +#define T_NOT 218 /* not ! */ +#define T_OR 219 /* or || */ +#define T_SPTP 220 /* s.t. */ +#define T_SYMDIFF 221 /* symdiff */ +#define T_THEN 222 /* then */ +#define T_UNION 223 /* union */ +#define T_WITHIN 224 /* within */ +#define T_PLUS 225 /* + */ +#define T_MINUS 226 /* - */ +#define T_ASTERISK 227 /* * */ +#define T_SLASH 228 /* / */ +#define T_POWER 229 /* ^ ** */ +#define T_LT 230 /* < */ +#define T_LE 231 /* <= */ +#define T_EQ 232 /* = == */ +#define T_GE 233 /* >= */ +#define T_GT 234 /* > */ +#define T_NE 235 /* <> != */ +#define T_CONCAT 236 /* & */ +#define T_BAR 237 /* | */ +#define T_POINT 238 /* . */ +#define T_COMMA 239 /* , */ +#define T_COLON 240 /* : */ +#define T_SEMICOLON 241 /* ; */ +#define T_ASSIGN 242 /* := */ +#define T_DOTS 243 /* .. */ +#define T_LEFT 244 /* ( */ +#define T_RIGHT 245 /* ) */ +#define T_LBRACKET 246 /* [ */ +#define T_RBRACKET 247 /* ] */ +#define T_LBRACE 248 /* { */ +#define T_RBRACE 249 /* } */ +#define T_APPEND 250 /* >> */ +#define T_TILDE 251 /* ~ */ +#define T_INPUT 252 /* <- */ + int imlen; + /* length of the current token */ + char *image; /* char image[MAX_LENGTH+1]; */ + /* image of the current token */ + double value; + /* value of the current token (for T_NUMBER only) */ + int b_token; + /* the previous token */ + int b_imlen; + /* length of the previous token */ + char *b_image; /* char b_image[MAX_LENGTH+1]; */ + /* image of the previous token */ + double b_value; + /* value of the previous token (if token is T_NUMBER) */ + int f_dots; + /* if this flag is set, the next token should be recognized as + T_DOTS, not as T_POINT */ + int f_scan; + /* if this flag is set, the next token is already scanned */ + int f_token; + /* the next token */ + int f_imlen; + /* length of the next token */ + char *f_image; /* char f_image[MAX_LENGTH+1]; */ + /* image of the next token */ + double f_value; + /* value of the next token (if token is T_NUMBER) */ + char *context; /* char context[CONTEXT_SIZE]; */ + /* context circular queue (not null-terminated!) */ + int c_ptr; + /* pointer to the current position in the context queue */ + int flag_d; + /* if this flag is set, the data section is being processed */ + /*--------------------------------------------------------------*/ + /* translating segment */ + DMP *pool; + /* memory pool used to allocate all data instances created during + the translation phase */ + AVL *tree; + /* symbolic name table: + node.type = A_INDEX => node.link -> DOMAIN_SLOT + node.type = A_SET => node.link -> SET + node.type = A_PARAMETER => node.link -> PARAMETER + node.type = A_VARIABLE => node.link -> VARIABLE + node.type = A_CONSTRANT => node.link -> CONSTRAINT */ + STATEMENT *model; + /* linked list of model statements in the original order */ + int flag_x; + /* if this flag is set, the current token being left parenthesis + begins a slice that allows recognizing any undeclared symbolic + names as dummy indices; this flag is automatically reset once + the next token has been scanned */ + int as_within; + /* the warning "in understood as within" has been issued */ + int as_in; + /* the warning "within understood as in" has been issued */ + int as_binary; + /* the warning "logical understood as binary" has been issued */ + int flag_s; + /* if this flag is set, the solve statement has been parsed */ + /*--------------------------------------------------------------*/ + /* common segment */ + DMP *strings; + /* memory pool to allocate STRING data structures */ + DMP *symbols; + /* memory pool to allocate SYMBOL data structures */ + DMP *tuples; + /* memory pool to allocate TUPLE data structures */ + DMP *arrays; + /* memory pool to allocate ARRAY data structures */ + DMP *members; + /* memory pool to allocate MEMBER data structures */ + DMP *elemvars; + /* memory pool to allocate ELEMVAR data structures */ + DMP *formulae; + /* memory pool to allocate FORMULA data structures */ + DMP *elemcons; + /* memory pool to allocate ELEMCON data structures */ + ARRAY *a_list; + /* linked list of all arrays in the database */ + char *sym_buf; /* char sym_buf[255+1]; */ + /* working buffer used by the routine format_symbol */ + char *tup_buf; /* char tup_buf[255+1]; */ + /* working buffer used by the routine format_tuple */ + /*--------------------------------------------------------------*/ + /* generating/postsolving segment */ + RNG *rand; + /* pseudo-random number generator */ + int flag_p; + /* if this flag is set, the postsolving phase is in effect */ + STATEMENT *stmt; + /* model statement being currently executed */ + TABDCA *dca; + /* pointer to table driver communication area for table statement + currently executed */ + int m; + /* number of rows in the problem, m >= 0 */ + int n; + /* number of columns in the problem, n >= 0 */ + ELEMCON **row; /* ELEMCON *row[1+m]; */ + /* row[0] is not used; + row[i] is elemental constraint or objective, which corresponds + to i-th row of the problem, 1 <= i <= m */ + ELEMVAR **col; /* ELEMVAR *col[1+n]; */ + /* col[0] is not used; + col[j] is elemental variable, which corresponds to j-th column + of the problem, 1 <= j <= n */ + /*--------------------------------------------------------------*/ + /* input/output segment */ + glp_file *in_fp; + /* stream assigned to the input text file */ + char *in_file; + /* name of the input text file */ + glp_file *out_fp; + /* stream assigned to the output text file used to write all data + produced by display and printf statements; NULL means the data + should be sent to stdout via the routine xprintf */ + char *out_file; + /* name of the output text file */ +#if 0 /* 08/XI-2009 */ + char *out_buf; /* char out_buf[OUTBUF_SIZE] */ + /* buffer to accumulate output data */ + int out_cnt; + /* count of data bytes stored in the output buffer */ +#endif + glp_file *prt_fp; + /* stream assigned to the print text file; may be NULL */ + char *prt_file; + /* name of the output print file */ + /*--------------------------------------------------------------*/ + /* solver interface segment */ + jmp_buf jump; + /* jump address for non-local go to in case of error */ + int phase; + /* phase of processing: + 0 - database is being or has been initialized + 1 - model section is being or has been read + 2 - data section is being or has been read + 3 - model is being or has been generated/postsolved + 4 - model processing error has occurred */ + char *mod_file; + /* name of the input text file, which contains model section */ + char *mpl_buf; /* char mpl_buf[255+1]; */ + /* working buffer used by some interface routines */ +}; + +/**********************************************************************/ +/* * * PROCESSING MODEL SECTION * * */ +/**********************************************************************/ + +#define alloc(type) ((type *)dmp_get_atomv(mpl->pool, sizeof(type))) +/* allocate atom of given type */ + +#define enter_context _glp_mpl_enter_context +void enter_context(MPL *mpl); +/* enter current token into context queue */ + +#define print_context _glp_mpl_print_context +void print_context(MPL *mpl); +/* print current content of context queue */ + +#define get_char _glp_mpl_get_char +void get_char(MPL *mpl); +/* scan next character from input text file */ + +#define append_char _glp_mpl_append_char +void append_char(MPL *mpl); +/* append character to current token */ + +#define get_token _glp_mpl_get_token +void get_token(MPL *mpl); +/* scan next token from input text file */ + +#define unget_token _glp_mpl_unget_token +void unget_token(MPL *mpl); +/* return current token back to input stream */ + +#define is_keyword _glp_mpl_is_keyword +int is_keyword(MPL *mpl, char *keyword); +/* check if current token is given non-reserved keyword */ + +#define is_reserved _glp_mpl_is_reserved +int is_reserved(MPL *mpl); +/* check if current token is reserved keyword */ + +#define make_code _glp_mpl_make_code +CODE *make_code(MPL *mpl, int op, OPERANDS *arg, int type, int dim); +/* generate pseudo-code (basic routine) */ + +#define make_unary _glp_mpl_make_unary +CODE *make_unary(MPL *mpl, int op, CODE *x, int type, int dim); +/* generate pseudo-code for unary operation */ + +#define make_binary _glp_mpl_make_binary +CODE *make_binary(MPL *mpl, int op, CODE *x, CODE *y, int type, + int dim); +/* generate pseudo-code for binary operation */ + +#define make_ternary _glp_mpl_make_ternary +CODE *make_ternary(MPL *mpl, int op, CODE *x, CODE *y, CODE *z, + int type, int dim); +/* generate pseudo-code for ternary operation */ + +#define numeric_literal _glp_mpl_numeric_literal +CODE *numeric_literal(MPL *mpl); +/* parse reference to numeric literal */ + +#define string_literal _glp_mpl_string_literal +CODE *string_literal(MPL *mpl); +/* parse reference to string literal */ + +#define create_arg_list _glp_mpl_create_arg_list +ARG_LIST *create_arg_list(MPL *mpl); +/* create empty operands list */ + +#define expand_arg_list _glp_mpl_expand_arg_list +ARG_LIST *expand_arg_list(MPL *mpl, ARG_LIST *list, CODE *x); +/* append operand to operands list */ + +#define arg_list_len _glp_mpl_arg_list_len +int arg_list_len(MPL *mpl, ARG_LIST *list); +/* determine length of operands list */ + +#define subscript_list _glp_mpl_subscript_list +ARG_LIST *subscript_list(MPL *mpl); +/* parse subscript list */ + +#define object_reference _glp_mpl_object_reference +CODE *object_reference(MPL *mpl); +/* parse reference to named object */ + +#define numeric_argument _glp_mpl_numeric_argument +CODE *numeric_argument(MPL *mpl, char *func); +/* parse argument passed to built-in function */ + +#define symbolic_argument _glp_mpl_symbolic_argument +CODE *symbolic_argument(MPL *mpl, char *func); + +#define elemset_argument _glp_mpl_elemset_argument +CODE *elemset_argument(MPL *mpl, char *func); + +#define function_reference _glp_mpl_function_reference +CODE *function_reference(MPL *mpl); +/* parse reference to built-in function */ + +#define create_domain _glp_mpl_create_domain +DOMAIN *create_domain(MPL *mpl); +/* create empty domain */ + +#define create_block _glp_mpl_create_block +DOMAIN_BLOCK *create_block(MPL *mpl); +/* create empty domain block */ + +#define append_block _glp_mpl_append_block +void append_block(MPL *mpl, DOMAIN *domain, DOMAIN_BLOCK *block); +/* append domain block to specified domain */ + +#define append_slot _glp_mpl_append_slot +DOMAIN_SLOT *append_slot(MPL *mpl, DOMAIN_BLOCK *block, char *name, + CODE *code); +/* create and append new slot to domain block */ + +#define expression_list _glp_mpl_expression_list +CODE *expression_list(MPL *mpl); +/* parse expression list */ + +#define literal_set _glp_mpl_literal_set +CODE *literal_set(MPL *mpl, CODE *code); +/* parse literal set */ + +#define indexing_expression _glp_mpl_indexing_expression +DOMAIN *indexing_expression(MPL *mpl); +/* parse indexing expression */ + +#define close_scope _glp_mpl_close_scope +void close_scope(MPL *mpl, DOMAIN *domain); +/* close scope of indexing expression */ + +#define iterated_expression _glp_mpl_iterated_expression +CODE *iterated_expression(MPL *mpl); +/* parse iterated expression */ + +#define domain_arity _glp_mpl_domain_arity +int domain_arity(MPL *mpl, DOMAIN *domain); +/* determine arity of domain */ + +#define set_expression _glp_mpl_set_expression +CODE *set_expression(MPL *mpl); +/* parse set expression */ + +#define branched_expression _glp_mpl_branched_expression +CODE *branched_expression(MPL *mpl); +/* parse conditional expression */ + +#define primary_expression _glp_mpl_primary_expression +CODE *primary_expression(MPL *mpl); +/* parse primary expression */ + +#define error_preceding _glp_mpl_error_preceding +void error_preceding(MPL *mpl, char *opstr); +/* raise error if preceding operand has wrong type */ + +#define error_following _glp_mpl_error_following +void error_following(MPL *mpl, char *opstr); +/* raise error if following operand has wrong type */ + +#define error_dimension _glp_mpl_error_dimension +void error_dimension(MPL *mpl, char *opstr, int dim1, int dim2); +/* raise error if operands have different dimension */ + +#define expression_0 _glp_mpl_expression_0 +CODE *expression_0(MPL *mpl); +/* parse expression of level 0 */ + +#define expression_1 _glp_mpl_expression_1 +CODE *expression_1(MPL *mpl); +/* parse expression of level 1 */ + +#define expression_2 _glp_mpl_expression_2 +CODE *expression_2(MPL *mpl); +/* parse expression of level 2 */ + +#define expression_3 _glp_mpl_expression_3 +CODE *expression_3(MPL *mpl); +/* parse expression of level 3 */ + +#define expression_4 _glp_mpl_expression_4 +CODE *expression_4(MPL *mpl); +/* parse expression of level 4 */ + +#define expression_5 _glp_mpl_expression_5 +CODE *expression_5(MPL *mpl); +/* parse expression of level 5 */ + +#define expression_6 _glp_mpl_expression_6 +CODE *expression_6(MPL *mpl); +/* parse expression of level 6 */ + +#define expression_7 _glp_mpl_expression_7 +CODE *expression_7(MPL *mpl); +/* parse expression of level 7 */ + +#define expression_8 _glp_mpl_expression_8 +CODE *expression_8(MPL *mpl); +/* parse expression of level 8 */ + +#define expression_9 _glp_mpl_expression_9 +CODE *expression_9(MPL *mpl); +/* parse expression of level 9 */ + +#define expression_10 _glp_mpl_expression_10 +CODE *expression_10(MPL *mpl); +/* parse expression of level 10 */ + +#define expression_11 _glp_mpl_expression_11 +CODE *expression_11(MPL *mpl); +/* parse expression of level 11 */ + +#define expression_12 _glp_mpl_expression_12 +CODE *expression_12(MPL *mpl); +/* parse expression of level 12 */ + +#define expression_13 _glp_mpl_expression_13 +CODE *expression_13(MPL *mpl); +/* parse expression of level 13 */ + +#define set_statement _glp_mpl_set_statement +SET *set_statement(MPL *mpl); +/* parse set statement */ + +#define parameter_statement _glp_mpl_parameter_statement +PARAMETER *parameter_statement(MPL *mpl); +/* parse parameter statement */ + +#define variable_statement _glp_mpl_variable_statement +VARIABLE *variable_statement(MPL *mpl); +/* parse variable statement */ + +#define constraint_statement _glp_mpl_constraint_statement +CONSTRAINT *constraint_statement(MPL *mpl); +/* parse constraint statement */ + +#define objective_statement _glp_mpl_objective_statement +CONSTRAINT *objective_statement(MPL *mpl); +/* parse objective statement */ + +#define table_statement _glp_mpl_table_statement +TABLE *table_statement(MPL *mpl); +/* parse table statement */ + +#define solve_statement _glp_mpl_solve_statement +void *solve_statement(MPL *mpl); +/* parse solve statement */ + +#define check_statement _glp_mpl_check_statement +CHECK *check_statement(MPL *mpl); +/* parse check statement */ + +#define display_statement _glp_mpl_display_statement +DISPLAY *display_statement(MPL *mpl); +/* parse display statement */ + +#define printf_statement _glp_mpl_printf_statement +PRINTF *printf_statement(MPL *mpl); +/* parse printf statement */ + +#define for_statement _glp_mpl_for_statement +FOR *for_statement(MPL *mpl); +/* parse for statement */ + +#define end_statement _glp_mpl_end_statement +void end_statement(MPL *mpl); +/* parse end statement */ + +#define simple_statement _glp_mpl_simple_statement +STATEMENT *simple_statement(MPL *mpl, int spec); +/* parse simple statement */ + +#define model_section _glp_mpl_model_section +void model_section(MPL *mpl); +/* parse model section */ + +/**********************************************************************/ +/* * * PROCESSING DATA SECTION * * */ +/**********************************************************************/ + +#if 2 + 2 == 5 +struct SLICE /* see TUPLE */ +{ /* component of slice; the slice itself is associated with its + first component; slices are similar to n-tuples with exception + that some slice components (which are indicated by asterisks) + don't refer to any symbols */ + SYMBOL *sym; + /* symbol, which this component refers to; can be NULL */ + SLICE *next; + /* the next component of slice */ +}; +#endif + +#define create_slice _glp_mpl_create_slice +SLICE *create_slice(MPL *mpl); +/* create slice */ + +#define expand_slice _glp_mpl_expand_slice +SLICE *expand_slice +( MPL *mpl, + SLICE *slice, /* destroyed */ + SYMBOL *sym /* destroyed */ +); +/* append new component to slice */ + +#define slice_dimen _glp_mpl_slice_dimen +int slice_dimen +( MPL *mpl, + SLICE *slice /* not changed */ +); +/* determine dimension of slice */ + +#define slice_arity _glp_mpl_slice_arity +int slice_arity +( MPL *mpl, + SLICE *slice /* not changed */ +); +/* determine arity of slice */ + +#define fake_slice _glp_mpl_fake_slice +SLICE *fake_slice(MPL *mpl, int dim); +/* create fake slice of all asterisks */ + +#define delete_slice _glp_mpl_delete_slice +void delete_slice +( MPL *mpl, + SLICE *slice /* destroyed */ +); +/* delete slice */ + +#define is_number _glp_mpl_is_number +int is_number(MPL *mpl); +/* check if current token is number */ + +#define is_symbol _glp_mpl_is_symbol +int is_symbol(MPL *mpl); +/* check if current token is symbol */ + +#define is_literal _glp_mpl_is_literal +int is_literal(MPL *mpl, char *literal); +/* check if current token is given symbolic literal */ + +#define read_number _glp_mpl_read_number +double read_number(MPL *mpl); +/* read number */ + +#define read_symbol _glp_mpl_read_symbol +SYMBOL *read_symbol(MPL *mpl); +/* read symbol */ + +#define read_slice _glp_mpl_read_slice +SLICE *read_slice +( MPL *mpl, + char *name, /* not changed */ + int dim +); +/* read slice */ + +#define select_set _glp_mpl_select_set +SET *select_set +( MPL *mpl, + char *name /* not changed */ +); +/* select set to saturate it with elemental sets */ + +#define simple_format _glp_mpl_simple_format +void simple_format +( MPL *mpl, + SET *set, /* not changed */ + MEMBER *memb, /* modified */ + SLICE *slice /* not changed */ +); +/* read set data block in simple format */ + +#define matrix_format _glp_mpl_matrix_format +void matrix_format +( MPL *mpl, + SET *set, /* not changed */ + MEMBER *memb, /* modified */ + SLICE *slice, /* not changed */ + int tr +); +/* read set data block in matrix format */ + +#define set_data _glp_mpl_set_data +void set_data(MPL *mpl); +/* read set data */ + +#define select_parameter _glp_mpl_select_parameter +PARAMETER *select_parameter +( MPL *mpl, + char *name /* not changed */ +); +/* select parameter to saturate it with data */ + +#define set_default _glp_mpl_set_default +void set_default +( MPL *mpl, + PARAMETER *par, /* not changed */ + SYMBOL *altval /* destroyed */ +); +/* set default parameter value */ + +#define read_value _glp_mpl_read_value +MEMBER *read_value +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* destroyed */ +); +/* read value and assign it to parameter member */ + +#define plain_format _glp_mpl_plain_format +void plain_format +( MPL *mpl, + PARAMETER *par, /* not changed */ + SLICE *slice /* not changed */ +); +/* read parameter data block in plain format */ + +#define tabular_format _glp_mpl_tabular_format +void tabular_format +( MPL *mpl, + PARAMETER *par, /* not changed */ + SLICE *slice, /* not changed */ + int tr +); +/* read parameter data block in tabular format */ + +#define tabbing_format _glp_mpl_tabbing_format +void tabbing_format +( MPL *mpl, + SYMBOL *altval /* not changed */ +); +/* read parameter data block in tabbing format */ + +#define parameter_data _glp_mpl_parameter_data +void parameter_data(MPL *mpl); +/* read parameter data */ + +#define data_section _glp_mpl_data_section +void data_section(MPL *mpl); +/* read data section */ + +/**********************************************************************/ +/* * * FLOATING-POINT NUMBERS * * */ +/**********************************************************************/ + +#define fp_add _glp_mpl_fp_add +double fp_add(MPL *mpl, double x, double y); +/* floating-point addition */ + +#define fp_sub _glp_mpl_fp_sub +double fp_sub(MPL *mpl, double x, double y); +/* floating-point subtraction */ + +#define fp_less _glp_mpl_fp_less +double fp_less(MPL *mpl, double x, double y); +/* floating-point non-negative subtraction */ + +#define fp_mul _glp_mpl_fp_mul +double fp_mul(MPL *mpl, double x, double y); +/* floating-point multiplication */ + +#define fp_div _glp_mpl_fp_div +double fp_div(MPL *mpl, double x, double y); +/* floating-point division */ + +#define fp_idiv _glp_mpl_fp_idiv +double fp_idiv(MPL *mpl, double x, double y); +/* floating-point quotient of exact division */ + +#define fp_mod _glp_mpl_fp_mod +double fp_mod(MPL *mpl, double x, double y); +/* floating-point remainder of exact division */ + +#define fp_power _glp_mpl_fp_power +double fp_power(MPL *mpl, double x, double y); +/* floating-point exponentiation (raise to power) */ + +#define fp_exp _glp_mpl_fp_exp +double fp_exp(MPL *mpl, double x); +/* floating-point base-e exponential */ + +#define fp_log _glp_mpl_fp_log +double fp_log(MPL *mpl, double x); +/* floating-point natural logarithm */ + +#define fp_log10 _glp_mpl_fp_log10 +double fp_log10(MPL *mpl, double x); +/* floating-point common (decimal) logarithm */ + +#define fp_sqrt _glp_mpl_fp_sqrt +double fp_sqrt(MPL *mpl, double x); +/* floating-point square root */ + +#define fp_sin _glp_mpl_fp_sin +double fp_sin(MPL *mpl, double x); +/* floating-point trigonometric sine */ + +#define fp_cos _glp_mpl_fp_cos +double fp_cos(MPL *mpl, double x); +/* floating-point trigonometric cosine */ + +#define fp_atan _glp_mpl_fp_atan +double fp_atan(MPL *mpl, double x); +/* floating-point trigonometric arctangent */ + +#define fp_atan2 _glp_mpl_fp_atan2 +double fp_atan2(MPL *mpl, double y, double x); +/* floating-point trigonometric arctangent */ + +#define fp_round _glp_mpl_fp_round +double fp_round(MPL *mpl, double x, double n); +/* round floating-point value to n fractional digits */ + +#define fp_trunc _glp_mpl_fp_trunc +double fp_trunc(MPL *mpl, double x, double n); +/* truncate floating-point value to n fractional digits */ + +/**********************************************************************/ +/* * * PSEUDO-RANDOM NUMBER GENERATORS * * */ +/**********************************************************************/ + +#define fp_irand224 _glp_mpl_fp_irand224 +double fp_irand224(MPL *mpl); +/* pseudo-random integer in the range [0, 2^24) */ + +#define fp_uniform01 _glp_mpl_fp_uniform01 +double fp_uniform01(MPL *mpl); +/* pseudo-random number in the range [0, 1) */ + +#define fp_uniform _glp_mpl_uniform +double fp_uniform(MPL *mpl, double a, double b); +/* pseudo-random number in the range [a, b) */ + +#define fp_normal01 _glp_mpl_fp_normal01 +double fp_normal01(MPL *mpl); +/* Gaussian random variate with mu = 0 and sigma = 1 */ + +#define fp_normal _glp_mpl_fp_normal +double fp_normal(MPL *mpl, double mu, double sigma); +/* Gaussian random variate with specified mu and sigma */ + +/**********************************************************************/ +/* * * DATE/TIME * * */ +/**********************************************************************/ + +#define fn_gmtime _glp_mpl_fn_gmtime +double fn_gmtime(MPL *mpl); +/* obtain the current calendar time (UTC) */ + +#define fn_str2time _glp_mpl_fn_str2time +double fn_str2time(MPL *mpl, const char *str, const char *fmt); +/* convert character string to the calendar time */ + +#define fn_time2str _glp_mpl_fn_time2str +void fn_time2str(MPL *mpl, char *str, double t, const char *fmt); +/* convert the calendar time to character string */ + +/**********************************************************************/ +/* * * CHARACTER STRINGS * * */ +/**********************************************************************/ + +#define create_string _glp_mpl_create_string +STRING *create_string +( MPL *mpl, + char buf[MAX_LENGTH+1] /* not changed */ +); +/* create character string */ + +#define copy_string _glp_mpl_copy_string +STRING *copy_string +( MPL *mpl, + STRING *str /* not changed */ +); +/* make copy of character string */ + +#define compare_strings _glp_mpl_compare_strings +int compare_strings +( MPL *mpl, + STRING *str1, /* not changed */ + STRING *str2 /* not changed */ +); +/* compare one character string with another */ + +#define fetch_string _glp_mpl_fetch_string +char *fetch_string +( MPL *mpl, + STRING *str, /* not changed */ + char buf[MAX_LENGTH+1] /* modified */ +); +/* extract content of character string */ + +#define delete_string _glp_mpl_delete_string +void delete_string +( MPL *mpl, + STRING *str /* destroyed */ +); +/* delete character string */ + +/**********************************************************************/ +/* * * SYMBOLS * * */ +/**********************************************************************/ + +struct SYMBOL +{ /* symbol (numeric or abstract quantity) */ + double num; + /* numeric value of symbol (used only if str == NULL) */ + STRING *str; + /* abstract value of symbol (used only if str != NULL) */ +}; + +#define create_symbol_num _glp_mpl_create_symbol_num +SYMBOL *create_symbol_num(MPL *mpl, double num); +/* create symbol of numeric type */ + +#define create_symbol_str _glp_mpl_create_symbol_str +SYMBOL *create_symbol_str +( MPL *mpl, + STRING *str /* destroyed */ +); +/* create symbol of abstract type */ + +#define copy_symbol _glp_mpl_copy_symbol +SYMBOL *copy_symbol +( MPL *mpl, + SYMBOL *sym /* not changed */ +); +/* make copy of symbol */ + +#define compare_symbols _glp_mpl_compare_symbols +int compare_symbols +( MPL *mpl, + SYMBOL *sym1, /* not changed */ + SYMBOL *sym2 /* not changed */ +); +/* compare one symbol with another */ + +#define delete_symbol _glp_mpl_delete_symbol +void delete_symbol +( MPL *mpl, + SYMBOL *sym /* destroyed */ +); +/* delete symbol */ + +#define format_symbol _glp_mpl_format_symbol +char *format_symbol +( MPL *mpl, + SYMBOL *sym /* not changed */ +); +/* format symbol for displaying or printing */ + +#define concat_symbols _glp_mpl_concat_symbols +SYMBOL *concat_symbols +( MPL *mpl, + SYMBOL *sym1, /* destroyed */ + SYMBOL *sym2 /* destroyed */ +); +/* concatenate one symbol with another */ + +/**********************************************************************/ +/* * * N-TUPLES * * */ +/**********************************************************************/ + +struct TUPLE +{ /* component of n-tuple; the n-tuple itself is associated with + its first component; (note that 0-tuple has no components) */ + SYMBOL *sym; + /* symbol, which the component refers to; cannot be NULL */ + TUPLE *next; + /* the next component of n-tuple */ +}; + +#define create_tuple _glp_mpl_create_tuple +TUPLE *create_tuple(MPL *mpl); +/* create n-tuple */ + +#define expand_tuple _glp_mpl_expand_tuple +TUPLE *expand_tuple +( MPL *mpl, + TUPLE *tuple, /* destroyed */ + SYMBOL *sym /* destroyed */ +); +/* append symbol to n-tuple */ + +#define tuple_dimen _glp_mpl_tuple_dimen +int tuple_dimen +( MPL *mpl, + TUPLE *tuple /* not changed */ +); +/* determine dimension of n-tuple */ + +#define copy_tuple _glp_mpl_copy_tuple +TUPLE *copy_tuple +( MPL *mpl, + TUPLE *tuple /* not changed */ +); +/* make copy of n-tuple */ + +#define compare_tuples _glp_mpl_compare_tuples +int compare_tuples +( MPL *mpl, + TUPLE *tuple1, /* not changed */ + TUPLE *tuple2 /* not changed */ +); +/* compare one n-tuple with another */ + +#define build_subtuple _glp_mpl_build_subtuple +TUPLE *build_subtuple +( MPL *mpl, + TUPLE *tuple, /* not changed */ + int dim +); +/* build subtuple of given n-tuple */ + +#define delete_tuple _glp_mpl_delete_tuple +void delete_tuple +( MPL *mpl, + TUPLE *tuple /* destroyed */ +); +/* delete n-tuple */ + +#define format_tuple _glp_mpl_format_tuple +char *format_tuple +( MPL *mpl, + int c, + TUPLE *tuple /* not changed */ +); +/* format n-tuple for displaying or printing */ + +/**********************************************************************/ +/* * * ELEMENTAL SETS * * */ +/**********************************************************************/ + +#if 2 + 2 == 5 +struct ELEMSET /* see ARRAY */ +{ /* elemental set of n-tuples; formally it is a "value" assigned + to members of model sets (like numbers and symbols, which are + values assigned to members of model parameters); note that a + simple model set is not an elemental set, it is 0-dimensional + array, the only member of which (if it exists) is assigned an + elemental set */ +#endif + +#define create_elemset _glp_mpl_create_elemset +ELEMSET *create_elemset(MPL *mpl, int dim); +/* create elemental set */ + +#define find_tuple _glp_mpl_find_tuple +MEMBER *find_tuple +( MPL *mpl, + ELEMSET *set, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* check if elemental set contains given n-tuple */ + +#define add_tuple _glp_mpl_add_tuple +MEMBER *add_tuple +( MPL *mpl, + ELEMSET *set, /* modified */ + TUPLE *tuple /* destroyed */ +); +/* add new n-tuple to elemental set */ + +#define check_then_add _glp_mpl_check_then_add +MEMBER *check_then_add +( MPL *mpl, + ELEMSET *set, /* modified */ + TUPLE *tuple /* destroyed */ +); +/* check and add new n-tuple to elemental set */ + +#define copy_elemset _glp_mpl_copy_elemset +ELEMSET *copy_elemset +( MPL *mpl, + ELEMSET *set /* not changed */ +); +/* make copy of elemental set */ + +#define delete_elemset _glp_mpl_delete_elemset +void delete_elemset +( MPL *mpl, + ELEMSET *set /* destroyed */ +); +/* delete elemental set */ + +#define arelset_size _glp_mpl_arelset_size +int arelset_size(MPL *mpl, double t0, double tf, double dt); +/* compute size of "arithmetic" elemental set */ + +#define arelset_member _glp_mpl_arelset_member +double arelset_member(MPL *mpl, double t0, double tf, double dt, int j); +/* compute member of "arithmetic" elemental set */ + +#define create_arelset _glp_mpl_create_arelset +ELEMSET *create_arelset(MPL *mpl, double t0, double tf, double dt); +/* create "arithmetic" elemental set */ + +#define set_union _glp_mpl_set_union +ELEMSET *set_union +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +); +/* union of two elemental sets */ + +#define set_diff _glp_mpl_set_diff +ELEMSET *set_diff +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +); +/* difference between two elemental sets */ + +#define set_symdiff _glp_mpl_set_symdiff +ELEMSET *set_symdiff +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +); +/* symmetric difference between two elemental sets */ + +#define set_inter _glp_mpl_set_inter +ELEMSET *set_inter +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +); +/* intersection of two elemental sets */ + +#define set_cross _glp_mpl_set_cross +ELEMSET *set_cross +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +); +/* cross (Cartesian) product of two elemental sets */ + +/**********************************************************************/ +/* * * ELEMENTAL VARIABLES * * */ +/**********************************************************************/ + +struct ELEMVAR +{ /* elemental variable; formally it is a "value" assigned to + members of model variables (like numbers and symbols, which + are values assigned to members of model parameters) */ + int j; + /* LP column number assigned to this elemental variable */ + VARIABLE *var; + /* model variable, which contains this elemental variable */ + MEMBER *memb; + /* array member, which is assigned this elemental variable */ + double lbnd; + /* lower bound */ + double ubnd; + /* upper bound */ + double temp; + /* working quantity used in operations on linear forms; normally + it contains floating-point zero */ +#if 1 /* 15/V-2010 */ + int stat; + double prim, dual; + /* solution components provided by the solver */ +#endif +}; + +/**********************************************************************/ +/* * * LINEAR FORMS * * */ +/**********************************************************************/ + +struct FORMULA +{ /* term of linear form c * x, where c is a coefficient, x is an + elemental variable; the linear form itself is the sum of terms + and is associated with its first term; (note that the linear + form may be empty that means the sum is equal to zero) */ + double coef; + /* coefficient at elemental variable or constant term */ + ELEMVAR *var; + /* reference to elemental variable; NULL means constant term */ + FORMULA *next; + /* the next term of linear form */ +}; + +#define constant_term _glp_mpl_constant_term +FORMULA *constant_term(MPL *mpl, double coef); +/* create constant term */ + +#define single_variable _glp_mpl_single_variable +FORMULA *single_variable +( MPL *mpl, + ELEMVAR *var /* referenced */ +); +/* create single variable */ + +#define copy_formula _glp_mpl_copy_formula +FORMULA *copy_formula +( MPL *mpl, + FORMULA *form /* not changed */ +); +/* make copy of linear form */ + +#define delete_formula _glp_mpl_delete_formula +void delete_formula +( MPL *mpl, + FORMULA *form /* destroyed */ +); +/* delete linear form */ + +#define linear_comb _glp_mpl_linear_comb +FORMULA *linear_comb +( MPL *mpl, + double a, FORMULA *fx, /* destroyed */ + double b, FORMULA *fy /* destroyed */ +); +/* linear combination of two linear forms */ + +#define remove_constant _glp_mpl_remove_constant +FORMULA *remove_constant +( MPL *mpl, + FORMULA *form, /* destroyed */ + double *coef /* modified */ +); +/* remove constant term from linear form */ + +#define reduce_terms _glp_mpl_reduce_terms +FORMULA *reduce_terms +( MPL *mpl, + FORMULA *form /* destroyed */ +); +/* reduce identical terms in linear form */ + +/**********************************************************************/ +/* * * ELEMENTAL CONSTRAINTS * * */ +/**********************************************************************/ + +struct ELEMCON +{ /* elemental constraint; formally it is a "value" assigned to + members of model constraints (like numbers or symbols, which + are values assigned to members of model parameters) */ + int i; + /* LP row number assigned to this elemental constraint */ + CONSTRAINT *con; + /* model constraint, which contains this elemental constraint */ + MEMBER *memb; + /* array member, which is assigned this elemental constraint */ + FORMULA *form; + /* linear form */ + double lbnd; + /* lower bound */ + double ubnd; + /* upper bound */ +#if 1 /* 15/V-2010 */ + int stat; + double prim, dual; + /* solution components provided by the solver */ +#endif +}; + +/**********************************************************************/ +/* * * GENERIC VALUES * * */ +/**********************************************************************/ + +union VALUE +{ /* generic value, which can be assigned to object member or be a + result of evaluation of expression */ + /* indicator that specifies the particular type of generic value + is stored in the corresponding array or pseudo-code descriptor + and can be one of the following: + A_NONE - no value + A_NUMERIC - floating-point number + A_SYMBOLIC - symbol + A_LOGICAL - logical value + A_TUPLE - n-tuple + A_ELEMSET - elemental set + A_ELEMVAR - elemental variable + A_FORMULA - linear form + A_ELEMCON - elemental constraint */ + void *none; /* null */ + double num; /* value */ + SYMBOL *sym; /* value */ + int bit; /* value */ + TUPLE *tuple; /* value */ + ELEMSET *set; /* value */ + ELEMVAR *var; /* reference */ + FORMULA *form; /* value */ + ELEMCON *con; /* reference */ +}; + +#define delete_value _glp_mpl_delete_value +void delete_value +( MPL *mpl, + int type, + VALUE *value /* content destroyed */ +); +/* delete generic value */ + +/**********************************************************************/ +/* * * SYMBOLICALLY INDEXED ARRAYS * * */ +/**********************************************************************/ + +struct ARRAY +{ /* multi-dimensional array, a set of members indexed over simple + or compound sets of symbols; arrays are used to represent the + contents of model objects (i.e. sets, parameters, variables, + constraints, and objectives); arrays also are used as "values" + that are assigned to members of set objects, in which case the + array itself represents an elemental set */ + int type; + /* type of generic values assigned to the array members: + A_NONE - none (members have no assigned values) + A_NUMERIC - floating-point numbers + A_SYMBOLIC - symbols + A_ELEMSET - elemental sets + A_ELEMVAR - elemental variables + A_ELEMCON - elemental constraints */ + int dim; + /* dimension of the array that determines number of components in + n-tuples for all members of the array, dim >= 0; dim = 0 means + the array is 0-dimensional */ + int size; + /* size of the array, i.e. number of its members */ + MEMBER *head; + /* the first array member; NULL means the array is empty */ + MEMBER *tail; + /* the last array member; NULL means the array is empty */ + AVL *tree; + /* the search tree intended to find array members for logarithmic + time; NULL means the search tree doesn't exist */ + ARRAY *prev; + /* the previous array in the translator database */ + ARRAY *next; + /* the next array in the translator database */ +}; + +struct MEMBER +{ /* array member */ + TUPLE *tuple; + /* n-tuple, which identifies the member; number of its components + is the same for all members within the array and determined by + the array dimension; duplicate members are not allowed */ + MEMBER *next; + /* the next array member */ + VALUE value; + /* generic value assigned to the member */ +}; + +#define create_array _glp_mpl_create_array +ARRAY *create_array(MPL *mpl, int type, int dim); +/* create array */ + +#define find_member _glp_mpl_find_member +MEMBER *find_member +( MPL *mpl, + ARRAY *array, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* find array member with given n-tuple */ + +#define add_member _glp_mpl_add_member +MEMBER *add_member +( MPL *mpl, + ARRAY *array, /* modified */ + TUPLE *tuple /* destroyed */ +); +/* add new member to array */ + +#define delete_array _glp_mpl_delete_array +void delete_array +( MPL *mpl, + ARRAY *array /* destroyed */ +); +/* delete array */ + +/**********************************************************************/ +/* * * DOMAINS AND DUMMY INDICES * * */ +/**********************************************************************/ + +struct DOMAIN +{ /* domain (a simple or compound set); syntactically domain looks + like '{ i in I, (j,k) in S, t in T : <predicate> }'; domains + are used to define sets, over which model objects are indexed, + and also as constituents of iterated operators */ + DOMAIN_BLOCK *list; + /* linked list of domain blocks (in the example above such blocks + are 'i in I', '(j,k) in S', and 't in T'); this list cannot be + empty */ + CODE *code; + /* pseudo-code for computing the logical predicate, which follows + the colon; NULL means no predicate is specified */ +}; + +struct DOMAIN_BLOCK +{ /* domain block; syntactically domain blocks look like 'i in I', + '(j,k) in S', and 't in T' in the example above (in the sequel + sets like I, S, and T are called basic sets) */ + DOMAIN_SLOT *list; + /* linked list of domain slots (i.e. indexing positions); number + of slots in this list is the same as dimension of n-tuples in + the basic set; this list cannot be empty */ + CODE *code; + /* pseudo-code for computing basic set; cannot be NULL */ + TUPLE *backup; + /* if this n-tuple is not empty, current values of dummy indices + in the domain block are the same as components of this n-tuple + (note that this n-tuple may have larger dimension than number + of dummy indices in this block, in which case extra components + are ignored); this n-tuple is used to restore former values of + dummy indices, if they were changed due to recursive calls to + the domain block */ + DOMAIN_BLOCK *next; + /* the next block in the same domain */ +}; + +struct DOMAIN_SLOT +{ /* domain slot; it specifies an individual indexing position and + defines the corresponding dummy index */ + char *name; + /* symbolic name of the dummy index; null pointer means the dummy + index is not explicitly specified */ + CODE *code; + /* pseudo-code for computing symbolic value, at which the dummy + index is bound; NULL means the dummy index is free within the + domain scope */ + SYMBOL *value; + /* current value assigned to the dummy index; NULL means no value + is assigned at the moment */ + CODE *list; + /* linked list of pseudo-codes with operation O_INDEX referring + to this slot; this linked list is used to invalidate resultant + values of the operation, which depend on this dummy index */ + DOMAIN_SLOT *next; + /* the next slot in the same domain block */ +}; + +#define assign_dummy_index _glp_mpl_assign_dummy_index +void assign_dummy_index +( MPL *mpl, + DOMAIN_SLOT *slot, /* modified */ + SYMBOL *value /* not changed */ +); +/* assign new value to dummy index */ + +#define update_dummy_indices _glp_mpl_update_dummy_indices +void update_dummy_indices +( MPL *mpl, + DOMAIN_BLOCK *block /* not changed */ +); +/* update current values of dummy indices */ + +#define enter_domain_block _glp_mpl_enter_domain_block +int enter_domain_block +( MPL *mpl, + DOMAIN_BLOCK *block, /* not changed */ + TUPLE *tuple, /* not changed */ + void *info, void (*func)(MPL *mpl, void *info) +); +/* enter domain block */ + +#define eval_within_domain _glp_mpl_eval_within_domain +int eval_within_domain +( MPL *mpl, + DOMAIN *domain, /* not changed */ + TUPLE *tuple, /* not changed */ + void *info, void (*func)(MPL *mpl, void *info) +); +/* perform evaluation within domain scope */ + +#define loop_within_domain _glp_mpl_loop_within_domain +void loop_within_domain +( MPL *mpl, + DOMAIN *domain, /* not changed */ + void *info, int (*func)(MPL *mpl, void *info) +); +/* perform iterations within domain scope */ + +#define out_of_domain _glp_mpl_out_of_domain +void out_of_domain +( MPL *mpl, + char *name, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* raise domain exception */ + +#define get_domain_tuple _glp_mpl_get_domain_tuple +TUPLE *get_domain_tuple +( MPL *mpl, + DOMAIN *domain /* not changed */ +); +/* obtain current n-tuple from domain */ + +#define clean_domain _glp_mpl_clean_domain +void clean_domain(MPL *mpl, DOMAIN *domain); +/* clean domain */ + +/**********************************************************************/ +/* * * MODEL SETS * * */ +/**********************************************************************/ + +struct SET +{ /* model set */ + char *name; + /* symbolic name; cannot be NULL */ + char *alias; + /* alias; NULL means alias is not specified */ + int dim; /* aka arity */ + /* dimension (number of subscripts); dim = 0 means 0-dimensional + (unsubscripted) set, dim > 0 means set of sets */ + DOMAIN *domain; + /* subscript domain; NULL for 0-dimensional set */ + int dimen; + /* dimension of n-tuples, which members of this set consist of + (note that the model set itself is an array of elemental sets, + which are its members; so, don't confuse this dimension with + dimension of the model set); always non-zero */ + WITHIN *within; + /* list of supersets, which restrict each member of the set to be + in every superset from this list; this list can be empty */ + CODE *assign; + /* pseudo-code for computing assigned value; can be NULL */ + CODE *option; + /* pseudo-code for computing default value; can be NULL */ + GADGET *gadget; + /* plain set used to initialize the array of sets; can be NULL */ + int data; + /* data status flag: + 0 - no data are provided in the data section + 1 - data are provided, but not checked yet + 2 - data are provided and have been checked */ + ARRAY *array; + /* array of members, which are assigned elemental sets */ +}; + +struct WITHIN +{ /* restricting superset list entry */ + CODE *code; + /* pseudo-code for computing the superset; cannot be NULL */ + WITHIN *next; + /* the next entry for the same set or parameter */ +}; + +struct GADGET +{ /* plain set used to initialize the array of sets with data */ + SET *set; + /* pointer to plain set; cannot be NULL */ + int ind[20]; /* ind[dim+dimen]; */ + /* permutation of integers 1, 2, ..., dim+dimen */ +}; + +#define check_elem_set _glp_mpl_check_elem_set +void check_elem_set +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple, /* not changed */ + ELEMSET *refer /* not changed */ +); +/* check elemental set assigned to set member */ + +#define take_member_set _glp_mpl_take_member_set +ELEMSET *take_member_set /* returns reference, not value */ +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* obtain elemental set assigned to set member */ + +#define eval_member_set _glp_mpl_eval_member_set +ELEMSET *eval_member_set /* returns reference, not value */ +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* evaluate elemental set assigned to set member */ + +#define eval_whole_set _glp_mpl_eval_whole_set +void eval_whole_set(MPL *mpl, SET *set); +/* evaluate model set over entire domain */ + +#define clean_set _glp_mpl_clean_set +void clean_set(MPL *mpl, SET *set); +/* clean model set */ + +/**********************************************************************/ +/* * * MODEL PARAMETERS * * */ +/**********************************************************************/ + +struct PARAMETER +{ /* model parameter */ + char *name; + /* symbolic name; cannot be NULL */ + char *alias; + /* alias; NULL means alias is not specified */ + int dim; /* aka arity */ + /* dimension (number of subscripts); dim = 0 means 0-dimensional + (unsubscripted) parameter */ + DOMAIN *domain; + /* subscript domain; NULL for 0-dimensional parameter */ + int type; + /* parameter type: + A_NUMERIC - numeric + A_INTEGER - integer + A_BINARY - binary + A_SYMBOLIC - symbolic */ + CONDITION *cond; + /* list of conditions, which restrict each parameter member to + satisfy to every condition from this list; this list is used + only for numeric parameters and can be empty */ + WITHIN *in; + /* list of supersets, which restrict each parameter member to be + in every superset from this list; this list is used only for + symbolic parameters and can be empty */ + CODE *assign; + /* pseudo-code for computing assigned value; can be NULL */ + CODE *option; + /* pseudo-code for computing default value; can be NULL */ + int data; + /* data status flag: + 0 - no data are provided in the data section + 1 - data are provided, but not checked yet + 2 - data are provided and have been checked */ + SYMBOL *defval; + /* default value provided in the data section; can be NULL */ + ARRAY *array; + /* array of members, which are assigned numbers or symbols */ +}; + +struct CONDITION +{ /* restricting condition list entry */ + int rho; + /* flag that specifies the form of the condition: + O_LT - less than + O_LE - less than or equal to + O_EQ - equal to + O_GE - greater than or equal to + O_GT - greater than + O_NE - not equal to */ + CODE *code; + /* pseudo-code for computing the reference value */ + CONDITION *next; + /* the next entry for the same parameter */ +}; + +#define check_value_num _glp_mpl_check_value_num +void check_value_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple, /* not changed */ + double value +); +/* check numeric value assigned to parameter member */ + +#define take_member_num _glp_mpl_take_member_num +double take_member_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* obtain numeric value assigned to parameter member */ + +#define eval_member_num _glp_mpl_eval_member_num +double eval_member_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* evaluate numeric value assigned to parameter member */ + +#define check_value_sym _glp_mpl_check_value_sym +void check_value_sym +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple, /* not changed */ + SYMBOL *value /* not changed */ +); +/* check symbolic value assigned to parameter member */ + +#define take_member_sym _glp_mpl_take_member_sym +SYMBOL *take_member_sym /* returns value, not reference */ +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* obtain symbolic value assigned to parameter member */ + +#define eval_member_sym _glp_mpl_eval_member_sym +SYMBOL *eval_member_sym /* returns value, not reference */ +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* evaluate symbolic value assigned to parameter member */ + +#define eval_whole_par _glp_mpl_eval_whole_par +void eval_whole_par(MPL *mpl, PARAMETER *par); +/* evaluate model parameter over entire domain */ + +#define clean_parameter _glp_mpl_clean_parameter +void clean_parameter(MPL *mpl, PARAMETER *par); +/* clean model parameter */ + +/**********************************************************************/ +/* * * MODEL VARIABLES * * */ +/**********************************************************************/ + +struct VARIABLE +{ /* model variable */ + char *name; + /* symbolic name; cannot be NULL */ + char *alias; + /* alias; NULL means alias is not specified */ + int dim; /* aka arity */ + /* dimension (number of subscripts); dim = 0 means 0-dimensional + (unsubscripted) variable */ + DOMAIN *domain; + /* subscript domain; NULL for 0-dimensional variable */ + int type; + /* variable type: + A_NUMERIC - continuous + A_INTEGER - integer + A_BINARY - binary */ + CODE *lbnd; + /* pseudo-code for computing lower bound; NULL means lower bound + is not specified */ + CODE *ubnd; + /* pseudo-code for computing upper bound; NULL means upper bound + is not specified */ + /* if both the pointers lbnd and ubnd refer to the same code, the + variable is fixed at the corresponding value */ + ARRAY *array; + /* array of members, which are assigned elemental variables */ +}; + +#define take_member_var _glp_mpl_take_member_var +ELEMVAR *take_member_var /* returns reference */ +( MPL *mpl, + VARIABLE *var, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* obtain reference to elemental variable */ + +#define eval_member_var _glp_mpl_eval_member_var +ELEMVAR *eval_member_var /* returns reference */ +( MPL *mpl, + VARIABLE *var, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* evaluate reference to elemental variable */ + +#define eval_whole_var _glp_mpl_eval_whole_var +void eval_whole_var(MPL *mpl, VARIABLE *var); +/* evaluate model variable over entire domain */ + +#define clean_variable _glp_mpl_clean_variable +void clean_variable(MPL *mpl, VARIABLE *var); +/* clean model variable */ + +/**********************************************************************/ +/* * * MODEL CONSTRAINTS AND OBJECTIVES * * */ +/**********************************************************************/ + +struct CONSTRAINT +{ /* model constraint or objective */ + char *name; + /* symbolic name; cannot be NULL */ + char *alias; + /* alias; NULL means alias is not specified */ + int dim; /* aka arity */ + /* dimension (number of subscripts); dim = 0 means 0-dimensional + (unsubscripted) constraint */ + DOMAIN *domain; + /* subscript domain; NULL for 0-dimensional constraint */ + int type; + /* constraint type: + A_CONSTRAINT - constraint + A_MINIMIZE - objective (minimization) + A_MAXIMIZE - objective (maximization) */ + CODE *code; + /* pseudo-code for computing main linear form; cannot be NULL */ + CODE *lbnd; + /* pseudo-code for computing lower bound; NULL means lower bound + is not specified */ + CODE *ubnd; + /* pseudo-code for computing upper bound; NULL means upper bound + is not specified */ + /* if both the pointers lbnd and ubnd refer to the same code, the + constraint has the form of equation */ + ARRAY *array; + /* array of members, which are assigned elemental constraints */ +}; + +#define take_member_con _glp_mpl_take_member_con +ELEMCON *take_member_con /* returns reference */ +( MPL *mpl, + CONSTRAINT *con, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* obtain reference to elemental constraint */ + +#define eval_member_con _glp_mpl_eval_member_con +ELEMCON *eval_member_con /* returns reference */ +( MPL *mpl, + CONSTRAINT *con, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* evaluate reference to elemental constraint */ + +#define eval_whole_con _glp_mpl_eval_whole_con +void eval_whole_con(MPL *mpl, CONSTRAINT *con); +/* evaluate model constraint over entire domain */ + +#define clean_constraint _glp_mpl_clean_constraint +void clean_constraint(MPL *mpl, CONSTRAINT *con); +/* clean model constraint */ + +/**********************************************************************/ +/* * * DATA TABLES * * */ +/**********************************************************************/ + +struct TABLE +{ /* data table */ + char *name; + /* symbolic name; cannot be NULL */ + char *alias; + /* alias; NULL means alias is not specified */ + int type; + /* table type: + A_INPUT - input table + A_OUTPUT - output table */ + TABARG *arg; + /* argument list; cannot be empty */ + union + { struct + { SET *set; + /* input set; NULL means the set is not specified */ + TABFLD *fld; + /* field list; cannot be empty */ + TABIN *list; + /* input list; can be empty */ + } in; + struct + { DOMAIN *domain; + /* subscript domain; cannot be NULL */ + TABOUT *list; + /* output list; cannot be empty */ + } out; + } u; +}; + +struct TABARG +{ /* table argument list entry */ + CODE *code; + /* pseudo-code for computing the argument */ + TABARG *next; + /* next entry for the same table */ +}; + +struct TABFLD +{ /* table field list entry */ + char *name; + /* field name; cannot be NULL */ + TABFLD *next; + /* next entry for the same table */ +}; + +struct TABIN +{ /* table input list entry */ + PARAMETER *par; + /* parameter to be read; cannot be NULL */ + char *name; + /* column name; cannot be NULL */ + TABIN *next; + /* next entry for the same table */ +}; + +struct TABOUT +{ /* table output list entry */ + CODE *code; + /* pseudo-code for computing the value to be written */ + char *name; + /* column name; cannot be NULL */ + TABOUT *next; + /* next entry for the same table */ +}; + +struct TABDCA +{ /* table driver communication area */ + int id; + /* driver identifier (set by mpl_tab_drv_open) */ + void *link; + /* driver link pointer (set by mpl_tab_drv_open) */ + int na; + /* number of arguments */ + char **arg; /* char *arg[1+ns]; */ + /* arg[k], 1 <= k <= ns, is pointer to k-th argument */ + int nf; + /* number of fields */ + char **name; /* char *name[1+nc]; */ + /* name[k], 1 <= k <= nc, is name of k-th field */ + int *type; /* int type[1+nc]; */ + /* type[k], 1 <= k <= nc, is type of k-th field: + '?' - value not assigned + 'N' - number + 'S' - character string */ + double *num; /* double num[1+nc]; */ + /* num[k], 1 <= k <= nc, is numeric value of k-th field */ + char **str; + /* str[k], 1 <= k <= nc, is string value of k-th field */ +}; + +#define mpl_tab_num_args _glp_mpl_tab_num_args +int mpl_tab_num_args(TABDCA *dca); + +#define mpl_tab_get_arg _glp_mpl_tab_get_arg +const char *mpl_tab_get_arg(TABDCA *dca, int k); + +#define mpl_tab_num_flds _glp_mpl_tab_num_flds +int mpl_tab_num_flds(TABDCA *dca); + +#define mpl_tab_get_name _glp_mpl_tab_get_name +const char *mpl_tab_get_name(TABDCA *dca, int k); + +#define mpl_tab_get_type _glp_mpl_tab_get_type +int mpl_tab_get_type(TABDCA *dca, int k); + +#define mpl_tab_get_num _glp_mpl_tab_get_num +double mpl_tab_get_num(TABDCA *dca, int k); + +#define mpl_tab_get_str _glp_mpl_tab_get_str +const char *mpl_tab_get_str(TABDCA *dca, int k); + +#define mpl_tab_set_num _glp_mpl_tab_set_num +void mpl_tab_set_num(TABDCA *dca, int k, double num); + +#define mpl_tab_set_str _glp_mpl_tab_set_str +void mpl_tab_set_str(TABDCA *dca, int k, const char *str); + +#define mpl_tab_drv_open _glp_mpl_tab_drv_open +void mpl_tab_drv_open(MPL *mpl, int mode); + +#define mpl_tab_drv_read _glp_mpl_tab_drv_read +int mpl_tab_drv_read(MPL *mpl); + +#define mpl_tab_drv_write _glp_mpl_tab_drv_write +void mpl_tab_drv_write(MPL *mpl); + +#define mpl_tab_drv_close _glp_mpl_tab_drv_close +void mpl_tab_drv_close(MPL *mpl); + +/**********************************************************************/ +/* * * PSEUDO-CODE * * */ +/**********************************************************************/ + +union OPERANDS +{ /* operands that participate in pseudo-code operation (choice of + particular operands depends on the operation code) */ + /*--------------------------------------------------------------*/ + double num; /* O_NUMBER */ + /* floaing-point number to be taken */ + /*--------------------------------------------------------------*/ + char *str; /* O_STRING */ + /* character string to be taken */ + /*--------------------------------------------------------------*/ + struct /* O_INDEX */ + { DOMAIN_SLOT *slot; + /* domain slot, which contains dummy index to be taken */ + CODE *next; + /* the next pseudo-code with op = O_INDEX, which refers to the + same slot as this one; pointer to the beginning of this list + is stored in the corresponding domain slot */ + } index; + /*--------------------------------------------------------------*/ + struct /* O_MEMNUM, O_MEMSYM */ + { PARAMETER *par; + /* model parameter, which contains member to be taken */ + ARG_LIST *list; + /* list of subscripts; NULL for 0-dimensional parameter */ + } par; + /*--------------------------------------------------------------*/ + struct /* O_MEMSET */ + { SET *set; + /* model set, which contains member to be taken */ + ARG_LIST *list; + /* list of subscripts; NULL for 0-dimensional set */ + } set; + /*--------------------------------------------------------------*/ + struct /* O_MEMVAR */ + { VARIABLE *var; + /* model variable, which contains member to be taken */ + ARG_LIST *list; + /* list of subscripts; NULL for 0-dimensional variable */ +#if 1 /* 15/V-2010 */ + int suff; + /* suffix specified: */ +#define DOT_NONE 0x00 /* none (means variable itself) */ +#define DOT_LB 0x01 /* .lb (lower bound) */ +#define DOT_UB 0x02 /* .ub (upper bound) */ +#define DOT_STATUS 0x03 /* .status (status) */ +#define DOT_VAL 0x04 /* .val (primal value) */ +#define DOT_DUAL 0x05 /* .dual (dual value) */ +#endif + } var; +#if 1 /* 15/V-2010 */ + /*--------------------------------------------------------------*/ + struct /* O_MEMCON */ + { CONSTRAINT *con; + /* model constraint, which contains member to be taken */ + ARG_LIST *list; + /* list of subscripys; NULL for 0-dimensional constraint */ + int suff; + /* suffix specified (see O_MEMVAR above) */ + } con; +#endif + /*--------------------------------------------------------------*/ + ARG_LIST *list; /* O_TUPLE, O_MAKE, n-ary operations */ + /* list of operands */ + /*--------------------------------------------------------------*/ + DOMAIN_BLOCK *slice; /* O_SLICE */ + /* domain block, which specifies slice (i.e. n-tuple that contains + free dummy indices); this operation is never evaluated */ + /*--------------------------------------------------------------*/ + struct /* unary, binary, ternary operations */ + { CODE *x; + /* pseudo-code for computing first operand */ + CODE *y; + /* pseudo-code for computing second operand */ + CODE *z; + /* pseudo-code for computing third operand */ + } arg; + /*--------------------------------------------------------------*/ + struct /* iterated operations */ + { DOMAIN *domain; + /* domain, over which the operation is performed */ + CODE *x; + /* pseudo-code for computing "integrand" */ + } loop; + /*--------------------------------------------------------------*/ +}; + +struct ARG_LIST +{ /* operands list entry */ + CODE *x; + /* pseudo-code for computing operand */ + ARG_LIST *next; + /* the next operand of the same operation */ +}; + +struct CODE +{ /* pseudo-code (internal form of expressions) */ + int op; + /* operation code: */ +#define O_NUMBER 301 /* take floating-point number */ +#define O_STRING 302 /* take character string */ +#define O_INDEX 303 /* take dummy index */ +#define O_MEMNUM 304 /* take member of numeric parameter */ +#define O_MEMSYM 305 /* take member of symbolic parameter */ +#define O_MEMSET 306 /* take member of set */ +#define O_MEMVAR 307 /* take member of variable */ +#define O_MEMCON 308 /* take member of constraint */ +#define O_TUPLE 309 /* make n-tuple */ +#define O_MAKE 310 /* make elemental set of n-tuples */ +#define O_SLICE 311 /* define domain block (dummy op) */ + /* 0-ary operations --------------------*/ +#define O_IRAND224 312 /* pseudo-random in [0, 2^24-1] */ +#define O_UNIFORM01 313 /* pseudo-random in [0, 1) */ +#define O_NORMAL01 314 /* gaussian random, mu = 0, sigma = 1 */ +#define O_GMTIME 315 /* current calendar time (UTC) */ + /* unary operations --------------------*/ +#define O_CVTNUM 316 /* conversion to numeric */ +#define O_CVTSYM 317 /* conversion to symbolic */ +#define O_CVTLOG 318 /* conversion to logical */ +#define O_CVTTUP 319 /* conversion to 1-tuple */ +#define O_CVTLFM 320 /* conversion to linear form */ +#define O_PLUS 321 /* unary plus */ +#define O_MINUS 322 /* unary minus */ +#define O_NOT 323 /* negation (logical "not") */ +#define O_ABS 324 /* absolute value */ +#define O_CEIL 325 /* round upward ("ceiling of x") */ +#define O_FLOOR 326 /* round downward ("floor of x") */ +#define O_EXP 327 /* base-e exponential */ +#define O_LOG 328 /* natural logarithm */ +#define O_LOG10 329 /* common (decimal) logarithm */ +#define O_SQRT 330 /* square root */ +#define O_SIN 331 /* trigonometric sine */ +#define O_COS 332 /* trigonometric cosine */ +#define O_ATAN 333 /* trigonometric arctangent */ +#define O_ROUND 334 /* round to nearest integer */ +#define O_TRUNC 335 /* truncate to nearest integer */ +#define O_CARD 336 /* cardinality of set */ +#define O_LENGTH 337 /* length of symbolic value */ + /* binary operations -------------------*/ +#define O_ADD 338 /* addition */ +#define O_SUB 339 /* subtraction */ +#define O_LESS 340 /* non-negative subtraction */ +#define O_MUL 341 /* multiplication */ +#define O_DIV 342 /* division */ +#define O_IDIV 343 /* quotient of exact division */ +#define O_MOD 344 /* remainder of exact division */ +#define O_POWER 345 /* exponentiation (raise to power) */ +#define O_ATAN2 346 /* trigonometric arctangent */ +#define O_ROUND2 347 /* round to n fractional digits */ +#define O_TRUNC2 348 /* truncate to n fractional digits */ +#define O_UNIFORM 349 /* pseudo-random in [a, b) */ +#define O_NORMAL 350 /* gaussian random, given mu and sigma */ +#define O_CONCAT 351 /* concatenation */ +#define O_LT 352 /* comparison on 'less than' */ +#define O_LE 353 /* comparison on 'not greater than' */ +#define O_EQ 354 /* comparison on 'equal to' */ +#define O_GE 355 /* comparison on 'not less than' */ +#define O_GT 356 /* comparison on 'greater than' */ +#define O_NE 357 /* comparison on 'not equal to' */ +#define O_AND 358 /* conjunction (logical "and") */ +#define O_OR 359 /* disjunction (logical "or") */ +#define O_UNION 360 /* union */ +#define O_DIFF 361 /* difference */ +#define O_SYMDIFF 362 /* symmetric difference */ +#define O_INTER 363 /* intersection */ +#define O_CROSS 364 /* cross (Cartesian) product */ +#define O_IN 365 /* test on 'x in Y' */ +#define O_NOTIN 366 /* test on 'x not in Y' */ +#define O_WITHIN 367 /* test on 'X within Y' */ +#define O_NOTWITHIN 368 /* test on 'X not within Y' */ +#define O_SUBSTR 369 /* substring */ +#define O_STR2TIME 370 /* convert string to time */ +#define O_TIME2STR 371 /* convert time to string */ + /* ternary operations ------------------*/ +#define O_DOTS 372 /* build "arithmetic" set */ +#define O_FORK 373 /* if-then-else */ +#define O_SUBSTR3 374 /* substring */ + /* n-ary operations --------------------*/ +#define O_MIN 375 /* minimal value (n-ary) */ +#define O_MAX 376 /* maximal value (n-ary) */ + /* iterated operations -----------------*/ +#define O_SUM 377 /* summation */ +#define O_PROD 378 /* multiplication */ +#define O_MINIMUM 379 /* minimum */ +#define O_MAXIMUM 380 /* maximum */ +#define O_FORALL 381 /* conjunction (A-quantification) */ +#define O_EXISTS 382 /* disjunction (E-quantification) */ +#define O_SETOF 383 /* compute elemental set */ +#define O_BUILD 384 /* build elemental set */ + OPERANDS arg; + /* operands that participate in the operation */ + int type; + /* type of the resultant value: + A_NUMERIC - numeric + A_SYMBOLIC - symbolic + A_LOGICAL - logical + A_TUPLE - n-tuple + A_ELEMSET - elemental set + A_FORMULA - linear form */ + int dim; + /* dimension of the resultant value; for A_TUPLE and A_ELEMSET it + is the dimension of the corresponding n-tuple(s) and cannot be + zero; for other resultant types it is always zero */ + CODE *up; + /* parent pseudo-code, which refers to this pseudo-code as to its + operand; NULL means this pseudo-code has no parent and defines + an expression, which is not contained in another expression */ + int vflag; + /* volatile flag; being set this flag means that this operation + has a side effect; for primary expressions this flag is set + directly by corresponding parsing routines (for example, if + primary expression is a reference to a function that generates + pseudo-random numbers); in other cases this flag is inherited + from operands */ + int valid; + /* if this flag is set, the resultant value, which is a temporary + result of evaluating this operation on particular values of + operands, is valid; if this flag is clear, the resultant value + doesn't exist and therefore not valid; having been evaluated + the resultant value is stored here and not destroyed until the + dummy indices, which this value depends on, have been changed + (and if it doesn't depend on dummy indices at all, it is never + destroyed); thus, if the resultant value is valid, evaluating + routine can immediately take its copy not computing the result + from scratch; this mechanism is similar to moving invariants + out of loops and allows improving efficiency at the expense of + some extra memory needed to keep temporary results */ + /* however, if the volatile flag (see above) is set, even if the + resultant value is valid, evaluating routine computes it as if + it were not valid, i.e. caching is not used in this case */ + VALUE value; + /* resultant value in generic format */ +}; + +#define eval_numeric _glp_mpl_eval_numeric +double eval_numeric(MPL *mpl, CODE *code); +/* evaluate pseudo-code to determine numeric value */ + +#define eval_symbolic _glp_mpl_eval_symbolic +SYMBOL *eval_symbolic(MPL *mpl, CODE *code); +/* evaluate pseudo-code to determine symbolic value */ + +#define eval_logical _glp_mpl_eval_logical +int eval_logical(MPL *mpl, CODE *code); +/* evaluate pseudo-code to determine logical value */ + +#define eval_tuple _glp_mpl_eval_tuple +TUPLE *eval_tuple(MPL *mpl, CODE *code); +/* evaluate pseudo-code to construct n-tuple */ + +#define eval_elemset _glp_mpl_eval_elemset +ELEMSET *eval_elemset(MPL *mpl, CODE *code); +/* evaluate pseudo-code to construct elemental set */ + +#define is_member _glp_mpl_is_member +int is_member(MPL *mpl, CODE *code, TUPLE *tuple); +/* check if n-tuple is in set specified by pseudo-code */ + +#define eval_formula _glp_mpl_eval_formula +FORMULA *eval_formula(MPL *mpl, CODE *code); +/* evaluate pseudo-code to construct linear form */ + +#define clean_code _glp_mpl_clean_code +void clean_code(MPL *mpl, CODE *code); +/* clean pseudo-code */ + +/**********************************************************************/ +/* * * MODEL STATEMENTS * * */ +/**********************************************************************/ + +struct CHECK +{ /* check statement */ + DOMAIN *domain; + /* subscript domain; NULL means domain is not used */ + CODE *code; + /* code for computing the predicate to be checked */ +}; + +struct DISPLAY +{ /* display statement */ + DOMAIN *domain; + /* subscript domain; NULL means domain is not used */ + DISPLAY1 *list; + /* display list; cannot be empty */ +}; + +struct DISPLAY1 +{ /* display list entry */ + int type; + /* item type: + A_INDEX - dummy index + A_SET - model set + A_PARAMETER - model parameter + A_VARIABLE - model variable + A_CONSTRAINT - model constraint/objective + A_EXPRESSION - expression */ + union + { DOMAIN_SLOT *slot; + SET *set; + PARAMETER *par; + VARIABLE *var; + CONSTRAINT *con; + CODE *code; + } u; + /* item to be displayed */ +#if 0 /* 15/V-2010 */ + ARG_LIST *list; + /* optional subscript list (for constraint/objective only) */ +#endif + DISPLAY1 *next; + /* the next entry for the same statement */ +}; + +struct PRINTF +{ /* printf statement */ + DOMAIN *domain; + /* subscript domain; NULL means domain is not used */ + CODE *fmt; + /* pseudo-code for computing format string */ + PRINTF1 *list; + /* printf list; can be empty */ + CODE *fname; + /* pseudo-code for computing filename to redirect the output; + NULL means the output goes to stdout */ + int app; + /* if this flag is set, the output is appended */ +}; + +struct PRINTF1 +{ /* printf list entry */ + CODE *code; + /* pseudo-code for computing value to be printed */ + PRINTF1 *next; + /* the next entry for the same statement */ +}; + +struct FOR +{ /* for statement */ + DOMAIN *domain; + /* subscript domain; cannot be NULL */ + STATEMENT *list; + /* linked list of model statements within this for statement in + the original order */ +}; + +struct STATEMENT +{ /* model statement */ + int line; + /* number of source text line, where statement begins */ + int type; + /* statement type: + A_SET - set statement + A_PARAMETER - parameter statement + A_VARIABLE - variable statement + A_CONSTRAINT - constraint/objective statement + A_TABLE - table statement + A_SOLVE - solve statement + A_CHECK - check statement + A_DISPLAY - display statement + A_PRINTF - printf statement + A_FOR - for statement */ + union + { SET *set; + PARAMETER *par; + VARIABLE *var; + CONSTRAINT *con; + TABLE *tab; + void *slv; /* currently not used (set to NULL) */ + CHECK *chk; + DISPLAY *dpy; + PRINTF *prt; + FOR *fur; + } u; + /* specific part of statement */ + STATEMENT *next; + /* the next statement; in this list statements follow in the same + order as they appear in the model section */ +}; + +#define execute_table _glp_mpl_execute_table +void execute_table(MPL *mpl, TABLE *tab); +/* execute table statement */ + +#define free_dca _glp_mpl_free_dca +void free_dca(MPL *mpl); +/* free table driver communucation area */ + +#define clean_table _glp_mpl_clean_table +void clean_table(MPL *mpl, TABLE *tab); +/* clean table statement */ + +#define execute_check _glp_mpl_execute_check +void execute_check(MPL *mpl, CHECK *chk); +/* execute check statement */ + +#define clean_check _glp_mpl_clean_check +void clean_check(MPL *mpl, CHECK *chk); +/* clean check statement */ + +#define execute_display _glp_mpl_execute_display +void execute_display(MPL *mpl, DISPLAY *dpy); +/* execute display statement */ + +#define clean_display _glp_mpl_clean_display +void clean_display(MPL *mpl, DISPLAY *dpy); +/* clean display statement */ + +#define execute_printf _glp_mpl_execute_printf +void execute_printf(MPL *mpl, PRINTF *prt); +/* execute printf statement */ + +#define clean_printf _glp_mpl_clean_printf +void clean_printf(MPL *mpl, PRINTF *prt); +/* clean printf statement */ + +#define execute_for _glp_mpl_execute_for +void execute_for(MPL *mpl, FOR *fur); +/* execute for statement */ + +#define clean_for _glp_mpl_clean_for +void clean_for(MPL *mpl, FOR *fur); +/* clean for statement */ + +#define execute_statement _glp_mpl_execute_statement +void execute_statement(MPL *mpl, STATEMENT *stmt); +/* execute specified model statement */ + +#define clean_statement _glp_mpl_clean_statement +void clean_statement(MPL *mpl, STATEMENT *stmt); +/* clean specified model statement */ + +/**********************************************************************/ +/* * * GENERATING AND POSTSOLVING MODEL * * */ +/**********************************************************************/ + +#define alloc_content _glp_mpl_alloc_content +void alloc_content(MPL *mpl); +/* allocate content arrays for all model objects */ + +#define generate_model _glp_mpl_generate_model +void generate_model(MPL *mpl); +/* generate model */ + +#define build_problem _glp_mpl_build_problem +void build_problem(MPL *mpl); +/* build problem instance */ + +#define postsolve_model _glp_mpl_postsolve_model +void postsolve_model(MPL *mpl); +/* postsolve model */ + +#define clean_model _glp_mpl_clean_model +void clean_model(MPL *mpl); +/* clean model content */ + +/**********************************************************************/ +/* * * INPUT/OUTPUT * * */ +/**********************************************************************/ + +#define open_input _glp_mpl_open_input +void open_input(MPL *mpl, char *file); +/* open input text file */ + +#define read_char _glp_mpl_read_char +int read_char(MPL *mpl); +/* read next character from input text file */ + +#define close_input _glp_mpl_close_input +void close_input(MPL *mpl); +/* close input text file */ + +#define open_output _glp_mpl_open_output +void open_output(MPL *mpl, char *file); +/* open output text file */ + +#define write_char _glp_mpl_write_char +void write_char(MPL *mpl, int c); +/* write next character to output text file */ + +#define write_text _glp_mpl_write_text +void write_text(MPL *mpl, char *fmt, ...); +/* format and write text to output text file */ + +#define flush_output _glp_mpl_flush_output +void flush_output(MPL *mpl); +/* finalize writing data to output text file */ + +/**********************************************************************/ +/* * * SOLVER INTERFACE * * */ +/**********************************************************************/ + +#define MPL_FR 401 /* free (unbounded) */ +#define MPL_LO 402 /* lower bound */ +#define MPL_UP 403 /* upper bound */ +#define MPL_DB 404 /* both lower and upper bounds */ +#define MPL_FX 405 /* fixed */ + +#define MPL_ST 411 /* constraint */ +#define MPL_MIN 412 /* objective (minimization) */ +#define MPL_MAX 413 /* objective (maximization) */ + +#define MPL_NUM 421 /* continuous */ +#define MPL_INT 422 /* integer */ +#define MPL_BIN 423 /* binary */ + +#define error _glp_mpl_error +void error(MPL *mpl, char *fmt, ...); +/* print error message and terminate model processing */ + +#define warning _glp_mpl_warning +void warning(MPL *mpl, char *fmt, ...); +/* print warning message and continue model processing */ + +#define mpl_initialize _glp_mpl_initialize +MPL *mpl_initialize(void); +/* create and initialize translator database */ + +#define mpl_read_model _glp_mpl_read_model +int mpl_read_model(MPL *mpl, char *file, int skip_data); +/* read model section and optional data section */ + +#define mpl_read_data _glp_mpl_read_data +int mpl_read_data(MPL *mpl, char *file); +/* read data section */ + +#define mpl_generate _glp_mpl_generate +int mpl_generate(MPL *mpl, char *file); +/* generate model */ + +#define mpl_get_prob_name _glp_mpl_get_prob_name +char *mpl_get_prob_name(MPL *mpl); +/* obtain problem (model) name */ + +#define mpl_get_num_rows _glp_mpl_get_num_rows +int mpl_get_num_rows(MPL *mpl); +/* determine number of rows */ + +#define mpl_get_num_cols _glp_mpl_get_num_cols +int mpl_get_num_cols(MPL *mpl); +/* determine number of columns */ + +#define mpl_get_row_name _glp_mpl_get_row_name +char *mpl_get_row_name(MPL *mpl, int i); +/* obtain row name */ + +#define mpl_get_row_kind _glp_mpl_get_row_kind +int mpl_get_row_kind(MPL *mpl, int i); +/* determine row kind */ + +#define mpl_get_row_bnds _glp_mpl_get_row_bnds +int mpl_get_row_bnds(MPL *mpl, int i, double *lb, double *ub); +/* obtain row bounds */ + +#define mpl_get_mat_row _glp_mpl_get_mat_row +int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[]); +/* obtain row of the constraint matrix */ + +#define mpl_get_row_c0 _glp_mpl_get_row_c0 +double mpl_get_row_c0(MPL *mpl, int i); +/* obtain constant term of free row */ + +#define mpl_get_col_name _glp_mpl_get_col_name +char *mpl_get_col_name(MPL *mpl, int j); +/* obtain column name */ + +#define mpl_get_col_kind _glp_mpl_get_col_kind +int mpl_get_col_kind(MPL *mpl, int j); +/* determine column kind */ + +#define mpl_get_col_bnds _glp_mpl_get_col_bnds +int mpl_get_col_bnds(MPL *mpl, int j, double *lb, double *ub); +/* obtain column bounds */ + +#define mpl_has_solve_stmt _glp_mpl_has_solve_stmt +int mpl_has_solve_stmt(MPL *mpl); +/* check if model has solve statement */ + +#if 1 /* 15/V-2010 */ +#define mpl_put_row_soln _glp_mpl_put_row_soln +void mpl_put_row_soln(MPL *mpl, int i, int stat, double prim, + double dual); +/* store row (constraint/objective) solution components */ +#endif + +#if 1 /* 15/V-2010 */ +#define mpl_put_col_soln _glp_mpl_put_col_soln +void mpl_put_col_soln(MPL *mpl, int j, int stat, double prim, + double dual); +/* store column (variable) solution components */ +#endif + +#if 0 /* 15/V-2010 */ +#define mpl_put_col_value _glp_mpl_put_col_value +void mpl_put_col_value(MPL *mpl, int j, double val); +/* store column value */ +#endif + +#define mpl_postsolve _glp_mpl_postsolve +int mpl_postsolve(MPL *mpl); +/* postsolve model */ + +#define mpl_terminate _glp_mpl_terminate +void mpl_terminate(MPL *mpl); +/* free all resources used by translator */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl01.c b/resources/3rdparty/glpk-4.53/src/glpmpl01.c new file mode 100644 index 000000000..db7af246b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpmpl01.c @@ -0,0 +1,4715 @@ +/* glpmpl01.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "glpmpl.h" + +#define dmp_get_atomv dmp_get_atom + +/**********************************************************************/ +/* * * PROCESSING MODEL SECTION * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- enter_context - enter current token into context queue. +-- +-- This routine enters the current token into the context queue. */ + +void enter_context(MPL *mpl) +{ char *image, *s; + if (mpl->token == T_EOF) + image = "_|_"; + else if (mpl->token == T_STRING) + image = "'...'"; + else + image = mpl->image; + xassert(0 <= mpl->c_ptr && mpl->c_ptr < CONTEXT_SIZE); + mpl->context[mpl->c_ptr++] = ' '; + if (mpl->c_ptr == CONTEXT_SIZE) mpl->c_ptr = 0; + for (s = image; *s != '\0'; s++) + { mpl->context[mpl->c_ptr++] = *s; + if (mpl->c_ptr == CONTEXT_SIZE) mpl->c_ptr = 0; + } + return; +} + +/*---------------------------------------------------------------------- +-- print_context - print current content of context queue. +-- +-- This routine prints current content of the context queue. */ + +void print_context(MPL *mpl) +{ int c; + while (mpl->c_ptr > 0) + { mpl->c_ptr--; + c = mpl->context[0]; + memmove(mpl->context, mpl->context+1, CONTEXT_SIZE-1); + mpl->context[CONTEXT_SIZE-1] = (char)c; + } + xprintf("Context: %s%.*s\n", mpl->context[0] == ' ' ? "" : "...", + CONTEXT_SIZE, mpl->context); + return; +} + +/*---------------------------------------------------------------------- +-- get_char - scan next character from input text file. +-- +-- This routine scans a next ASCII character from the input text file. +-- In case of end-of-file, the character is assigned EOF. */ + +void get_char(MPL *mpl) +{ int c; + if (mpl->c == EOF) goto done; + if (mpl->c == '\n') mpl->line++; + c = read_char(mpl); + if (c == EOF) + { if (mpl->c == '\n') + mpl->line--; + else + warning(mpl, "final NL missing before end of file"); + } + else if (c == '\n') + ; + else if (isspace(c)) + c = ' '; + else if (iscntrl(c)) + { enter_context(mpl); + error(mpl, "control character 0x%02X not allowed", c); + } + mpl->c = c; +done: return; +} + +/*---------------------------------------------------------------------- +-- append_char - append character to current token. +-- +-- This routine appends the current character to the current token and +-- then scans a next character. */ + +void append_char(MPL *mpl) +{ xassert(0 <= mpl->imlen && mpl->imlen <= MAX_LENGTH); + if (mpl->imlen == MAX_LENGTH) + { switch (mpl->token) + { case T_NAME: + enter_context(mpl); + error(mpl, "symbolic name %s... too long", mpl->image); + case T_SYMBOL: + enter_context(mpl); + error(mpl, "symbol %s... too long", mpl->image); + case T_NUMBER: + enter_context(mpl); + error(mpl, "numeric literal %s... too long", mpl->image); + case T_STRING: + enter_context(mpl); + error(mpl, "string literal too long"); + default: + xassert(mpl != mpl); + } + } + mpl->image[mpl->imlen++] = (char)mpl->c; + mpl->image[mpl->imlen] = '\0'; + get_char(mpl); + return; +} + +/*---------------------------------------------------------------------- +-- get_token - scan next token from input text file. +-- +-- This routine scans a next token from the input text file using the +-- standard finite automation technique. */ + +void get_token(MPL *mpl) +{ /* save the current token */ + mpl->b_token = mpl->token; + mpl->b_imlen = mpl->imlen; + strcpy(mpl->b_image, mpl->image); + mpl->b_value = mpl->value; + /* if the next token is already scanned, make it current */ + if (mpl->f_scan) + { mpl->f_scan = 0; + mpl->token = mpl->f_token; + mpl->imlen = mpl->f_imlen; + strcpy(mpl->image, mpl->f_image); + mpl->value = mpl->f_value; + goto done; + } +loop: /* nothing has been scanned so far */ + mpl->token = 0; + mpl->imlen = 0; + mpl->image[0] = '\0'; + mpl->value = 0.0; + /* skip any uninteresting characters */ + while (mpl->c == ' ' || mpl->c == '\n') get_char(mpl); + /* recognize and construct the token */ + if (mpl->c == EOF) + { /* end-of-file reached */ + mpl->token = T_EOF; + } + else if (mpl->c == '#') + { /* comment; skip anything until end-of-line */ + while (mpl->c != '\n' && mpl->c != EOF) get_char(mpl); + goto loop; + } + else if (!mpl->flag_d && (isalpha(mpl->c) || mpl->c == '_')) + { /* symbolic name or reserved keyword */ + mpl->token = T_NAME; + while (isalnum(mpl->c) || mpl->c == '_') append_char(mpl); + if (strcmp(mpl->image, "and") == 0) + mpl->token = T_AND; + else if (strcmp(mpl->image, "by") == 0) + mpl->token = T_BY; + else if (strcmp(mpl->image, "cross") == 0) + mpl->token = T_CROSS; + else if (strcmp(mpl->image, "diff") == 0) + mpl->token = T_DIFF; + else if (strcmp(mpl->image, "div") == 0) + mpl->token = T_DIV; + else if (strcmp(mpl->image, "else") == 0) + mpl->token = T_ELSE; + else if (strcmp(mpl->image, "if") == 0) + mpl->token = T_IF; + else if (strcmp(mpl->image, "in") == 0) + mpl->token = T_IN; +#if 1 /* 21/VII-2006 */ + else if (strcmp(mpl->image, "Infinity") == 0) + mpl->token = T_INFINITY; +#endif + else if (strcmp(mpl->image, "inter") == 0) + mpl->token = T_INTER; + else if (strcmp(mpl->image, "less") == 0) + mpl->token = T_LESS; + else if (strcmp(mpl->image, "mod") == 0) + mpl->token = T_MOD; + else if (strcmp(mpl->image, "not") == 0) + mpl->token = T_NOT; + else if (strcmp(mpl->image, "or") == 0) + mpl->token = T_OR; + else if (strcmp(mpl->image, "s") == 0 && mpl->c == '.') + { mpl->token = T_SPTP; + append_char(mpl); + if (mpl->c != 't') +sptp: { enter_context(mpl); + error(mpl, "keyword s.t. incomplete"); + } + append_char(mpl); + if (mpl->c != '.') goto sptp; + append_char(mpl); + } + else if (strcmp(mpl->image, "symdiff") == 0) + mpl->token = T_SYMDIFF; + else if (strcmp(mpl->image, "then") == 0) + mpl->token = T_THEN; + else if (strcmp(mpl->image, "union") == 0) + mpl->token = T_UNION; + else if (strcmp(mpl->image, "within") == 0) + mpl->token = T_WITHIN; + } + else if (!mpl->flag_d && isdigit(mpl->c)) + { /* numeric literal */ + mpl->token = T_NUMBER; + /* scan integer part */ + while (isdigit(mpl->c)) append_char(mpl); + /* scan optional fractional part */ + if (mpl->c == '.') + { append_char(mpl); + if (mpl->c == '.') + { /* hmm, it is not the fractional part, it is dots that + follow the integer part */ + mpl->imlen--; + mpl->image[mpl->imlen] = '\0'; + mpl->f_dots = 1; + goto conv; + } +frac: while (isdigit(mpl->c)) append_char(mpl); + } + /* scan optional decimal exponent */ + if (mpl->c == 'e' || mpl->c == 'E') + { append_char(mpl); + if (mpl->c == '+' || mpl->c == '-') append_char(mpl); + if (!isdigit(mpl->c)) + { enter_context(mpl); + error(mpl, "numeric literal %s incomplete", mpl->image); + } + while (isdigit(mpl->c)) append_char(mpl); + } + /* there must be no letter following the numeric literal */ + if (isalpha(mpl->c) || mpl->c == '_') + { enter_context(mpl); + error(mpl, "symbol %s%c... should be enclosed in quotes", + mpl->image, mpl->c); + } +conv: /* convert numeric literal to floating-point */ + if (str2num(mpl->image, &mpl->value)) +err: { enter_context(mpl); + error(mpl, "cannot convert numeric literal %s to floating-p" + "oint number", mpl->image); + } + } + else if (mpl->c == '\'' || mpl->c == '"') + { /* character string */ + int quote = mpl->c; + mpl->token = T_STRING; + get_char(mpl); + for (;;) + { if (mpl->c == '\n' || mpl->c == EOF) + { enter_context(mpl); + error(mpl, "unexpected end of line; string literal incom" + "plete"); + } + if (mpl->c == quote) + { get_char(mpl); + if (mpl->c != quote) break; + } + append_char(mpl); + } + } + else if (!mpl->flag_d && mpl->c == '+') + mpl->token = T_PLUS, append_char(mpl); + else if (!mpl->flag_d && mpl->c == '-') + mpl->token = T_MINUS, append_char(mpl); + else if (mpl->c == '*') + { mpl->token = T_ASTERISK, append_char(mpl); + if (mpl->c == '*') + mpl->token = T_POWER, append_char(mpl); + } + else if (mpl->c == '/') + { mpl->token = T_SLASH, append_char(mpl); + if (mpl->c == '*') + { /* comment sequence */ + get_char(mpl); + for (;;) + { if (mpl->c == EOF) + { /* do not call enter_context at this point */ + error(mpl, "unexpected end of file; comment sequence " + "incomplete"); + } + else if (mpl->c == '*') + { get_char(mpl); + if (mpl->c == '/') break; + } + else + get_char(mpl); + } + get_char(mpl); + goto loop; + } + } + else if (mpl->c == '^') + mpl->token = T_POWER, append_char(mpl); + else if (mpl->c == '<') + { mpl->token = T_LT, append_char(mpl); + if (mpl->c == '=') + mpl->token = T_LE, append_char(mpl); + else if (mpl->c == '>') + mpl->token = T_NE, append_char(mpl); +#if 1 /* 11/II-2008 */ + else if (mpl->c == '-') + mpl->token = T_INPUT, append_char(mpl); +#endif + } + else if (mpl->c == '=') + { mpl->token = T_EQ, append_char(mpl); + if (mpl->c == '=') append_char(mpl); + } + else if (mpl->c == '>') + { mpl->token = T_GT, append_char(mpl); + if (mpl->c == '=') + mpl->token = T_GE, append_char(mpl); +#if 1 /* 14/VII-2006 */ + else if (mpl->c == '>') + mpl->token = T_APPEND, append_char(mpl); +#endif + } + else if (mpl->c == '!') + { mpl->token = T_NOT, append_char(mpl); + if (mpl->c == '=') + mpl->token = T_NE, append_char(mpl); + } + else if (mpl->c == '&') + { mpl->token = T_CONCAT, append_char(mpl); + if (mpl->c == '&') + mpl->token = T_AND, append_char(mpl); + } + else if (mpl->c == '|') + { mpl->token = T_BAR, append_char(mpl); + if (mpl->c == '|') + mpl->token = T_OR, append_char(mpl); + } + else if (!mpl->flag_d && mpl->c == '.') + { mpl->token = T_POINT, append_char(mpl); + if (mpl->f_dots) + { /* dots; the first dot was read on the previous call to the + scanner, so the current character is the second dot */ + mpl->token = T_DOTS; + mpl->imlen = 2; + strcpy(mpl->image, ".."); + mpl->f_dots = 0; + } + else if (mpl->c == '.') + mpl->token = T_DOTS, append_char(mpl); + else if (isdigit(mpl->c)) + { /* numeric literal that begins with the decimal point */ + mpl->token = T_NUMBER, append_char(mpl); + goto frac; + } + } + else if (mpl->c == ',') + mpl->token = T_COMMA, append_char(mpl); + else if (mpl->c == ':') + { mpl->token = T_COLON, append_char(mpl); + if (mpl->c == '=') + mpl->token = T_ASSIGN, append_char(mpl); + } + else if (mpl->c == ';') + mpl->token = T_SEMICOLON, append_char(mpl); + else if (mpl->c == '(') + mpl->token = T_LEFT, append_char(mpl); + else if (mpl->c == ')') + mpl->token = T_RIGHT, append_char(mpl); + else if (mpl->c == '[') + mpl->token = T_LBRACKET, append_char(mpl); + else if (mpl->c == ']') + mpl->token = T_RBRACKET, append_char(mpl); + else if (mpl->c == '{') + mpl->token = T_LBRACE, append_char(mpl); + else if (mpl->c == '}') + mpl->token = T_RBRACE, append_char(mpl); +#if 1 /* 11/II-2008 */ + else if (mpl->c == '~') + mpl->token = T_TILDE, append_char(mpl); +#endif + else if (isalnum(mpl->c) || strchr("+-._", mpl->c) != NULL) + { /* symbol */ + xassert(mpl->flag_d); + mpl->token = T_SYMBOL; + while (isalnum(mpl->c) || strchr("+-._", mpl->c) != NULL) + append_char(mpl); + switch (str2num(mpl->image, &mpl->value)) + { case 0: + mpl->token = T_NUMBER; + break; + case 1: + goto err; + case 2: + break; + default: + xassert(mpl != mpl); + } + } + else + { enter_context(mpl); + error(mpl, "character %c not allowed", mpl->c); + } + /* enter the current token into the context queue */ + enter_context(mpl); + /* reset the flag, which may be set by indexing_expression() and + is used by expression_list() */ + mpl->flag_x = 0; +done: return; +} + +/*---------------------------------------------------------------------- +-- unget_token - return current token back to input stream. +-- +-- This routine returns the current token back to the input stream, so +-- the previously scanned token becomes the current one. */ + +void unget_token(MPL *mpl) +{ /* save the current token, which becomes the next one */ + xassert(!mpl->f_scan); + mpl->f_scan = 1; + mpl->f_token = mpl->token; + mpl->f_imlen = mpl->imlen; + strcpy(mpl->f_image, mpl->image); + mpl->f_value = mpl->value; + /* restore the previous token, which becomes the current one */ + mpl->token = mpl->b_token; + mpl->imlen = mpl->b_imlen; + strcpy(mpl->image, mpl->b_image); + mpl->value = mpl->b_value; + return; +} + +/*---------------------------------------------------------------------- +-- is_keyword - check if current token is given non-reserved keyword. +-- +-- If the current token is given (non-reserved) keyword, this routine +-- returns non-zero. Otherwise zero is returned. */ + +int is_keyword(MPL *mpl, char *keyword) +{ return + mpl->token == T_NAME && strcmp(mpl->image, keyword) == 0; +} + +/*---------------------------------------------------------------------- +-- is_reserved - check if current token is reserved keyword. +-- +-- If the current token is a reserved keyword, this routine returns +-- non-zero. Otherwise zero is returned. */ + +int is_reserved(MPL *mpl) +{ return + mpl->token == T_AND && mpl->image[0] == 'a' || + mpl->token == T_BY || + mpl->token == T_CROSS || + mpl->token == T_DIFF || + mpl->token == T_DIV || + mpl->token == T_ELSE || + mpl->token == T_IF || + mpl->token == T_IN || + mpl->token == T_INTER || + mpl->token == T_LESS || + mpl->token == T_MOD || + mpl->token == T_NOT && mpl->image[0] == 'n' || + mpl->token == T_OR && mpl->image[0] == 'o' || + mpl->token == T_SYMDIFF || + mpl->token == T_THEN || + mpl->token == T_UNION || + mpl->token == T_WITHIN; +} + +/*---------------------------------------------------------------------- +-- make_code - generate pseudo-code (basic routine). +-- +-- This routine generates specified pseudo-code. It is assumed that all +-- other translator routines use this basic routine. */ + +CODE *make_code(MPL *mpl, int op, OPERANDS *arg, int type, int dim) +{ CODE *code; + DOMAIN *domain; + DOMAIN_BLOCK *block; + ARG_LIST *e; + /* generate pseudo-code */ + code = alloc(CODE); + code->op = op; + code->vflag = 0; /* is inherited from operand(s) */ + /* copy operands and also make them referring to the pseudo-code + being generated, because the latter becomes the parent for all + its operands */ + memset(&code->arg, '?', sizeof(OPERANDS)); + switch (op) + { case O_NUMBER: + code->arg.num = arg->num; + break; + case O_STRING: + code->arg.str = arg->str; + break; + case O_INDEX: + code->arg.index.slot = arg->index.slot; + code->arg.index.next = arg->index.next; + break; + case O_MEMNUM: + case O_MEMSYM: + for (e = arg->par.list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.par.par = arg->par.par; + code->arg.par.list = arg->par.list; + break; + case O_MEMSET: + for (e = arg->set.list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.set.set = arg->set.set; + code->arg.set.list = arg->set.list; + break; + case O_MEMVAR: + for (e = arg->var.list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.var.var = arg->var.var; + code->arg.var.list = arg->var.list; +#if 1 /* 15/V-2010 */ + code->arg.var.suff = arg->var.suff; +#endif + break; +#if 1 /* 15/V-2010 */ + case O_MEMCON: + for (e = arg->con.list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.con.con = arg->con.con; + code->arg.con.list = arg->con.list; + code->arg.con.suff = arg->con.suff; + break; +#endif + case O_TUPLE: + case O_MAKE: + for (e = arg->list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.list = arg->list; + break; + case O_SLICE: + xassert(arg->slice != NULL); + code->arg.slice = arg->slice; + break; + case O_IRAND224: + case O_UNIFORM01: + case O_NORMAL01: + case O_GMTIME: + code->vflag = 1; + break; + case O_CVTNUM: + case O_CVTSYM: + case O_CVTLOG: + case O_CVTTUP: + case O_CVTLFM: + case O_PLUS: + case O_MINUS: + case O_NOT: + case O_ABS: + case O_CEIL: + case O_FLOOR: + case O_EXP: + case O_LOG: + case O_LOG10: + case O_SQRT: + case O_SIN: + case O_COS: + case O_ATAN: + case O_ROUND: + case O_TRUNC: + case O_CARD: + case O_LENGTH: + /* unary operation */ + xassert(arg->arg.x != NULL); + xassert(arg->arg.x->up == NULL); + arg->arg.x->up = code; + code->vflag |= arg->arg.x->vflag; + code->arg.arg.x = arg->arg.x; + break; + case O_ADD: + case O_SUB: + case O_LESS: + case O_MUL: + case O_DIV: + case O_IDIV: + case O_MOD: + case O_POWER: + case O_ATAN2: + case O_ROUND2: + case O_TRUNC2: + case O_UNIFORM: + if (op == O_UNIFORM) code->vflag = 1; + case O_NORMAL: + if (op == O_NORMAL) code->vflag = 1; + case O_CONCAT: + case O_LT: + case O_LE: + case O_EQ: + case O_GE: + case O_GT: + case O_NE: + case O_AND: + case O_OR: + case O_UNION: + case O_DIFF: + case O_SYMDIFF: + case O_INTER: + case O_CROSS: + case O_IN: + case O_NOTIN: + case O_WITHIN: + case O_NOTWITHIN: + case O_SUBSTR: + case O_STR2TIME: + case O_TIME2STR: + /* binary operation */ + xassert(arg->arg.x != NULL); + xassert(arg->arg.x->up == NULL); + arg->arg.x->up = code; + code->vflag |= arg->arg.x->vflag; + xassert(arg->arg.y != NULL); + xassert(arg->arg.y->up == NULL); + arg->arg.y->up = code; + code->vflag |= arg->arg.y->vflag; + code->arg.arg.x = arg->arg.x; + code->arg.arg.y = arg->arg.y; + break; + case O_DOTS: + case O_FORK: + case O_SUBSTR3: + /* ternary operation */ + xassert(arg->arg.x != NULL); + xassert(arg->arg.x->up == NULL); + arg->arg.x->up = code; + code->vflag |= arg->arg.x->vflag; + xassert(arg->arg.y != NULL); + xassert(arg->arg.y->up == NULL); + arg->arg.y->up = code; + code->vflag |= arg->arg.y->vflag; + if (arg->arg.z != NULL) + { xassert(arg->arg.z->up == NULL); + arg->arg.z->up = code; + code->vflag |= arg->arg.z->vflag; + } + code->arg.arg.x = arg->arg.x; + code->arg.arg.y = arg->arg.y; + code->arg.arg.z = arg->arg.z; + break; + case O_MIN: + case O_MAX: + /* n-ary operation */ + for (e = arg->list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.list = arg->list; + break; + case O_SUM: + case O_PROD: + case O_MINIMUM: + case O_MAXIMUM: + case O_FORALL: + case O_EXISTS: + case O_SETOF: + case O_BUILD: + /* iterated operation */ + domain = arg->loop.domain; + xassert(domain != NULL); + if (domain->code != NULL) + { xassert(domain->code->up == NULL); + domain->code->up = code; + code->vflag |= domain->code->vflag; + } + for (block = domain->list; block != NULL; block = + block->next) + { xassert(block->code != NULL); + xassert(block->code->up == NULL); + block->code->up = code; + code->vflag |= block->code->vflag; + } + if (arg->loop.x != NULL) + { xassert(arg->loop.x->up == NULL); + arg->loop.x->up = code; + code->vflag |= arg->loop.x->vflag; + } + code->arg.loop.domain = arg->loop.domain; + code->arg.loop.x = arg->loop.x; + break; + default: + xassert(op != op); + } + /* set other attributes of the pseudo-code */ + code->type = type; + code->dim = dim; + code->up = NULL; + code->valid = 0; + memset(&code->value, '?', sizeof(VALUE)); + return code; +} + +/*---------------------------------------------------------------------- +-- make_unary - generate pseudo-code for unary operation. +-- +-- This routine generates pseudo-code for unary operation. */ + +CODE *make_unary(MPL *mpl, int op, CODE *x, int type, int dim) +{ CODE *code; + OPERANDS arg; + xassert(x != NULL); + arg.arg.x = x; + code = make_code(mpl, op, &arg, type, dim); + return code; +} + +/*---------------------------------------------------------------------- +-- make_binary - generate pseudo-code for binary operation. +-- +-- This routine generates pseudo-code for binary operation. */ + +CODE *make_binary(MPL *mpl, int op, CODE *x, CODE *y, int type, + int dim) +{ CODE *code; + OPERANDS arg; + xassert(x != NULL); + xassert(y != NULL); + arg.arg.x = x; + arg.arg.y = y; + code = make_code(mpl, op, &arg, type, dim); + return code; +} + +/*---------------------------------------------------------------------- +-- make_ternary - generate pseudo-code for ternary operation. +-- +-- This routine generates pseudo-code for ternary operation. */ + +CODE *make_ternary(MPL *mpl, int op, CODE *x, CODE *y, CODE *z, + int type, int dim) +{ CODE *code; + OPERANDS arg; + xassert(x != NULL); + xassert(y != NULL); + /* third operand can be NULL */ + arg.arg.x = x; + arg.arg.y = y; + arg.arg.z = z; + code = make_code(mpl, op, &arg, type, dim); + return code; +} + +/*---------------------------------------------------------------------- +-- numeric_literal - parse reference to numeric literal. +-- +-- This routine parses primary expression using the syntax: +-- +-- <primary expression> ::= <numeric literal> */ + +CODE *numeric_literal(MPL *mpl) +{ CODE *code; + OPERANDS arg; + xassert(mpl->token == T_NUMBER); + arg.num = mpl->value; + code = make_code(mpl, O_NUMBER, &arg, A_NUMERIC, 0); + get_token(mpl /* <numeric literal> */); + return code; +} + +/*---------------------------------------------------------------------- +-- string_literal - parse reference to string literal. +-- +-- This routine parses primary expression using the syntax: +-- +-- <primary expression> ::= <string literal> */ + +CODE *string_literal(MPL *mpl) +{ CODE *code; + OPERANDS arg; + xassert(mpl->token == T_STRING); + arg.str = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(arg.str, mpl->image); + code = make_code(mpl, O_STRING, &arg, A_SYMBOLIC, 0); + get_token(mpl /* <string literal> */); + return code; +} + +/*---------------------------------------------------------------------- +-- create_arg_list - create empty operands list. +-- +-- This routine creates operands list, which is initially empty. */ + +ARG_LIST *create_arg_list(MPL *mpl) +{ ARG_LIST *list; + xassert(mpl == mpl); + list = NULL; + return list; +} + +/*---------------------------------------------------------------------- +-- expand_arg_list - append operand to operands list. +-- +-- This routine appends new operand to specified operands list. */ + +ARG_LIST *expand_arg_list(MPL *mpl, ARG_LIST *list, CODE *x) +{ ARG_LIST *tail, *temp; + xassert(x != NULL); + /* create new operands list entry */ + tail = alloc(ARG_LIST); + tail->x = x; + tail->next = NULL; + /* and append it to the operands list */ + if (list == NULL) + list = tail; + else + { for (temp = list; temp->next != NULL; temp = temp->next); + temp->next = tail; + } + return list; +} + +/*---------------------------------------------------------------------- +-- arg_list_len - determine length of operands list. +-- +-- This routine returns the number of operands in operands list. */ + +int arg_list_len(MPL *mpl, ARG_LIST *list) +{ ARG_LIST *temp; + int len; + xassert(mpl == mpl); + len = 0; + for (temp = list; temp != NULL; temp = temp->next) len++; + return len; +} + +/*---------------------------------------------------------------------- +-- subscript_list - parse subscript list. +-- +-- This routine parses subscript list using the syntax: +-- +-- <subscript list> ::= <subscript> +-- <subscript list> ::= <subscript list> , <subscript> +-- <subscript> ::= <expression 5> */ + +ARG_LIST *subscript_list(MPL *mpl) +{ ARG_LIST *list; + CODE *x; + list = create_arg_list(mpl); + for (;;) + { /* parse subscript expression */ + x = expression_5(mpl); + /* convert it to symbolic type, if necessary */ + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); + /* check that now the expression is of symbolic type */ + if (x->type != A_SYMBOLIC) + error(mpl, "subscript expression has invalid type"); + xassert(x->dim == 0); + /* and append it to the subscript list */ + list = expand_arg_list(mpl, list, x); + /* check a token that follows the subscript expression */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RBRACKET) + break; + else + error(mpl, "syntax error in subscript list"); + } + return list; +} + +#if 1 /* 15/V-2010 */ +/*---------------------------------------------------------------------- +-- object_reference - parse reference to named object. +-- +-- This routine parses primary expression using the syntax: +-- +-- <primary expression> ::= <dummy index> +-- <primary expression> ::= <set name> +-- <primary expression> ::= <set name> [ <subscript list> ] +-- <primary expression> ::= <parameter name> +-- <primary expression> ::= <parameter name> [ <subscript list> ] +-- <primary expression> ::= <variable name> <suffix> +-- <primary expression> ::= <variable name> [ <subscript list> ] +-- <suffix> +-- <primary expression> ::= <constraint name> <suffix> +-- <primary expression> ::= <constraint name> [ <subscript list> ] +-- <suffix> +-- <dummy index> ::= <symbolic name> +-- <set name> ::= <symbolic name> +-- <parameter name> ::= <symbolic name> +-- <variable name> ::= <symbolic name> +-- <constraint name> ::= <symbolic name> +-- <suffix> ::= <empty> | .lb | .ub | .status | .val | .dual */ + +CODE *object_reference(MPL *mpl) +{ AVLNODE *node; + DOMAIN_SLOT *slot; + SET *set; + PARAMETER *par; + VARIABLE *var; + CONSTRAINT *con; + ARG_LIST *list; + OPERANDS arg; + CODE *code; + char *name; + int dim, suff; + /* find the object in the symbolic name table */ + xassert(mpl->token == T_NAME); + node = avl_find_node(mpl->tree, mpl->image); + if (node == NULL) + error(mpl, "%s not defined", mpl->image); + /* check the object type and obtain its dimension */ + switch (avl_get_node_type(node)) + { case A_INDEX: + /* dummy index */ + slot = (DOMAIN_SLOT *)avl_get_node_link(node); + name = slot->name; + dim = 0; + break; + case A_SET: + /* model set */ + set = (SET *)avl_get_node_link(node); + name = set->name; + dim = set->dim; + /* if a set object is referenced in its own declaration and + the dimen attribute is not specified yet, use dimen 1 by + default */ + if (set->dimen == 0) set->dimen = 1; + break; + case A_PARAMETER: + /* model parameter */ + par = (PARAMETER *)avl_get_node_link(node); + name = par->name; + dim = par->dim; + break; + case A_VARIABLE: + /* model variable */ + var = (VARIABLE *)avl_get_node_link(node); + name = var->name; + dim = var->dim; + break; + case A_CONSTRAINT: + /* model constraint or objective */ + con = (CONSTRAINT *)avl_get_node_link(node); + name = con->name; + dim = con->dim; + break; + default: + xassert(node != node); + } + get_token(mpl /* <symbolic name> */); + /* parse optional subscript list */ + if (mpl->token == T_LBRACKET) + { /* subscript list is specified */ + if (dim == 0) + error(mpl, "%s cannot be subscripted", name); + get_token(mpl /* [ */); + list = subscript_list(mpl); + if (dim != arg_list_len(mpl, list)) + error(mpl, "%s must have %d subscript%s rather than %d", + name, dim, dim == 1 ? "" : "s", arg_list_len(mpl, list)); + xassert(mpl->token == T_RBRACKET); + get_token(mpl /* ] */); + } + else + { /* subscript list is not specified */ + if (dim != 0) + error(mpl, "%s must be subscripted", name); + list = create_arg_list(mpl); + } + /* parse optional suffix */ + if (!mpl->flag_s && avl_get_node_type(node) == A_VARIABLE) + suff = DOT_NONE; + else + suff = DOT_VAL; + if (mpl->token == T_POINT) + { get_token(mpl /* . */); + if (mpl->token != T_NAME) + error(mpl, "invalid use of period"); + if (!(avl_get_node_type(node) == A_VARIABLE || + avl_get_node_type(node) == A_CONSTRAINT)) + error(mpl, "%s cannot have a suffix", name); + if (strcmp(mpl->image, "lb") == 0) + suff = DOT_LB; + else if (strcmp(mpl->image, "ub") == 0) + suff = DOT_UB; + else if (strcmp(mpl->image, "status") == 0) + suff = DOT_STATUS; + else if (strcmp(mpl->image, "val") == 0) + suff = DOT_VAL; + else if (strcmp(mpl->image, "dual") == 0) + suff = DOT_DUAL; + else + error(mpl, "suffix .%s invalid", mpl->image); + get_token(mpl /* suffix */); + } + /* generate pseudo-code to take value of the object */ + switch (avl_get_node_type(node)) + { case A_INDEX: + arg.index.slot = slot; + arg.index.next = slot->list; + code = make_code(mpl, O_INDEX, &arg, A_SYMBOLIC, 0); + slot->list = code; + break; + case A_SET: + arg.set.set = set; + arg.set.list = list; + code = make_code(mpl, O_MEMSET, &arg, A_ELEMSET, + set->dimen); + break; + case A_PARAMETER: + arg.par.par = par; + arg.par.list = list; + if (par->type == A_SYMBOLIC) + code = make_code(mpl, O_MEMSYM, &arg, A_SYMBOLIC, 0); + else + code = make_code(mpl, O_MEMNUM, &arg, A_NUMERIC, 0); + break; + case A_VARIABLE: + if (!mpl->flag_s && (suff == DOT_STATUS || suff == DOT_VAL + || suff == DOT_DUAL)) + error(mpl, "invalid reference to status, primal value, o" + "r dual value of variable %s above solve statement", + var->name); + arg.var.var = var; + arg.var.list = list; + arg.var.suff = suff; + code = make_code(mpl, O_MEMVAR, &arg, suff == DOT_NONE ? + A_FORMULA : A_NUMERIC, 0); + break; + case A_CONSTRAINT: + if (!mpl->flag_s && (suff == DOT_STATUS || suff == DOT_VAL + || suff == DOT_DUAL)) + error(mpl, "invalid reference to status, primal value, o" + "r dual value of %s %s above solve statement", + con->type == A_CONSTRAINT ? "constraint" : "objective" + , con->name); + arg.con.con = con; + arg.con.list = list; + arg.con.suff = suff; + code = make_code(mpl, O_MEMCON, &arg, A_NUMERIC, 0); + break; + default: + xassert(node != node); + } + return code; +} +#endif + +/*---------------------------------------------------------------------- +-- numeric_argument - parse argument passed to built-in function. +-- +-- This routine parses an argument passed to numeric built-in function +-- using the syntax: +-- +-- <arg> ::= <expression 5> */ + +CODE *numeric_argument(MPL *mpl, char *func) +{ CODE *x; + x = expression_5(mpl); + /* convert the argument to numeric type, if necessary */ + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + /* check that now the argument is of numeric type */ + if (x->type != A_NUMERIC) + error(mpl, "argument for %s has invalid type", func); + xassert(x->dim == 0); + return x; +} + +#if 1 /* 15/VII-2006 */ +CODE *symbolic_argument(MPL *mpl, char *func) +{ CODE *x; + x = expression_5(mpl); + /* convert the argument to symbolic type, if necessary */ + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); + /* check that now the argument is of symbolic type */ + if (x->type != A_SYMBOLIC) + error(mpl, "argument for %s has invalid type", func); + xassert(x->dim == 0); + return x; +} +#endif + +#if 1 /* 15/VII-2006 */ +CODE *elemset_argument(MPL *mpl, char *func) +{ CODE *x; + x = expression_9(mpl); + if (x->type != A_ELEMSET) + error(mpl, "argument for %s has invalid type", func); + xassert(x->dim > 0); + return x; +} +#endif + +/*---------------------------------------------------------------------- +-- function_reference - parse reference to built-in function. +-- +-- This routine parses primary expression using the syntax: +-- +-- <primary expression> ::= abs ( <arg> ) +-- <primary expression> ::= ceil ( <arg> ) +-- <primary expression> ::= floor ( <arg> ) +-- <primary expression> ::= exp ( <arg> ) +-- <primary expression> ::= log ( <arg> ) +-- <primary expression> ::= log10 ( <arg> ) +-- <primary expression> ::= max ( <arg list> ) +-- <primary expression> ::= min ( <arg list> ) +-- <primary expression> ::= sqrt ( <arg> ) +-- <primary expression> ::= sin ( <arg> ) +-- <primary expression> ::= cos ( <arg> ) +-- <primary expression> ::= atan ( <arg> ) +-- <primary expression> ::= atan2 ( <arg> , <arg> ) +-- <primary expression> ::= round ( <arg> ) +-- <primary expression> ::= round ( <arg> , <arg> ) +-- <primary expression> ::= trunc ( <arg> ) +-- <primary expression> ::= trunc ( <arg> , <arg> ) +-- <primary expression> ::= Irand224 ( ) +-- <primary expression> ::= Uniform01 ( ) +-- <primary expression> ::= Uniform ( <arg> , <arg> ) +-- <primary expression> ::= Normal01 ( ) +-- <primary expression> ::= Normal ( <arg> , <arg> ) +-- <primary expression> ::= card ( <arg> ) +-- <primary expression> ::= length ( <arg> ) +-- <primary expression> ::= substr ( <arg> , <arg> ) +-- <primary expression> ::= substr ( <arg> , <arg> , <arg> ) +-- <primary expression> ::= str2time ( <arg> , <arg> ) +-- <primary expression> ::= time2str ( <arg> , <arg> ) +-- <primary expression> ::= gmtime ( ) +-- <arg list> ::= <arg> +-- <arg list> ::= <arg list> , <arg> */ + +CODE *function_reference(MPL *mpl) +{ CODE *code; + OPERANDS arg; + int op; + char func[15+1]; + /* determine operation code */ + xassert(mpl->token == T_NAME); + if (strcmp(mpl->image, "abs") == 0) + op = O_ABS; + else if (strcmp(mpl->image, "ceil") == 0) + op = O_CEIL; + else if (strcmp(mpl->image, "floor") == 0) + op = O_FLOOR; + else if (strcmp(mpl->image, "exp") == 0) + op = O_EXP; + else if (strcmp(mpl->image, "log") == 0) + op = O_LOG; + else if (strcmp(mpl->image, "log10") == 0) + op = O_LOG10; + else if (strcmp(mpl->image, "sqrt") == 0) + op = O_SQRT; + else if (strcmp(mpl->image, "sin") == 0) + op = O_SIN; + else if (strcmp(mpl->image, "cos") == 0) + op = O_COS; + else if (strcmp(mpl->image, "atan") == 0) + op = O_ATAN; + else if (strcmp(mpl->image, "min") == 0) + op = O_MIN; + else if (strcmp(mpl->image, "max") == 0) + op = O_MAX; + else if (strcmp(mpl->image, "round") == 0) + op = O_ROUND; + else if (strcmp(mpl->image, "trunc") == 0) + op = O_TRUNC; + else if (strcmp(mpl->image, "Irand224") == 0) + op = O_IRAND224; + else if (strcmp(mpl->image, "Uniform01") == 0) + op = O_UNIFORM01; + else if (strcmp(mpl->image, "Uniform") == 0) + op = O_UNIFORM; + else if (strcmp(mpl->image, "Normal01") == 0) + op = O_NORMAL01; + else if (strcmp(mpl->image, "Normal") == 0) + op = O_NORMAL; + else if (strcmp(mpl->image, "card") == 0) + op = O_CARD; + else if (strcmp(mpl->image, "length") == 0) + op = O_LENGTH; + else if (strcmp(mpl->image, "substr") == 0) + op = O_SUBSTR; + else if (strcmp(mpl->image, "str2time") == 0) + op = O_STR2TIME; + else if (strcmp(mpl->image, "time2str") == 0) + op = O_TIME2STR; + else if (strcmp(mpl->image, "gmtime") == 0) + op = O_GMTIME; + else + error(mpl, "function %s unknown", mpl->image); + /* save symbolic name of the function */ + strcpy(func, mpl->image); + xassert(strlen(func) < sizeof(func)); + get_token(mpl /* <symbolic name> */); + /* check the left parenthesis that follows the function name */ + xassert(mpl->token == T_LEFT); + get_token(mpl /* ( */); + /* parse argument list */ + if (op == O_MIN || op == O_MAX) + { /* min and max allow arbitrary number of arguments */ + arg.list = create_arg_list(mpl); + /* parse argument list */ + for (;;) + { /* parse argument and append it to the operands list */ + arg.list = expand_arg_list(mpl, arg.list, + numeric_argument(mpl, func)); + /* check a token that follows the argument */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RIGHT) + break; + else + error(mpl, "syntax error in argument list for %s", func); + } + } + else if (op == O_IRAND224 || op == O_UNIFORM01 || op == + O_NORMAL01 || op == O_GMTIME) + { /* Irand224, Uniform01, Normal01, gmtime need no arguments */ + if (mpl->token != T_RIGHT) + error(mpl, "%s needs no arguments", func); + } + else if (op == O_UNIFORM || op == O_NORMAL) + { /* Uniform and Normal need two arguments */ + /* parse the first argument */ + arg.arg.x = numeric_argument(mpl, func); + /* check a token that follows the first argument */ + if (mpl->token == T_COMMA) + ; + else if (mpl->token == T_RIGHT) + error(mpl, "%s needs two arguments", func); + else + error(mpl, "syntax error in argument for %s", func); + get_token(mpl /* , */); + /* parse the second argument */ + arg.arg.y = numeric_argument(mpl, func); + /* check a token that follows the second argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs two argument", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + else if (op == O_ATAN || op == O_ROUND || op == O_TRUNC) + { /* atan, round, and trunc need one or two arguments */ + /* parse the first argument */ + arg.arg.x = numeric_argument(mpl, func); + /* parse the second argument, if specified */ + if (mpl->token == T_COMMA) + { switch (op) + { case O_ATAN: op = O_ATAN2; break; + case O_ROUND: op = O_ROUND2; break; + case O_TRUNC: op = O_TRUNC2; break; + default: xassert(op != op); + } + get_token(mpl /* , */); + arg.arg.y = numeric_argument(mpl, func); + } + /* check a token that follows the last argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs one or two arguments", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + else if (op == O_SUBSTR) + { /* substr needs two or three arguments */ + /* parse the first argument */ + arg.arg.x = symbolic_argument(mpl, func); + /* check a token that follows the first argument */ + if (mpl->token == T_COMMA) + ; + else if (mpl->token == T_RIGHT) + error(mpl, "%s needs two or three arguments", func); + else + error(mpl, "syntax error in argument for %s", func); + get_token(mpl /* , */); + /* parse the second argument */ + arg.arg.y = numeric_argument(mpl, func); + /* parse the third argument, if specified */ + if (mpl->token == T_COMMA) + { op = O_SUBSTR3; + get_token(mpl /* , */); + arg.arg.z = numeric_argument(mpl, func); + } + /* check a token that follows the last argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs two or three arguments", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + else if (op == O_STR2TIME) + { /* str2time needs two arguments, both symbolic */ + /* parse the first argument */ + arg.arg.x = symbolic_argument(mpl, func); + /* check a token that follows the first argument */ + if (mpl->token == T_COMMA) + ; + else if (mpl->token == T_RIGHT) + error(mpl, "%s needs two arguments", func); + else + error(mpl, "syntax error in argument for %s", func); + get_token(mpl /* , */); + /* parse the second argument */ + arg.arg.y = symbolic_argument(mpl, func); + /* check a token that follows the second argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs two argument", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + else if (op == O_TIME2STR) + { /* time2str needs two arguments, numeric and symbolic */ + /* parse the first argument */ + arg.arg.x = numeric_argument(mpl, func); + /* check a token that follows the first argument */ + if (mpl->token == T_COMMA) + ; + else if (mpl->token == T_RIGHT) + error(mpl, "%s needs two arguments", func); + else + error(mpl, "syntax error in argument for %s", func); + get_token(mpl /* , */); + /* parse the second argument */ + arg.arg.y = symbolic_argument(mpl, func); + /* check a token that follows the second argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs two argument", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + else + { /* other functions need one argument */ + if (op == O_CARD) + arg.arg.x = elemset_argument(mpl, func); + else if (op == O_LENGTH) + arg.arg.x = symbolic_argument(mpl, func); + else + arg.arg.x = numeric_argument(mpl, func); + /* check a token that follows the argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs one argument", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + /* make pseudo-code to call the built-in function */ + if (op == O_SUBSTR || op == O_SUBSTR3 || op == O_TIME2STR) + code = make_code(mpl, op, &arg, A_SYMBOLIC, 0); + else + code = make_code(mpl, op, &arg, A_NUMERIC, 0); + /* the reference ends with the right parenthesis */ + xassert(mpl->token == T_RIGHT); + get_token(mpl /* ) */); + return code; +} + +/*---------------------------------------------------------------------- +-- create_domain - create empty domain. +-- +-- This routine creates empty domain, which is initially empty, i.e. +-- has no domain blocks. */ + +DOMAIN *create_domain(MPL *mpl) +{ DOMAIN *domain; + domain = alloc(DOMAIN); + domain->list = NULL; + domain->code = NULL; + return domain; +} + +/*---------------------------------------------------------------------- +-- create_block - create empty domain block. +-- +-- This routine creates empty domain block, which is initially empty, +-- i.e. has no domain slots. */ + +DOMAIN_BLOCK *create_block(MPL *mpl) +{ DOMAIN_BLOCK *block; + block = alloc(DOMAIN_BLOCK); + block->list = NULL; + block->code = NULL; + block->backup = NULL; + block->next = NULL; + return block; +} + +/*---------------------------------------------------------------------- +-- append_block - append domain block to specified domain. +-- +-- This routine adds given domain block to the end of the block list of +-- specified domain. */ + +void append_block(MPL *mpl, DOMAIN *domain, DOMAIN_BLOCK *block) +{ DOMAIN_BLOCK *temp; + xassert(mpl == mpl); + xassert(domain != NULL); + xassert(block != NULL); + xassert(block->next == NULL); + if (domain->list == NULL) + domain->list = block; + else + { for (temp = domain->list; temp->next != NULL; temp = + temp->next); + temp->next = block; + } + return; +} + +/*---------------------------------------------------------------------- +-- append_slot - create and append new slot to domain block. +-- +-- This routine creates new domain slot and adds it to the end of slot +-- list of specified domain block. +-- +-- The parameter name is symbolic name of the dummy index associated +-- with the slot (the character string must be allocated). NULL means +-- the dummy index is not explicitly specified. +-- +-- The parameter code is pseudo-code for computing symbolic value, at +-- which the dummy index is bounded. NULL means the dummy index is free +-- in the domain scope. */ + +DOMAIN_SLOT *append_slot(MPL *mpl, DOMAIN_BLOCK *block, char *name, + CODE *code) +{ DOMAIN_SLOT *slot, *temp; + xassert(block != NULL); + slot = alloc(DOMAIN_SLOT); + slot->name = name; + slot->code = code; + slot->value = NULL; + slot->list = NULL; + slot->next = NULL; + if (block->list == NULL) + block->list = slot; + else + { for (temp = block->list; temp->next != NULL; temp = + temp->next); + temp->next = slot; + } + return slot; +} + +/*---------------------------------------------------------------------- +-- expression_list - parse expression list. +-- +-- This routine parses a list of one or more expressions enclosed into +-- the parentheses using the syntax: +-- +-- <primary expression> ::= ( <expression list> ) +-- <expression list> ::= <expression 13> +-- <expression list> ::= <expression 13> , <expression list> +-- +-- Note that this construction may have three different meanings: +-- +-- 1. If <expression list> consists of only one expression, <primary +-- expression> is a parenthesized expression, which may be of any +-- valid type (not necessarily 1-tuple). +-- +-- 2. If <expression list> consists of several expressions separated by +-- commae, where no expression is undeclared symbolic name, <primary +-- expression> is a n-tuple. +-- +-- 3. If <expression list> consists of several expressions separated by +-- commae, where at least one expression is undeclared symbolic name +-- (that denotes a dummy index), <primary expression> is a slice and +-- can be only used as constituent of indexing expression. */ + +#define max_dim 20 +/* maximal number of components allowed within parentheses */ + +CODE *expression_list(MPL *mpl) +{ CODE *code; + OPERANDS arg; + struct { char *name; CODE *code; } list[1+max_dim]; + int flag_x, next_token, dim, j, slice = 0; + xassert(mpl->token == T_LEFT); + /* the flag, which allows recognizing undeclared symbolic names + as dummy indices, will be automatically reset by get_token(), + so save it before scanning the next token */ + flag_x = mpl->flag_x; + get_token(mpl /* ( */); + /* parse <expression list> */ + for (dim = 1; ; dim++) + { if (dim > max_dim) + error(mpl, "too many components within parentheses"); + /* current component of <expression list> can be either dummy + index or expression */ + if (mpl->token == T_NAME) + { /* symbolic name is recognized as dummy index only if: + the flag, which allows that, is set, and + the name is followed by comma or right parenthesis, and + the name is undeclared */ + get_token(mpl /* <symbolic name> */); + next_token = mpl->token; + unget_token(mpl); + if (!(flag_x && + (next_token == T_COMMA || next_token == T_RIGHT) && + avl_find_node(mpl->tree, mpl->image) == NULL)) + { /* this is not dummy index */ + goto expr; + } + /* all dummy indices within the same slice must have unique + symbolic names */ + for (j = 1; j < dim; j++) + { if (list[j].name != NULL && strcmp(list[j].name, + mpl->image) == 0) + error(mpl, "duplicate dummy index %s not allowed", + mpl->image); + } + /* current component of <expression list> is dummy index */ + list[dim].name + = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(list[dim].name, mpl->image); + list[dim].code = NULL; + get_token(mpl /* <symbolic name> */); + /* <expression list> is a slice, because at least one dummy + index has appeared */ + slice = 1; + /* note that the context ( <dummy index> ) is not allowed, + i.e. in this case <primary expression> is considered as + a parenthesized expression */ + if (dim == 1 && mpl->token == T_RIGHT) + error(mpl, "%s not defined", list[dim].name); + } + else +expr: { /* current component of <expression list> is expression */ + code = expression_13(mpl); + /* if the current expression is followed by comma or it is + not the very first expression, entire <expression list> + is n-tuple or slice, in which case the current expression + should be converted to symbolic type, if necessary */ + if (mpl->token == T_COMMA || dim > 1) + { if (code->type == A_NUMERIC) + code = make_unary(mpl, O_CVTSYM, code, A_SYMBOLIC, 0); + /* now the expression must be of symbolic type */ + if (code->type != A_SYMBOLIC) + error(mpl, "component expression has invalid type"); + xassert(code->dim == 0); + } + list[dim].name = NULL; + list[dim].code = code; + } + /* check a token that follows the current component */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RIGHT) + break; + else + error(mpl, "right parenthesis missing where expected"); + } + /* generate pseudo-code for <primary expression> */ + if (dim == 1 && !slice) + { /* <primary expression> is a parenthesized expression */ + code = list[1].code; + } + else if (!slice) + { /* <primary expression> is a n-tuple */ + arg.list = create_arg_list(mpl); + for (j = 1; j <= dim; j++) + arg.list = expand_arg_list(mpl, arg.list, list[j].code); + code = make_code(mpl, O_TUPLE, &arg, A_TUPLE, dim); + } + else + { /* <primary expression> is a slice */ + arg.slice = create_block(mpl); + for (j = 1; j <= dim; j++) + append_slot(mpl, arg.slice, list[j].name, list[j].code); + /* note that actually pseudo-codes with op = O_SLICE are never + evaluated */ + code = make_code(mpl, O_SLICE, &arg, A_TUPLE, dim); + } + get_token(mpl /* ) */); + /* if <primary expression> is a slice, there must be the keyword + 'in', which follows the right parenthesis */ + if (slice && mpl->token != T_IN) + error(mpl, "keyword in missing where expected"); + /* if the slice flag is set and there is the keyword 'in', which + follows <primary expression>, the latter must be a slice */ + if (flag_x && mpl->token == T_IN && !slice) + { if (dim == 1) + error(mpl, "syntax error in indexing expression"); + else + error(mpl, "0-ary slice not allowed"); + } + return code; +} + +/*---------------------------------------------------------------------- +-- literal set - parse literal set. +-- +-- This routine parses literal set using the syntax: +-- +-- <literal set> ::= { <member list> } +-- <member list> ::= <member expression> +-- <member list> ::= <member list> , <member expression> +-- <member expression> ::= <expression 5> +-- +-- It is assumed that the left curly brace and the very first member +-- expression that follows it are already parsed. The right curly brace +-- remains unscanned on exit. */ + +CODE *literal_set(MPL *mpl, CODE *code) +{ OPERANDS arg; + int j; + xassert(code != NULL); + arg.list = create_arg_list(mpl); + /* parse <member list> */ + for (j = 1; ; j++) + { /* all member expressions must be n-tuples; so, if the current + expression is not n-tuple, convert it to 1-tuple */ + if (code->type == A_NUMERIC) + code = make_unary(mpl, O_CVTSYM, code, A_SYMBOLIC, 0); + if (code->type == A_SYMBOLIC) + code = make_unary(mpl, O_CVTTUP, code, A_TUPLE, 1); + /* now the expression must be n-tuple */ + if (code->type != A_TUPLE) + error(mpl, "member expression has invalid type"); + /* all member expressions must have identical dimension */ + if (arg.list != NULL && arg.list->x->dim != code->dim) + error(mpl, "member %d has %d component%s while member %d ha" + "s %d component%s", + j-1, arg.list->x->dim, arg.list->x->dim == 1 ? "" : "s", + j, code->dim, code->dim == 1 ? "" : "s"); + /* append the current expression to the member list */ + arg.list = expand_arg_list(mpl, arg.list, code); + /* check a token that follows the current expression */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RBRACE) + break; + else + error(mpl, "syntax error in literal set"); + /* parse the next expression that follows the comma */ + code = expression_5(mpl); + } + /* generate pseudo-code for <literal set> */ + code = make_code(mpl, O_MAKE, &arg, A_ELEMSET, arg.list->x->dim); + return code; +} + +/*---------------------------------------------------------------------- +-- indexing_expression - parse indexing expression. +-- +-- This routine parses indexing expression using the syntax: +-- +-- <indexing expression> ::= <literal set> +-- <indexing expression> ::= { <indexing list> } +-- <indexing expression> ::= { <indexing list> : <logical expression> } +-- <indexing list> ::= <indexing element> +-- <indexing list> ::= <indexing list> , <indexing element> +-- <indexing element> ::= <basic expression> +-- <indexing element> ::= <dummy index> in <basic expression> +-- <indexing element> ::= <slice> in <basic expression> +-- <dummy index> ::= <symbolic name> +-- <slice> ::= ( <expression list> ) +-- <basic expression> ::= <expression 9> +-- <logical expression> ::= <expression 13> +-- +-- This routine creates domain for <indexing expression>, where each +-- domain block corresponds to <indexing element>, and each domain slot +-- corresponds to individual indexing position. */ + +DOMAIN *indexing_expression(MPL *mpl) +{ DOMAIN *domain; + DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + CODE *code; + xassert(mpl->token == T_LBRACE); + get_token(mpl /* { */); + if (mpl->token == T_RBRACE) + error(mpl, "empty indexing expression not allowed"); + /* create domain to be constructed */ + domain = create_domain(mpl); + /* parse either <member list> or <indexing list> that follows the + left brace */ + for (;;) + { /* domain block for <indexing element> is not created yet */ + block = NULL; + /* pseudo-code for <basic expression> is not generated yet */ + code = NULL; + /* check a token, which <indexing element> begins with */ + if (mpl->token == T_NAME) + { /* it is a symbolic name */ + int next_token; + char *name; + /* symbolic name is recognized as dummy index only if it is + followed by the keyword 'in' and not declared */ + get_token(mpl /* <symbolic name> */); + next_token = mpl->token; + unget_token(mpl); + if (!(next_token == T_IN && + avl_find_node(mpl->tree, mpl->image) == NULL)) + { /* this is not dummy index; the symbolic name begins an + expression, which is either <basic expression> or the + very first <member expression> in <literal set> */ + goto expr; + } + /* create domain block with one slot, which is assigned the + dummy index */ + block = create_block(mpl); + name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(name, mpl->image); + append_slot(mpl, block, name, NULL); + get_token(mpl /* <symbolic name> */); + /* the keyword 'in' is already checked above */ + xassert(mpl->token == T_IN); + get_token(mpl /* in */); + /* <basic expression> that follows the keyword 'in' will be + parsed below */ + } + else if (mpl->token == T_LEFT) + { /* it is the left parenthesis; parse expression that begins + with this parenthesis (the flag is set in order to allow + recognizing slices; see the routine expression_list) */ + mpl->flag_x = 1; + code = expression_9(mpl); + if (code->op != O_SLICE) + { /* this is either <basic expression> or the very first + <member expression> in <literal set> */ + goto expr; + } + /* this is a slice; besides the corresponding domain block + is already created by expression_list() */ + block = code->arg.slice; + code = NULL; /* <basic expression> is not parsed yet */ + /* the keyword 'in' following the slice is already checked + by expression_list() */ + xassert(mpl->token == T_IN); + get_token(mpl /* in */); + /* <basic expression> that follows the keyword 'in' will be + parsed below */ + } +expr: /* parse expression that follows either the keyword 'in' (in + which case it can be <basic expression) or the left brace + (in which case it can be <basic expression> as well as the + very first <member expression> in <literal set>); note that + this expression can be already parsed above */ + if (code == NULL) code = expression_9(mpl); + /* check the type of the expression just parsed */ + if (code->type != A_ELEMSET) + { /* it is not <basic expression> and therefore it can only + be the very first <member expression> in <literal set>; + however, then there must be no dummy index neither slice + between the left brace and this expression */ + if (block != NULL) + error(mpl, "domain expression has invalid type"); + /* parse the rest part of <literal set> and make this set + be <basic expression>, i.e. the construction {a, b, c} + is parsed as it were written as {A}, where A = {a, b, c} + is a temporary elemental set */ + code = literal_set(mpl, code); + } + /* now pseudo-code for <basic set> has been built */ + xassert(code != NULL); + xassert(code->type == A_ELEMSET); + xassert(code->dim > 0); + /* if domain block for the current <indexing element> is still + not created, create it for fake slice of the same dimension + as <basic set> */ + if (block == NULL) + { int j; + block = create_block(mpl); + for (j = 1; j <= code->dim; j++) + append_slot(mpl, block, NULL, NULL); + } + /* number of indexing positions in <indexing element> must be + the same as dimension of n-tuples in basic set */ + { int dim = 0; + for (slot = block->list; slot != NULL; slot = slot->next) + dim++; + if (dim != code->dim) + error(mpl,"%d %s specified for set of dimension %d", + dim, dim == 1 ? "index" : "indices", code->dim); + } + /* store pseudo-code for <basic set> in the domain block */ + xassert(block->code == NULL); + block->code = code; + /* and append the domain block to the domain */ + append_block(mpl, domain, block); + /* the current <indexing element> has been completely parsed; + include all its dummy indices into the symbolic name table + to make them available for referencing from expressions; + implicit declarations of dummy indices remain valid while + the corresponding domain scope is valid */ + for (slot = block->list; slot != NULL; slot = slot->next) + if (slot->name != NULL) + { AVLNODE *node; + xassert(avl_find_node(mpl->tree, slot->name) == NULL); + node = avl_insert_node(mpl->tree, slot->name); + avl_set_node_type(node, A_INDEX); + avl_set_node_link(node, (void *)slot); + } + /* check a token that follows <indexing element> */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_COLON || mpl->token == T_RBRACE) + break; + else + error(mpl, "syntax error in indexing expression"); + } + /* parse <logical expression> that follows the colon */ + if (mpl->token == T_COLON) + { get_token(mpl /* : */); + code = expression_13(mpl); + /* convert the expression to logical type, if necessary */ + if (code->type == A_SYMBOLIC) + code = make_unary(mpl, O_CVTNUM, code, A_NUMERIC, 0); + if (code->type == A_NUMERIC) + code = make_unary(mpl, O_CVTLOG, code, A_LOGICAL, 0); + /* now the expression must be of logical type */ + if (code->type != A_LOGICAL) + error(mpl, "expression following colon has invalid type"); + xassert(code->dim == 0); + domain->code = code; + /* the right brace must follow the logical expression */ + if (mpl->token != T_RBRACE) + error(mpl, "syntax error in indexing expression"); + } + get_token(mpl /* } */); + return domain; +} + +/*---------------------------------------------------------------------- +-- close_scope - close scope of indexing expression. +-- +-- The routine closes the scope of indexing expression specified by its +-- domain and thereby makes all dummy indices introduced in the indexing +-- expression no longer available for referencing. */ + +void close_scope(MPL *mpl, DOMAIN *domain) +{ DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + AVLNODE *node; + xassert(domain != NULL); + /* remove all dummy indices from the symbolic names table */ + for (block = domain->list; block != NULL; block = block->next) + { for (slot = block->list; slot != NULL; slot = slot->next) + { if (slot->name != NULL) + { node = avl_find_node(mpl->tree, slot->name); + xassert(node != NULL); + xassert(avl_get_node_type(node) == A_INDEX); + avl_delete_node(mpl->tree, node); + } + } + } + return; +} + +/*---------------------------------------------------------------------- +-- iterated_expression - parse iterated expression. +-- +-- This routine parses primary expression using the syntax: +-- +-- <primary expression> ::= <iterated expression> +-- <iterated expression> ::= sum <indexing expression> <expression 3> +-- <iterated expression> ::= prod <indexing expression> <expression 3> +-- <iterated expression> ::= min <indexing expression> <expression 3> +-- <iterated expression> ::= max <indexing expression> <expression 3> +-- <iterated expression> ::= exists <indexing expression> +-- <expression 12> +-- <iterated expression> ::= forall <indexing expression> +-- <expression 12> +-- <iterated expression> ::= setof <indexing expression> <expression 5> +-- +-- Note that parsing "integrand" depends on the iterated operator. */ + +#if 1 /* 07/IX-2008 */ +static void link_up(CODE *code) +{ /* if we have something like sum{(i+1,j,k-1) in E} x[i,j,k], + where i and k are dummy indices defined out of the iterated + expression, we should link up pseudo-code for computing i+1 + and k-1 to pseudo-code for computing the iterated expression; + this is needed to invalidate current value of the iterated + expression once i or k have been changed */ + DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + for (block = code->arg.loop.domain->list; block != NULL; + block = block->next) + { for (slot = block->list; slot != NULL; slot = slot->next) + { if (slot->code != NULL) + { xassert(slot->code->up == NULL); + slot->code->up = code; + } + } + } + return; +} +#endif + +CODE *iterated_expression(MPL *mpl) +{ CODE *code; + OPERANDS arg; + int op; + char opstr[8]; + /* determine operation code */ + xassert(mpl->token == T_NAME); + if (strcmp(mpl->image, "sum") == 0) + op = O_SUM; + else if (strcmp(mpl->image, "prod") == 0) + op = O_PROD; + else if (strcmp(mpl->image, "min") == 0) + op = O_MINIMUM; + else if (strcmp(mpl->image, "max") == 0) + op = O_MAXIMUM; + else if (strcmp(mpl->image, "forall") == 0) + op = O_FORALL; + else if (strcmp(mpl->image, "exists") == 0) + op = O_EXISTS; + else if (strcmp(mpl->image, "setof") == 0) + op = O_SETOF; + else + error(mpl, "operator %s unknown", mpl->image); + strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + get_token(mpl /* <symbolic name> */); + /* check the left brace that follows the operator name */ + xassert(mpl->token == T_LBRACE); + /* parse indexing expression that controls iterating */ + arg.loop.domain = indexing_expression(mpl); + /* parse "integrand" expression and generate pseudo-code */ + switch (op) + { case O_SUM: + case O_PROD: + case O_MINIMUM: + case O_MAXIMUM: + arg.loop.x = expression_3(mpl); + /* convert the integrand to numeric type, if necessary */ + if (arg.loop.x->type == A_SYMBOLIC) + arg.loop.x = make_unary(mpl, O_CVTNUM, arg.loop.x, + A_NUMERIC, 0); + /* now the integrand must be of numeric type or linear form + (the latter is only allowed for the sum operator) */ + if (!(arg.loop.x->type == A_NUMERIC || + op == O_SUM && arg.loop.x->type == A_FORMULA)) +err: error(mpl, "integrand following %s{...} has invalid type" + , opstr); + xassert(arg.loop.x->dim == 0); + /* generate pseudo-code */ + code = make_code(mpl, op, &arg, arg.loop.x->type, 0); + break; + case O_FORALL: + case O_EXISTS: + arg.loop.x = expression_12(mpl); + /* convert the integrand to logical type, if necessary */ + if (arg.loop.x->type == A_SYMBOLIC) + arg.loop.x = make_unary(mpl, O_CVTNUM, arg.loop.x, + A_NUMERIC, 0); + if (arg.loop.x->type == A_NUMERIC) + arg.loop.x = make_unary(mpl, O_CVTLOG, arg.loop.x, + A_LOGICAL, 0); + /* now the integrand must be of logical type */ + if (arg.loop.x->type != A_LOGICAL) goto err; + xassert(arg.loop.x->dim == 0); + /* generate pseudo-code */ + code = make_code(mpl, op, &arg, A_LOGICAL, 0); + break; + case O_SETOF: + arg.loop.x = expression_5(mpl); + /* convert the integrand to 1-tuple, if necessary */ + if (arg.loop.x->type == A_NUMERIC) + arg.loop.x = make_unary(mpl, O_CVTSYM, arg.loop.x, + A_SYMBOLIC, 0); + if (arg.loop.x->type == A_SYMBOLIC) + arg.loop.x = make_unary(mpl, O_CVTTUP, arg.loop.x, + A_TUPLE, 1); + /* now the integrand must be n-tuple */ + if (arg.loop.x->type != A_TUPLE) goto err; + xassert(arg.loop.x->dim > 0); + /* generate pseudo-code */ + code = make_code(mpl, op, &arg, A_ELEMSET, arg.loop.x->dim); + break; + default: + xassert(op != op); + } + /* close the scope of the indexing expression */ + close_scope(mpl, arg.loop.domain); +#if 1 /* 07/IX-2008 */ + link_up(code); +#endif + return code; +} + +/*---------------------------------------------------------------------- +-- domain_arity - determine arity of domain. +-- +-- This routine returns arity of specified domain, which is number of +-- its free dummy indices. */ + +int domain_arity(MPL *mpl, DOMAIN *domain) +{ DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + int arity; + xassert(mpl == mpl); + arity = 0; + for (block = domain->list; block != NULL; block = block->next) + for (slot = block->list; slot != NULL; slot = slot->next) + if (slot->code == NULL) arity++; + return arity; +} + +/*---------------------------------------------------------------------- +-- set_expression - parse set expression. +-- +-- This routine parses primary expression using the syntax: +-- +-- <primary expression> ::= { } +-- <primary expression> ::= <indexing expression> */ + +CODE *set_expression(MPL *mpl) +{ CODE *code; + OPERANDS arg; + xassert(mpl->token == T_LBRACE); + get_token(mpl /* { */); + /* check a token that follows the left brace */ + if (mpl->token == T_RBRACE) + { /* it is the right brace, so the resultant is an empty set of + dimension 1 */ + arg.list = NULL; + /* generate pseudo-code to build the resultant set */ + code = make_code(mpl, O_MAKE, &arg, A_ELEMSET, 1); + get_token(mpl /* } */); + } + else + { /* the next token begins an indexing expression */ + unget_token(mpl); + arg.loop.domain = indexing_expression(mpl); + arg.loop.x = NULL; /* integrand is not used */ + /* close the scope of the indexing expression */ + close_scope(mpl, arg.loop.domain); + /* generate pseudo-code to build the resultant set */ + code = make_code(mpl, O_BUILD, &arg, A_ELEMSET, + domain_arity(mpl, arg.loop.domain)); +#if 1 /* 07/IX-2008 */ + link_up(code); +#endif + } + return code; +} + +/*---------------------------------------------------------------------- +-- branched_expression - parse conditional expression. +-- +-- This routine parses primary expression using the syntax: +-- +-- <primary expression> ::= <branched expression> +-- <branched expression> ::= if <logical expression> then <expression 9> +-- <branched expression> ::= if <logical expression> then <expression 9> +-- else <expression 9> +-- <logical expression> ::= <expression 13> */ + +CODE *branched_expression(MPL *mpl) +{ CODE *code, *x, *y, *z; + xassert(mpl->token == T_IF); + get_token(mpl /* if */); + /* parse <logical expression> that follows 'if' */ + x = expression_13(mpl); + /* convert the expression to logical type, if necessary */ + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); + /* now the expression must be of logical type */ + if (x->type != A_LOGICAL) + error(mpl, "expression following if has invalid type"); + xassert(x->dim == 0); + /* the keyword 'then' must follow the logical expression */ + if (mpl->token != T_THEN) + error(mpl, "keyword then missing where expected"); + get_token(mpl /* then */); + /* parse <expression> that follows 'then' and check its type */ + y = expression_9(mpl); + if (!(y->type == A_NUMERIC || y->type == A_SYMBOLIC || + y->type == A_ELEMSET || y->type == A_FORMULA)) + error(mpl, "expression following then has invalid type"); + /* if the expression that follows the keyword 'then' is elemental + set, the keyword 'else' cannot be omitted; otherwise else-part + is optional */ + if (mpl->token != T_ELSE) + { if (y->type == A_ELEMSET) + error(mpl, "keyword else missing where expected"); + z = NULL; + goto skip; + } + get_token(mpl /* else */); + /* parse <expression> that follow 'else' and check its type */ + z = expression_9(mpl); + if (!(z->type == A_NUMERIC || z->type == A_SYMBOLIC || + z->type == A_ELEMSET || z->type == A_FORMULA)) + error(mpl, "expression following else has invalid type"); + /* convert to identical types, if necessary */ + if (y->type == A_FORMULA || z->type == A_FORMULA) + { if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTLFM, y, A_FORMULA, 0); + if (z->type == A_SYMBOLIC) + z = make_unary(mpl, O_CVTNUM, z, A_NUMERIC, 0); + if (z->type == A_NUMERIC) + z = make_unary(mpl, O_CVTLFM, z, A_FORMULA, 0); + } + if (y->type == A_SYMBOLIC || z->type == A_SYMBOLIC) + { if (y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTSYM, y, A_SYMBOLIC, 0); + if (z->type == A_NUMERIC) + z = make_unary(mpl, O_CVTSYM, z, A_SYMBOLIC, 0); + } + /* now both expressions must have identical types */ + if (y->type != z->type) + error(mpl, "expressions following then and else have incompati" + "ble types"); + /* and identical dimensions */ + if (y->dim != z->dim) + error(mpl, "expressions following then and else have different" + " dimensions %d and %d, respectively", y->dim, z->dim); +skip: /* generate pseudo-code to perform branching */ + code = make_ternary(mpl, O_FORK, x, y, z, y->type, y->dim); + return code; +} + +/*---------------------------------------------------------------------- +-- primary_expression - parse primary expression. +-- +-- This routine parses primary expression using the syntax: +-- +-- <primary expression> ::= <numeric literal> +-- <primary expression> ::= Infinity +-- <primary expression> ::= <string literal> +-- <primary expression> ::= <dummy index> +-- <primary expression> ::= <set name> +-- <primary expression> ::= <set name> [ <subscript list> ] +-- <primary expression> ::= <parameter name> +-- <primary expression> ::= <parameter name> [ <subscript list> ] +-- <primary expression> ::= <variable name> +-- <primary expression> ::= <variable name> [ <subscript list> ] +-- <primary expression> ::= <built-in function> ( <argument list> ) +-- <primary expression> ::= ( <expression list> ) +-- <primary expression> ::= <iterated expression> +-- <primary expression> ::= { } +-- <primary expression> ::= <indexing expression> +-- <primary expression> ::= <branched expression> +-- +-- For complete list of syntactic rules for <primary expression> see +-- comments to the corresponding parsing routines. */ + +CODE *primary_expression(MPL *mpl) +{ CODE *code; + if (mpl->token == T_NUMBER) + { /* parse numeric literal */ + code = numeric_literal(mpl); + } +#if 1 /* 21/VII-2006 */ + else if (mpl->token == T_INFINITY) + { /* parse "infinity" */ + OPERANDS arg; + arg.num = DBL_MAX; + code = make_code(mpl, O_NUMBER, &arg, A_NUMERIC, 0); + get_token(mpl /* Infinity */); + } +#endif + else if (mpl->token == T_STRING) + { /* parse string literal */ + code = string_literal(mpl); + } + else if (mpl->token == T_NAME) + { int next_token; + get_token(mpl /* <symbolic name> */); + next_token = mpl->token; + unget_token(mpl); + /* check a token that follows <symbolic name> */ + switch (next_token) + { case T_LBRACKET: + /* parse reference to subscripted object */ + code = object_reference(mpl); + break; + case T_LEFT: + /* parse reference to built-in function */ + code = function_reference(mpl); + break; + case T_LBRACE: + /* parse iterated expression */ + code = iterated_expression(mpl); + break; + default: + /* parse reference to unsubscripted object */ + code = object_reference(mpl); + break; + } + } + else if (mpl->token == T_LEFT) + { /* parse parenthesized expression */ + code = expression_list(mpl); + } + else if (mpl->token == T_LBRACE) + { /* parse set expression */ + code = set_expression(mpl); + } + else if (mpl->token == T_IF) + { /* parse conditional expression */ + code = branched_expression(mpl); + } + else if (is_reserved(mpl)) + { /* other reserved keywords cannot be used here */ + error(mpl, "invalid use of reserved keyword %s", mpl->image); + } + else + error(mpl, "syntax error in expression"); + return code; +} + +/*---------------------------------------------------------------------- +-- error_preceding - raise error if preceding operand has wrong type. +-- +-- This routine is called to raise error if operand that precedes some +-- infix operator has invalid type. */ + +void error_preceding(MPL *mpl, char *opstr) +{ error(mpl, "operand preceding %s has invalid type", opstr); + /* no return */ +} + +/*---------------------------------------------------------------------- +-- error_following - raise error if following operand has wrong type. +-- +-- This routine is called to raise error if operand that follows some +-- infix operator has invalid type. */ + +void error_following(MPL *mpl, char *opstr) +{ error(mpl, "operand following %s has invalid type", opstr); + /* no return */ +} + +/*---------------------------------------------------------------------- +-- error_dimension - raise error if operands have different dimension. +-- +-- This routine is called to raise error if two operands of some infix +-- operator have different dimension. */ + +void error_dimension(MPL *mpl, char *opstr, int dim1, int dim2) +{ error(mpl, "operands preceding and following %s have different di" + "mensions %d and %d, respectively", opstr, dim1, dim2); + /* no return */ +} + +/*---------------------------------------------------------------------- +-- expression_0 - parse expression of level 0. +-- +-- This routine parses expression of level 0 using the syntax: +-- +-- <expression 0> ::= <primary expression> */ + +CODE *expression_0(MPL *mpl) +{ CODE *code; + code = primary_expression(mpl); + return code; +} + +/*---------------------------------------------------------------------- +-- expression_1 - parse expression of level 1. +-- +-- This routine parses expression of level 1 using the syntax: +-- +-- <expression 1> ::= <expression 0> +-- <expression 1> ::= <expression 0> <power> <expression 1> +-- <expression 1> ::= <expression 0> <power> <expression 2> +-- <power> ::= ^ | ** */ + +CODE *expression_1(MPL *mpl) +{ CODE *x, *y; + char opstr[8]; + x = expression_0(mpl); + if (mpl->token == T_POWER) + { strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, opstr); + get_token(mpl /* ^ | ** */); + if (mpl->token == T_PLUS || mpl->token == T_MINUS) + y = expression_2(mpl); + else + y = expression_1(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, opstr); + x = make_binary(mpl, O_POWER, x, y, A_NUMERIC, 0); + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_2 - parse expression of level 2. +-- +-- This routine parses expression of level 2 using the syntax: +-- +-- <expression 2> ::= <expression 1> +-- <expression 2> ::= + <expression 1> +-- <expression 2> ::= - <expression 1> */ + +CODE *expression_2(MPL *mpl) +{ CODE *x; + if (mpl->token == T_PLUS) + { get_token(mpl /* + */); + x = expression_1(mpl); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_following(mpl, "+"); + x = make_unary(mpl, O_PLUS, x, x->type, 0); + } + else if (mpl->token == T_MINUS) + { get_token(mpl /* - */); + x = expression_1(mpl); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_following(mpl, "-"); + x = make_unary(mpl, O_MINUS, x, x->type, 0); + } + else + x = expression_1(mpl); + return x; +} + +/*---------------------------------------------------------------------- +-- expression_3 - parse expression of level 3. +-- +-- This routine parses expression of level 3 using the syntax: +-- +-- <expression 3> ::= <expression 2> +-- <expression 3> ::= <expression 3> * <expression 2> +-- <expression 3> ::= <expression 3> / <expression 2> +-- <expression 3> ::= <expression 3> div <expression 2> +-- <expression 3> ::= <expression 3> mod <expression 2> */ + +CODE *expression_3(MPL *mpl) +{ CODE *x, *y; + x = expression_2(mpl); + for (;;) + { if (mpl->token == T_ASTERISK) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_preceding(mpl, "*"); + get_token(mpl /* * */); + y = expression_2(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (!(y->type == A_NUMERIC || y->type == A_FORMULA)) + error_following(mpl, "*"); + if (x->type == A_FORMULA && y->type == A_FORMULA) + error(mpl, "multiplication of linear forms not allowed"); + if (x->type == A_NUMERIC && y->type == A_NUMERIC) + x = make_binary(mpl, O_MUL, x, y, A_NUMERIC, 0); + else + x = make_binary(mpl, O_MUL, x, y, A_FORMULA, 0); + } + else if (mpl->token == T_SLASH) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_preceding(mpl, "/"); + get_token(mpl /* / */); + y = expression_2(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, "/"); + if (x->type == A_NUMERIC) + x = make_binary(mpl, O_DIV, x, y, A_NUMERIC, 0); + else + x = make_binary(mpl, O_DIV, x, y, A_FORMULA, 0); + } + else if (mpl->token == T_DIV) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, "div"); + get_token(mpl /* div */); + y = expression_2(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, "div"); + x = make_binary(mpl, O_IDIV, x, y, A_NUMERIC, 0); + } + else if (mpl->token == T_MOD) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, "mod"); + get_token(mpl /* mod */); + y = expression_2(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, "mod"); + x = make_binary(mpl, O_MOD, x, y, A_NUMERIC, 0); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_4 - parse expression of level 4. +-- +-- This routine parses expression of level 4 using the syntax: +-- +-- <expression 4> ::= <expression 3> +-- <expression 4> ::= <expression 4> + <expression 3> +-- <expression 4> ::= <expression 4> - <expression 3> +-- <expression 4> ::= <expression 4> less <expression 3> */ + +CODE *expression_4(MPL *mpl) +{ CODE *x, *y; + x = expression_3(mpl); + for (;;) + { if (mpl->token == T_PLUS) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_preceding(mpl, "+"); + get_token(mpl /* + */); + y = expression_3(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (!(y->type == A_NUMERIC || y->type == A_FORMULA)) + error_following(mpl, "+"); + if (x->type == A_NUMERIC && y->type == A_FORMULA) + x = make_unary(mpl, O_CVTLFM, x, A_FORMULA, 0); + if (x->type == A_FORMULA && y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTLFM, y, A_FORMULA, 0); + x = make_binary(mpl, O_ADD, x, y, x->type, 0); + } + else if (mpl->token == T_MINUS) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_preceding(mpl, "-"); + get_token(mpl /* - */); + y = expression_3(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (!(y->type == A_NUMERIC || y->type == A_FORMULA)) + error_following(mpl, "-"); + if (x->type == A_NUMERIC && y->type == A_FORMULA) + x = make_unary(mpl, O_CVTLFM, x, A_FORMULA, 0); + if (x->type == A_FORMULA && y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTLFM, y, A_FORMULA, 0); + x = make_binary(mpl, O_SUB, x, y, x->type, 0); + } + else if (mpl->token == T_LESS) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, "less"); + get_token(mpl /* less */); + y = expression_3(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, "less"); + x = make_binary(mpl, O_LESS, x, y, A_NUMERIC, 0); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_5 - parse expression of level 5. +-- +-- This routine parses expression of level 5 using the syntax: +-- +-- <expression 5> ::= <expression 4> +-- <expression 5> ::= <expression 5> & <expression 4> */ + +CODE *expression_5(MPL *mpl) +{ CODE *x, *y; + x = expression_4(mpl); + for (;;) + { if (mpl->token == T_CONCAT) + { if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); + if (x->type != A_SYMBOLIC) + error_preceding(mpl, "&"); + get_token(mpl /* & */); + y = expression_4(mpl); + if (y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTSYM, y, A_SYMBOLIC, 0); + if (y->type != A_SYMBOLIC) + error_following(mpl, "&"); + x = make_binary(mpl, O_CONCAT, x, y, A_SYMBOLIC, 0); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_6 - parse expression of level 6. +-- +-- This routine parses expression of level 6 using the syntax: +-- +-- <expression 6> ::= <expression 5> +-- <expression 6> ::= <expression 5> .. <expression 5> +-- <expression 6> ::= <expression 5> .. <expression 5> by +-- <expression 5> */ + +CODE *expression_6(MPL *mpl) +{ CODE *x, *y, *z; + x = expression_5(mpl); + if (mpl->token == T_DOTS) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, ".."); + get_token(mpl /* .. */); + y = expression_5(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, ".."); + if (mpl->token == T_BY) + { get_token(mpl /* by */); + z = expression_5(mpl); + if (z->type == A_SYMBOLIC) + z = make_unary(mpl, O_CVTNUM, z, A_NUMERIC, 0); + if (z->type != A_NUMERIC) + error_following(mpl, "by"); + } + else + z = NULL; + x = make_ternary(mpl, O_DOTS, x, y, z, A_ELEMSET, 1); + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_7 - parse expression of level 7. +-- +-- This routine parses expression of level 7 using the syntax: +-- +-- <expression 7> ::= <expression 6> +-- <expression 7> ::= <expression 7> cross <expression 6> */ + +CODE *expression_7(MPL *mpl) +{ CODE *x, *y; + x = expression_6(mpl); + for (;;) + { if (mpl->token == T_CROSS) + { if (x->type != A_ELEMSET) + error_preceding(mpl, "cross"); + get_token(mpl /* cross */); + y = expression_6(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, "cross"); + x = make_binary(mpl, O_CROSS, x, y, A_ELEMSET, + x->dim + y->dim); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_8 - parse expression of level 8. +-- +-- This routine parses expression of level 8 using the syntax: +-- +-- <expression 8> ::= <expression 7> +-- <expression 8> ::= <expression 8> inter <expression 7> */ + +CODE *expression_8(MPL *mpl) +{ CODE *x, *y; + x = expression_7(mpl); + for (;;) + { if (mpl->token == T_INTER) + { if (x->type != A_ELEMSET) + error_preceding(mpl, "inter"); + get_token(mpl /* inter */); + y = expression_7(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, "inter"); + if (x->dim != y->dim) + error_dimension(mpl, "inter", x->dim, y->dim); + x = make_binary(mpl, O_INTER, x, y, A_ELEMSET, x->dim); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_9 - parse expression of level 9. +-- +-- This routine parses expression of level 9 using the syntax: +-- +-- <expression 9> ::= <expression 8> +-- <expression 9> ::= <expression 9> union <expression 8> +-- <expression 9> ::= <expression 9> diff <expression 8> +-- <expression 9> ::= <expression 9> symdiff <expression 8> */ + +CODE *expression_9(MPL *mpl) +{ CODE *x, *y; + x = expression_8(mpl); + for (;;) + { if (mpl->token == T_UNION) + { if (x->type != A_ELEMSET) + error_preceding(mpl, "union"); + get_token(mpl /* union */); + y = expression_8(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, "union"); + if (x->dim != y->dim) + error_dimension(mpl, "union", x->dim, y->dim); + x = make_binary(mpl, O_UNION, x, y, A_ELEMSET, x->dim); + } + else if (mpl->token == T_DIFF) + { if (x->type != A_ELEMSET) + error_preceding(mpl, "diff"); + get_token(mpl /* diff */); + y = expression_8(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, "diff"); + if (x->dim != y->dim) + error_dimension(mpl, "diff", x->dim, y->dim); + x = make_binary(mpl, O_DIFF, x, y, A_ELEMSET, x->dim); + } + else if (mpl->token == T_SYMDIFF) + { if (x->type != A_ELEMSET) + error_preceding(mpl, "symdiff"); + get_token(mpl /* symdiff */); + y = expression_8(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, "symdiff"); + if (x->dim != y->dim) + error_dimension(mpl, "symdiff", x->dim, y->dim); + x = make_binary(mpl, O_SYMDIFF, x, y, A_ELEMSET, x->dim); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_10 - parse expression of level 10. +-- +-- This routine parses expression of level 10 using the syntax: +-- +-- <expression 10> ::= <expression 9> +-- <expression 10> ::= <expression 9> <rho> <expression 9> +-- <rho> ::= < | <= | = | == | >= | > | <> | != | in | not in | ! in | +-- within | not within | ! within */ + +CODE *expression_10(MPL *mpl) +{ CODE *x, *y; + int op = -1; + char opstr[16]; + x = expression_9(mpl); + strcpy(opstr, ""); + switch (mpl->token) + { case T_LT: + op = O_LT; break; + case T_LE: + op = O_LE; break; + case T_EQ: + op = O_EQ; break; + case T_GE: + op = O_GE; break; + case T_GT: + op = O_GT; break; + case T_NE: + op = O_NE; break; + case T_IN: + op = O_IN; break; + case T_WITHIN: + op = O_WITHIN; break; + case T_NOT: + strcpy(opstr, mpl->image); + get_token(mpl /* not | ! */); + if (mpl->token == T_IN) + op = O_NOTIN; + else if (mpl->token == T_WITHIN) + op = O_NOTWITHIN; + else + error(mpl, "invalid use of %s", opstr); + strcat(opstr, " "); + break; + default: + goto done; + } + strcat(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + switch (op) + { case O_EQ: + case O_NE: +#if 1 /* 02/VIII-2008 */ + case O_LT: + case O_LE: + case O_GT: + case O_GE: +#endif + if (!(x->type == A_NUMERIC || x->type == A_SYMBOLIC)) + error_preceding(mpl, opstr); + get_token(mpl /* <rho> */); + y = expression_9(mpl); + if (!(y->type == A_NUMERIC || y->type == A_SYMBOLIC)) + error_following(mpl, opstr); + if (x->type == A_NUMERIC && y->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); + if (x->type == A_SYMBOLIC && y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTSYM, y, A_SYMBOLIC, 0); + x = make_binary(mpl, op, x, y, A_LOGICAL, 0); + break; +#if 0 /* 02/VIII-2008 */ + case O_LT: + case O_LE: + case O_GT: + case O_GE: + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, opstr); + get_token(mpl /* <rho> */); + y = expression_9(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, opstr); + x = make_binary(mpl, op, x, y, A_LOGICAL, 0); + break; +#endif + case O_IN: + case O_NOTIN: + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTTUP, x, A_TUPLE, 1); + if (x->type != A_TUPLE) + error_preceding(mpl, opstr); + get_token(mpl /* <rho> */); + y = expression_9(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, opstr); + if (x->dim != y->dim) + error_dimension(mpl, opstr, x->dim, y->dim); + x = make_binary(mpl, op, x, y, A_LOGICAL, 0); + break; + case O_WITHIN: + case O_NOTWITHIN: + if (x->type != A_ELEMSET) + error_preceding(mpl, opstr); + get_token(mpl /* <rho> */); + y = expression_9(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, opstr); + if (x->dim != y->dim) + error_dimension(mpl, opstr, x->dim, y->dim); + x = make_binary(mpl, op, x, y, A_LOGICAL, 0); + break; + default: + xassert(op != op); + } +done: return x; +} + +/*---------------------------------------------------------------------- +-- expression_11 - parse expression of level 11. +-- +-- This routine parses expression of level 11 using the syntax: +-- +-- <expression 11> ::= <expression 10> +-- <expression 11> ::= not <expression 10> +-- <expression 11> ::= ! <expression 10> */ + +CODE *expression_11(MPL *mpl) +{ CODE *x; + char opstr[8]; + if (mpl->token == T_NOT) + { strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + get_token(mpl /* not | ! */); + x = expression_10(mpl); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); + if (x->type != A_LOGICAL) + error_following(mpl, opstr); + x = make_unary(mpl, O_NOT, x, A_LOGICAL, 0); + } + else + x = expression_10(mpl); + return x; +} + +/*---------------------------------------------------------------------- +-- expression_12 - parse expression of level 12. +-- +-- This routine parses expression of level 12 using the syntax: +-- +-- <expression 12> ::= <expression 11> +-- <expression 12> ::= <expression 12> and <expression 11> +-- <expression 12> ::= <expression 12> && <expression 11> */ + +CODE *expression_12(MPL *mpl) +{ CODE *x, *y; + char opstr[8]; + x = expression_11(mpl); + for (;;) + { if (mpl->token == T_AND) + { strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); + if (x->type != A_LOGICAL) + error_preceding(mpl, opstr); + get_token(mpl /* and | && */); + y = expression_11(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTLOG, y, A_LOGICAL, 0); + if (y->type != A_LOGICAL) + error_following(mpl, opstr); + x = make_binary(mpl, O_AND, x, y, A_LOGICAL, 0); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_13 - parse expression of level 13. +-- +-- This routine parses expression of level 13 using the syntax: +-- +-- <expression 13> ::= <expression 12> +-- <expression 13> ::= <expression 13> or <expression 12> +-- <expression 13> ::= <expression 13> || <expression 12> */ + +CODE *expression_13(MPL *mpl) +{ CODE *x, *y; + char opstr[8]; + x = expression_12(mpl); + for (;;) + { if (mpl->token == T_OR) + { strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); + if (x->type != A_LOGICAL) + error_preceding(mpl, opstr); + get_token(mpl /* or | || */); + y = expression_12(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTLOG, y, A_LOGICAL, 0); + if (y->type != A_LOGICAL) + error_following(mpl, opstr); + x = make_binary(mpl, O_OR, x, y, A_LOGICAL, 0); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- set_statement - parse set statement. +-- +-- This routine parses set statement using the syntax: +-- +-- <set statement> ::= set <symbolic name> <alias> <domain> +-- <attributes> ; +-- <alias> ::= <empty> +-- <alias> ::= <string literal> +-- <domain> ::= <empty> +-- <domain> ::= <indexing expression> +-- <attributes> ::= <empty> +-- <attributes> ::= <attributes> , dimen <numeric literal> +-- <attributes> ::= <attributes> , within <expression 9> +-- <attributes> ::= <attributes> , := <expression 9> +-- <attributes> ::= <attributes> , default <expression 9> +-- +-- Commae in <attributes> are optional and may be omitted anywhere. */ + +SET *set_statement(MPL *mpl) +{ SET *set; + int dimen_used = 0; + xassert(is_keyword(mpl, "set")); + get_token(mpl /* set */); + /* symbolic name must follow the keyword 'set' */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create model set */ + set = alloc(SET); + set->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(set->name, mpl->image); + set->alias = NULL; + set->dim = 0; + set->domain = NULL; + set->dimen = 0; + set->within = NULL; + set->assign = NULL; + set->option = NULL; + set->gadget = NULL; + set->data = 0; + set->array = NULL; + get_token(mpl /* <symbolic name> */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { set->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(set->alias, mpl->image); + get_token(mpl /* <string literal> */); + } + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { set->domain = indexing_expression(mpl); + set->dim = domain_arity(mpl, set->domain); + } + /* include the set name in the symbolic names table */ + { AVLNODE *node; + node = avl_insert_node(mpl->tree, set->name); + avl_set_node_type(node, A_SET); + avl_set_node_link(node, (void *)set); + } + /* parse the list of optional attributes */ + for (;;) + { if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_SEMICOLON) + break; + if (is_keyword(mpl, "dimen")) + { /* dimension of set members */ + int dimen; + get_token(mpl /* dimen */); + if (!(mpl->token == T_NUMBER && + 1.0 <= mpl->value && mpl->value <= 20.0 && + floor(mpl->value) == mpl->value)) + error(mpl, "dimension must be integer between 1 and 20"); + dimen = (int)(mpl->value + 0.5); + if (dimen_used) + error(mpl, "at most one dimension attribute allowed"); + if (set->dimen > 0) + error(mpl, "dimension %d conflicts with dimension %d alr" + "eady determined", dimen, set->dimen); + set->dimen = dimen; + dimen_used = 1; + get_token(mpl /* <numeric literal> */); + } + else if (mpl->token == T_WITHIN || mpl->token == T_IN) + { /* restricting superset */ + WITHIN *within, *temp; + if (mpl->token == T_IN && !mpl->as_within) + { warning(mpl, "keyword in understood as within"); + mpl->as_within = 1; + } + get_token(mpl /* within */); + /* create new restricting superset list entry and append it + to the within-list */ + within = alloc(WITHIN); + within->code = NULL; + within->next = NULL; + if (set->within == NULL) + set->within = within; + else + { for (temp = set->within; temp->next != NULL; temp = + temp->next); + temp->next = within; + } + /* parse an expression that follows 'within' */ + within->code = expression_9(mpl); + if (within->code->type != A_ELEMSET) + error(mpl, "expression following within has invalid type" + ); + xassert(within->code->dim > 0); + /* check/set dimension of set members */ + if (set->dimen == 0) set->dimen = within->code->dim; + if (set->dimen != within->code->dim) + error(mpl, "set expression following within must have di" + "mension %d rather than %d", + set->dimen, within->code->dim); + } + else if (mpl->token == T_ASSIGN) + { /* assignment expression */ + if (!(set->assign == NULL && set->option == NULL && + set->gadget == NULL)) +err: error(mpl, "at most one := or default/data allowed"); + get_token(mpl /* := */); + /* parse an expression that follows ':=' */ + set->assign = expression_9(mpl); + if (set->assign->type != A_ELEMSET) + error(mpl, "expression following := has invalid type"); + xassert(set->assign->dim > 0); + /* check/set dimension of set members */ + if (set->dimen == 0) set->dimen = set->assign->dim; + if (set->dimen != set->assign->dim) + error(mpl, "set expression following := must have dimens" + "ion %d rather than %d", + set->dimen, set->assign->dim); + } + else if (is_keyword(mpl, "default")) + { /* expression for default value */ + if (!(set->assign == NULL && set->option == NULL)) goto err; + get_token(mpl /* := */); + /* parse an expression that follows 'default' */ + set->option = expression_9(mpl); + if (set->option->type != A_ELEMSET) + error(mpl, "expression following default has invalid typ" + "e"); + xassert(set->option->dim > 0); + /* check/set dimension of set members */ + if (set->dimen == 0) set->dimen = set->option->dim; + if (set->dimen != set->option->dim) + error(mpl, "set expression following default must have d" + "imension %d rather than %d", + set->dimen, set->option->dim); + } +#if 1 /* 12/XII-2008 */ + else if (is_keyword(mpl, "data")) + { /* gadget to initialize the set by data from plain set */ + GADGET *gadget; + AVLNODE *node; + int i, k, fff[20]; + if (!(set->assign == NULL && set->gadget == NULL)) goto err; + get_token(mpl /* data */); + set->gadget = gadget = alloc(GADGET); + /* set name must follow the keyword 'data' */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", + mpl->image); + else + error(mpl, "set name missing where expected"); + /* find the set in the symbolic name table */ + node = avl_find_node(mpl->tree, mpl->image); + if (node == NULL) + error(mpl, "%s not defined", mpl->image); + if (avl_get_node_type(node) != A_SET) +err1: error(mpl, "%s not a plain set", mpl->image); + gadget->set = avl_get_node_link(node); + if (gadget->set->dim != 0) goto err1; + if (gadget->set == set) + error(mpl, "set cannot be initialized by itself"); + /* check and set dimensions */ + if (set->dim >= gadget->set->dimen) +err2: error(mpl, "dimension of %s too small", mpl->image); + if (set->dimen == 0) + set->dimen = gadget->set->dimen - set->dim; + if (set->dim + set->dimen > gadget->set->dimen) + goto err2; + else if (set->dim + set->dimen < gadget->set->dimen) + error(mpl, "dimension of %s too big", mpl->image); + get_token(mpl /* set name */); + /* left parenthesis must follow the set name */ + if (mpl->token == T_LEFT) + get_token(mpl /* ( */); + else + error(mpl, "left parenthesis missing where expected"); + /* parse permutation of component numbers */ + for (k = 0; k < gadget->set->dimen; k++) fff[k] = 0; + k = 0; + for (;;) + { if (mpl->token != T_NUMBER) + error(mpl, "component number missing where expected"); + if (str2int(mpl->image, &i) != 0) +err3: error(mpl, "component number must be integer between " + "1 and %d", gadget->set->dimen); + if (!(1 <= i && i <= gadget->set->dimen)) goto err3; + if (fff[i-1] != 0) + error(mpl, "component %d multiply specified", i); + gadget->ind[k++] = i, fff[i-1] = 1; + xassert(k <= gadget->set->dimen); + get_token(mpl /* number */); + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RIGHT) + break; + else + error(mpl, "syntax error in data attribute"); + } + if (k < gadget->set->dimen) + error(mpl, "there are must be %d components rather than " + "%d", gadget->set->dimen, k); + get_token(mpl /* ) */); + } +#endif + else + error(mpl, "syntax error in set statement"); + } + /* close the domain scope */ + if (set->domain != NULL) close_scope(mpl, set->domain); + /* if dimension of set members is still unknown, set it to 1 */ + if (set->dimen == 0) set->dimen = 1; + /* the set statement has been completely parsed */ + xassert(mpl->token == T_SEMICOLON); + get_token(mpl /* ; */); + return set; +} + +/*---------------------------------------------------------------------- +-- parameter_statement - parse parameter statement. +-- +-- This routine parses parameter statement using the syntax: +-- +-- <parameter statement> ::= param <symbolic name> <alias> <domain> +-- <attributes> ; +-- <alias> ::= <empty> +-- <alias> ::= <string literal> +-- <domain> ::= <empty> +-- <domain> ::= <indexing expression> +-- <attributes> ::= <empty> +-- <attributes> ::= <attributes> , integer +-- <attributes> ::= <attributes> , binary +-- <attributes> ::= <attributes> , symbolic +-- <attributes> ::= <attributes> , <rho> <expression 5> +-- <attributes> ::= <attributes> , in <expression 9> +-- <attributes> ::= <attributes> , := <expression 5> +-- <attributes> ::= <attributes> , default <expression 5> +-- <rho> ::= < | <= | = | == | >= | > | <> | != +-- +-- Commae in <attributes> are optional and may be omitted anywhere. */ + +PARAMETER *parameter_statement(MPL *mpl) +{ PARAMETER *par; + int integer_used = 0, binary_used = 0, symbolic_used = 0; + xassert(is_keyword(mpl, "param")); + get_token(mpl /* param */); + /* symbolic name must follow the keyword 'param' */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create model parameter */ + par = alloc(PARAMETER); + par->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(par->name, mpl->image); + par->alias = NULL; + par->dim = 0; + par->domain = NULL; + par->type = A_NUMERIC; + par->cond = NULL; + par->in = NULL; + par->assign = NULL; + par->option = NULL; + par->data = 0; + par->defval = NULL; + par->array = NULL; + get_token(mpl /* <symbolic name> */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { par->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(par->alias, mpl->image); + get_token(mpl /* <string literal> */); + } + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { par->domain = indexing_expression(mpl); + par->dim = domain_arity(mpl, par->domain); + } + /* include the parameter name in the symbolic names table */ + { AVLNODE *node; + node = avl_insert_node(mpl->tree, par->name); + avl_set_node_type(node, A_PARAMETER); + avl_set_node_link(node, (void *)par); + } + /* parse the list of optional attributes */ + for (;;) + { if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_SEMICOLON) + break; + if (is_keyword(mpl, "integer")) + { if (integer_used) + error(mpl, "at most one integer allowed"); + if (par->type == A_SYMBOLIC) + error(mpl, "symbolic parameter cannot be integer"); + if (par->type != A_BINARY) par->type = A_INTEGER; + integer_used = 1; + get_token(mpl /* integer */); + } + else if (is_keyword(mpl, "binary")) +bin: { if (binary_used) + error(mpl, "at most one binary allowed"); + if (par->type == A_SYMBOLIC) + error(mpl, "symbolic parameter cannot be binary"); + par->type = A_BINARY; + binary_used = 1; + get_token(mpl /* binary */); + } + else if (is_keyword(mpl, "logical")) + { if (!mpl->as_binary) + { warning(mpl, "keyword logical understood as binary"); + mpl->as_binary = 1; + } + goto bin; + } + else if (is_keyword(mpl, "symbolic")) + { if (symbolic_used) + error(mpl, "at most one symbolic allowed"); + if (par->type != A_NUMERIC) + error(mpl, "integer or binary parameter cannot be symbol" + "ic"); + /* the parameter may be referenced from expressions given + in the same parameter declaration, so its type must be + completed before parsing that expressions */ + if (!(par->cond == NULL && par->in == NULL && + par->assign == NULL && par->option == NULL)) + error(mpl, "keyword symbolic must precede any other para" + "meter attributes"); + par->type = A_SYMBOLIC; + symbolic_used = 1; + get_token(mpl /* symbolic */); + } + else if (mpl->token == T_LT || mpl->token == T_LE || + mpl->token == T_EQ || mpl->token == T_GE || + mpl->token == T_GT || mpl->token == T_NE) + { /* restricting condition */ + CONDITION *cond, *temp; + char opstr[8]; + /* create new restricting condition list entry and append + it to the conditions list */ + cond = alloc(CONDITION); + switch (mpl->token) + { case T_LT: + cond->rho = O_LT, strcpy(opstr, mpl->image); break; + case T_LE: + cond->rho = O_LE, strcpy(opstr, mpl->image); break; + case T_EQ: + cond->rho = O_EQ, strcpy(opstr, mpl->image); break; + case T_GE: + cond->rho = O_GE, strcpy(opstr, mpl->image); break; + case T_GT: + cond->rho = O_GT, strcpy(opstr, mpl->image); break; + case T_NE: + cond->rho = O_NE, strcpy(opstr, mpl->image); break; + default: + xassert(mpl->token != mpl->token); + } + xassert(strlen(opstr) < sizeof(opstr)); + cond->code = NULL; + cond->next = NULL; + if (par->cond == NULL) + par->cond = cond; + else + { for (temp = par->cond; temp->next != NULL; temp = + temp->next); + temp->next = cond; + } +#if 0 /* 13/VIII-2008 */ + if (par->type == A_SYMBOLIC && + !(cond->rho == O_EQ || cond->rho == O_NE)) + error(mpl, "inequality restriction not allowed"); +#endif + get_token(mpl /* rho */); + /* parse an expression that follows relational operator */ + cond->code = expression_5(mpl); + if (!(cond->code->type == A_NUMERIC || + cond->code->type == A_SYMBOLIC)) + error(mpl, "expression following %s has invalid type", + opstr); + xassert(cond->code->dim == 0); + /* convert to the parameter type, if necessary */ + if (par->type != A_SYMBOLIC && cond->code->type == + A_SYMBOLIC) + cond->code = make_unary(mpl, O_CVTNUM, cond->code, + A_NUMERIC, 0); + if (par->type == A_SYMBOLIC && cond->code->type != + A_SYMBOLIC) + cond->code = make_unary(mpl, O_CVTSYM, cond->code, + A_SYMBOLIC, 0); + } + else if (mpl->token == T_IN || mpl->token == T_WITHIN) + { /* restricting superset */ + WITHIN *in, *temp; + if (mpl->token == T_WITHIN && !mpl->as_in) + { warning(mpl, "keyword within understood as in"); + mpl->as_in = 1; + } + get_token(mpl /* in */); + /* create new restricting superset list entry and append it + to the in-list */ + in = alloc(WITHIN); + in->code = NULL; + in->next = NULL; + if (par->in == NULL) + par->in = in; + else + { for (temp = par->in; temp->next != NULL; temp = + temp->next); + temp->next = in; + } + /* parse an expression that follows 'in' */ + in->code = expression_9(mpl); + if (in->code->type != A_ELEMSET) + error(mpl, "expression following in has invalid type"); + xassert(in->code->dim > 0); + if (in->code->dim != 1) + error(mpl, "set expression following in must have dimens" + "ion 1 rather than %d", in->code->dim); + } + else if (mpl->token == T_ASSIGN) + { /* assignment expression */ + if (!(par->assign == NULL && par->option == NULL)) +err: error(mpl, "at most one := or default allowed"); + get_token(mpl /* := */); + /* parse an expression that follows ':=' */ + par->assign = expression_5(mpl); + /* the expression must be of numeric/symbolic type */ + if (!(par->assign->type == A_NUMERIC || + par->assign->type == A_SYMBOLIC)) + error(mpl, "expression following := has invalid type"); + xassert(par->assign->dim == 0); + /* convert to the parameter type, if necessary */ + if (par->type != A_SYMBOLIC && par->assign->type == + A_SYMBOLIC) + par->assign = make_unary(mpl, O_CVTNUM, par->assign, + A_NUMERIC, 0); + if (par->type == A_SYMBOLIC && par->assign->type != + A_SYMBOLIC) + par->assign = make_unary(mpl, O_CVTSYM, par->assign, + A_SYMBOLIC, 0); + } + else if (is_keyword(mpl, "default")) + { /* expression for default value */ + if (!(par->assign == NULL && par->option == NULL)) goto err; + get_token(mpl /* default */); + /* parse an expression that follows 'default' */ + par->option = expression_5(mpl); + if (!(par->option->type == A_NUMERIC || + par->option->type == A_SYMBOLIC)) + error(mpl, "expression following default has invalid typ" + "e"); + xassert(par->option->dim == 0); + /* convert to the parameter type, if necessary */ + if (par->type != A_SYMBOLIC && par->option->type == + A_SYMBOLIC) + par->option = make_unary(mpl, O_CVTNUM, par->option, + A_NUMERIC, 0); + if (par->type == A_SYMBOLIC && par->option->type != + A_SYMBOLIC) + par->option = make_unary(mpl, O_CVTSYM, par->option, + A_SYMBOLIC, 0); + } + else + error(mpl, "syntax error in parameter statement"); + } + /* close the domain scope */ + if (par->domain != NULL) close_scope(mpl, par->domain); + /* the parameter statement has been completely parsed */ + xassert(mpl->token == T_SEMICOLON); + get_token(mpl /* ; */); + return par; +} + +/*---------------------------------------------------------------------- +-- variable_statement - parse variable statement. +-- +-- This routine parses variable statement using the syntax: +-- +-- <variable statement> ::= var <symbolic name> <alias> <domain> +-- <attributes> ; +-- <alias> ::= <empty> +-- <alias> ::= <string literal> +-- <domain> ::= <empty> +-- <domain> ::= <indexing expression> +-- <attributes> ::= <empty> +-- <attributes> ::= <attributes> , integer +-- <attributes> ::= <attributes> , binary +-- <attributes> ::= <attributes> , <rho> <expression 5> +-- <rho> ::= >= | <= | = | == +-- +-- Commae in <attributes> are optional and may be omitted anywhere. */ + +VARIABLE *variable_statement(MPL *mpl) +{ VARIABLE *var; + int integer_used = 0, binary_used = 0; + xassert(is_keyword(mpl, "var")); + if (mpl->flag_s) + error(mpl, "variable statement must precede solve statement"); + get_token(mpl /* var */); + /* symbolic name must follow the keyword 'var' */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create model variable */ + var = alloc(VARIABLE); + var->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(var->name, mpl->image); + var->alias = NULL; + var->dim = 0; + var->domain = NULL; + var->type = A_NUMERIC; + var->lbnd = NULL; + var->ubnd = NULL; + var->array = NULL; + get_token(mpl /* <symbolic name> */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { var->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(var->alias, mpl->image); + get_token(mpl /* <string literal> */); + } + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { var->domain = indexing_expression(mpl); + var->dim = domain_arity(mpl, var->domain); + } + /* include the variable name in the symbolic names table */ + { AVLNODE *node; + node = avl_insert_node(mpl->tree, var->name); + avl_set_node_type(node, A_VARIABLE); + avl_set_node_link(node, (void *)var); + } + /* parse the list of optional attributes */ + for (;;) + { if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_SEMICOLON) + break; + if (is_keyword(mpl, "integer")) + { if (integer_used) + error(mpl, "at most one integer allowed"); + if (var->type != A_BINARY) var->type = A_INTEGER; + integer_used = 1; + get_token(mpl /* integer */); + } + else if (is_keyword(mpl, "binary")) +bin: { if (binary_used) + error(mpl, "at most one binary allowed"); + var->type = A_BINARY; + binary_used = 1; + get_token(mpl /* binary */); + } + else if (is_keyword(mpl, "logical")) + { if (!mpl->as_binary) + { warning(mpl, "keyword logical understood as binary"); + mpl->as_binary = 1; + } + goto bin; + } + else if (is_keyword(mpl, "symbolic")) + error(mpl, "variable cannot be symbolic"); + else if (mpl->token == T_GE) + { /* lower bound */ + if (var->lbnd != NULL) + { if (var->lbnd == var->ubnd) + error(mpl, "both fixed value and lower bound not allo" + "wed"); + else + error(mpl, "at most one lower bound allowed"); + } + get_token(mpl /* >= */); + /* parse an expression that specifies the lower bound */ + var->lbnd = expression_5(mpl); + if (var->lbnd->type == A_SYMBOLIC) + var->lbnd = make_unary(mpl, O_CVTNUM, var->lbnd, + A_NUMERIC, 0); + if (var->lbnd->type != A_NUMERIC) + error(mpl, "expression following >= has invalid type"); + xassert(var->lbnd->dim == 0); + } + else if (mpl->token == T_LE) + { /* upper bound */ + if (var->ubnd != NULL) + { if (var->ubnd == var->lbnd) + error(mpl, "both fixed value and upper bound not allo" + "wed"); + else + error(mpl, "at most one upper bound allowed"); + } + get_token(mpl /* <= */); + /* parse an expression that specifies the upper bound */ + var->ubnd = expression_5(mpl); + if (var->ubnd->type == A_SYMBOLIC) + var->ubnd = make_unary(mpl, O_CVTNUM, var->ubnd, + A_NUMERIC, 0); + if (var->ubnd->type != A_NUMERIC) + error(mpl, "expression following <= has invalid type"); + xassert(var->ubnd->dim == 0); + } + else if (mpl->token == T_EQ) + { /* fixed value */ + char opstr[8]; + if (!(var->lbnd == NULL && var->ubnd == NULL)) + { if (var->lbnd == var->ubnd) + error(mpl, "at most one fixed value allowed"); + else if (var->lbnd != NULL) + error(mpl, "both lower bound and fixed value not allo" + "wed"); + else + error(mpl, "both upper bound and fixed value not allo" + "wed"); + } + strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + get_token(mpl /* = | == */); + /* parse an expression that specifies the fixed value */ + var->lbnd = expression_5(mpl); + if (var->lbnd->type == A_SYMBOLIC) + var->lbnd = make_unary(mpl, O_CVTNUM, var->lbnd, + A_NUMERIC, 0); + if (var->lbnd->type != A_NUMERIC) + error(mpl, "expression following %s has invalid type", + opstr); + xassert(var->lbnd->dim == 0); + /* indicate that the variable is fixed, not bounded */ + var->ubnd = var->lbnd; + } + else if (mpl->token == T_LT || mpl->token == T_GT || + mpl->token == T_NE) + error(mpl, "strict bound not allowed"); + else + error(mpl, "syntax error in variable statement"); + } + /* close the domain scope */ + if (var->domain != NULL) close_scope(mpl, var->domain); + /* the variable statement has been completely parsed */ + xassert(mpl->token == T_SEMICOLON); + get_token(mpl /* ; */); + return var; +} + +/*---------------------------------------------------------------------- +-- constraint_statement - parse constraint statement. +-- +-- This routine parses constraint statement using the syntax: +-- +-- <constraint statement> ::= <subject to> <symbolic name> <alias> +-- <domain> : <constraint> ; +-- <subject to> ::= <empty> +-- <subject to> ::= subject to +-- <subject to> ::= subj to +-- <subject to> ::= s.t. +-- <alias> ::= <empty> +-- <alias> ::= <string literal> +-- <domain> ::= <empty> +-- <domain> ::= <indexing expression> +-- <constraint> ::= <formula> , >= <formula> +-- <constraint> ::= <formula> , <= <formula> +-- <constraint> ::= <formula> , = <formula> +-- <constraint> ::= <formula> , <= <formula> , <= <formula> +-- <constraint> ::= <formula> , >= <formula> , >= <formula> +-- <formula> ::= <expression 5> +-- +-- Commae in <constraint> are optional and may be omitted anywhere. */ + +CONSTRAINT *constraint_statement(MPL *mpl) +{ CONSTRAINT *con; + CODE *first, *second, *third; + int rho; + char opstr[8]; + if (mpl->flag_s) + error(mpl, "constraint statement must precede solve statement") + ; + if (is_keyword(mpl, "subject")) + { get_token(mpl /* subject */); + if (!is_keyword(mpl, "to")) + error(mpl, "keyword subject to incomplete"); + get_token(mpl /* to */); + } + else if (is_keyword(mpl, "subj")) + { get_token(mpl /* subj */); + if (!is_keyword(mpl, "to")) + error(mpl, "keyword subj to incomplete"); + get_token(mpl /* to */); + } + else if (mpl->token == T_SPTP) + get_token(mpl /* s.t. */); + /* the current token must be symbolic name of constraint */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create model constraint */ + con = alloc(CONSTRAINT); + con->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(con->name, mpl->image); + con->alias = NULL; + con->dim = 0; + con->domain = NULL; + con->type = A_CONSTRAINT; + con->code = NULL; + con->lbnd = NULL; + con->ubnd = NULL; + con->array = NULL; + get_token(mpl /* <symbolic name> */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { con->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(con->alias, mpl->image); + get_token(mpl /* <string literal> */); + } + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { con->domain = indexing_expression(mpl); + con->dim = domain_arity(mpl, con->domain); + } + /* include the constraint name in the symbolic names table */ + { AVLNODE *node; + node = avl_insert_node(mpl->tree, con->name); + avl_set_node_type(node, A_CONSTRAINT); + avl_set_node_link(node, (void *)con); + } + /* the colon must precede the first expression */ + if (mpl->token != T_COLON) + error(mpl, "colon missing where expected"); + get_token(mpl /* : */); + /* parse the first expression */ + first = expression_5(mpl); + if (first->type == A_SYMBOLIC) + first = make_unary(mpl, O_CVTNUM, first, A_NUMERIC, 0); + if (!(first->type == A_NUMERIC || first->type == A_FORMULA)) + error(mpl, "expression following colon has invalid type"); + xassert(first->dim == 0); + /* relational operator must follow the first expression */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + switch (mpl->token) + { case T_LE: + case T_GE: + case T_EQ: + break; + case T_LT: + case T_GT: + case T_NE: + error(mpl, "strict inequality not allowed"); + case T_SEMICOLON: + error(mpl, "constraint must be equality or inequality"); + default: + goto err; + } + rho = mpl->token; + strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + get_token(mpl /* rho */); + /* parse the second expression */ + second = expression_5(mpl); + if (second->type == A_SYMBOLIC) + second = make_unary(mpl, O_CVTNUM, second, A_NUMERIC, 0); + if (!(second->type == A_NUMERIC || second->type == A_FORMULA)) + error(mpl, "expression following %s has invalid type", opstr); + xassert(second->dim == 0); + /* check a token that follow the second expression */ + if (mpl->token == T_COMMA) + { get_token(mpl /* , */); + if (mpl->token == T_SEMICOLON) goto err; + } + if (mpl->token == T_LT || mpl->token == T_LE || + mpl->token == T_EQ || mpl->token == T_GE || + mpl->token == T_GT || mpl->token == T_NE) + { /* it is another relational operator, therefore the constraint + is double inequality */ + if (rho == T_EQ || mpl->token != rho) + error(mpl, "double inequality must be ... <= ... <= ... or " + "... >= ... >= ..."); + /* the first expression cannot be linear form */ + if (first->type == A_FORMULA) + error(mpl, "leftmost expression in double inequality cannot" + " be linear form"); + get_token(mpl /* rho */); + /* parse the third expression */ + third = expression_5(mpl); + if (third->type == A_SYMBOLIC) + third = make_unary(mpl, O_CVTNUM, second, A_NUMERIC, 0); + if (!(third->type == A_NUMERIC || third->type == A_FORMULA)) + error(mpl, "rightmost expression in double inequality const" + "raint has invalid type"); + xassert(third->dim == 0); + /* the third expression also cannot be linear form */ + if (third->type == A_FORMULA) + error(mpl, "rightmost expression in double inequality canno" + "t be linear form"); + } + else + { /* the constraint is equality or single inequality */ + third = NULL; + } + /* close the domain scope */ + if (con->domain != NULL) close_scope(mpl, con->domain); + /* convert all expressions to linear form, if necessary */ + if (first->type != A_FORMULA) + first = make_unary(mpl, O_CVTLFM, first, A_FORMULA, 0); + if (second->type != A_FORMULA) + second = make_unary(mpl, O_CVTLFM, second, A_FORMULA, 0); + if (third != NULL) + third = make_unary(mpl, O_CVTLFM, third, A_FORMULA, 0); + /* arrange expressions in the constraint */ + if (third == NULL) + { /* the constraint is equality or single inequality */ + switch (rho) + { case T_LE: + /* first <= second */ + con->code = first; + con->lbnd = NULL; + con->ubnd = second; + break; + case T_GE: + /* first >= second */ + con->code = first; + con->lbnd = second; + con->ubnd = NULL; + break; + case T_EQ: + /* first = second */ + con->code = first; + con->lbnd = second; + con->ubnd = second; + break; + default: + xassert(rho != rho); + } + } + else + { /* the constraint is double inequality */ + switch (rho) + { case T_LE: + /* first <= second <= third */ + con->code = second; + con->lbnd = first; + con->ubnd = third; + break; + case T_GE: + /* first >= second >= third */ + con->code = second; + con->lbnd = third; + con->ubnd = first; + break; + default: + xassert(rho != rho); + } + } + /* the constraint statement has been completely parsed */ + if (mpl->token != T_SEMICOLON) +err: error(mpl, "syntax error in constraint statement"); + get_token(mpl /* ; */); + return con; +} + +/*---------------------------------------------------------------------- +-- objective_statement - parse objective statement. +-- +-- This routine parses objective statement using the syntax: +-- +-- <objective statement> ::= <verb> <symbolic name> <alias> <domain> : +-- <formula> ; +-- <verb> ::= minimize +-- <verb> ::= maximize +-- <alias> ::= <empty> +-- <alias> ::= <string literal> +-- <domain> ::= <empty> +-- <domain> ::= <indexing expression> +-- <formula> ::= <expression 5> */ + +CONSTRAINT *objective_statement(MPL *mpl) +{ CONSTRAINT *obj; + int type; + if (is_keyword(mpl, "minimize")) + type = A_MINIMIZE; + else if (is_keyword(mpl, "maximize")) + type = A_MAXIMIZE; + else + xassert(mpl != mpl); + if (mpl->flag_s) + error(mpl, "objective statement must precede solve statement"); + get_token(mpl /* minimize | maximize */); + /* symbolic name must follow the verb 'minimize' or 'maximize' */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create model objective */ + obj = alloc(CONSTRAINT); + obj->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(obj->name, mpl->image); + obj->alias = NULL; + obj->dim = 0; + obj->domain = NULL; + obj->type = type; + obj->code = NULL; + obj->lbnd = NULL; + obj->ubnd = NULL; + obj->array = NULL; + get_token(mpl /* <symbolic name> */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { obj->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(obj->alias, mpl->image); + get_token(mpl /* <string literal> */); + } + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { obj->domain = indexing_expression(mpl); + obj->dim = domain_arity(mpl, obj->domain); + } + /* include the constraint name in the symbolic names table */ + { AVLNODE *node; + node = avl_insert_node(mpl->tree, obj->name); + avl_set_node_type(node, A_CONSTRAINT); + avl_set_node_link(node, (void *)obj); + } + /* the colon must precede the objective expression */ + if (mpl->token != T_COLON) + error(mpl, "colon missing where expected"); + get_token(mpl /* : */); + /* parse the objective expression */ + obj->code = expression_5(mpl); + if (obj->code->type == A_SYMBOLIC) + obj->code = make_unary(mpl, O_CVTNUM, obj->code, A_NUMERIC, 0); + if (obj->code->type == A_NUMERIC) + obj->code = make_unary(mpl, O_CVTLFM, obj->code, A_FORMULA, 0); + if (obj->code->type != A_FORMULA) + error(mpl, "expression following colon has invalid type"); + xassert(obj->code->dim == 0); + /* close the domain scope */ + if (obj->domain != NULL) close_scope(mpl, obj->domain); + /* the objective statement has been completely parsed */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in objective statement"); + get_token(mpl /* ; */); + return obj; +} + +#if 1 /* 11/II-2008 */ +/*********************************************************************** +* table_statement - parse table statement +* +* This routine parses table statement using the syntax: +* +* <table statement> ::= <input table statement> +* <table statement> ::= <output table statement> +* +* <input table statement> ::= +* table <table name> <alias> IN <argument list> : +* <input set> [ <field list> ] , <input list> ; +* <alias> ::= <empty> +* <alias> ::= <string literal> +* <argument list> ::= <expression 5> +* <argument list> ::= <argument list> <expression 5> +* <argument list> ::= <argument list> , <expression 5> +* <input set> ::= <empty> +* <input set> ::= <set name> <- +* <field list> ::= <field name> +* <field list> ::= <field list> , <field name> +* <input list> ::= <input item> +* <input list> ::= <input list> , <input item> +* <input item> ::= <parameter name> +* <input item> ::= <parameter name> ~ <field name> +* +* <output table statement> ::= +* table <table name> <alias> <domain> OUT <argument list> : +* <output list> ; +* <domain> ::= <indexing expression> +* <output list> ::= <output item> +* <output list> ::= <output list> , <output item> +* <output item> ::= <expression 5> +* <output item> ::= <expression 5> ~ <field name> */ + +TABLE *table_statement(MPL *mpl) +{ TABLE *tab; + TABARG *last_arg, *arg; + TABFLD *last_fld, *fld; + TABIN *last_in, *in; + TABOUT *last_out, *out; + AVLNODE *node; + int nflds; + char name[MAX_LENGTH+1]; + xassert(is_keyword(mpl, "table")); + get_token(mpl /* solve */); + /* symbolic name must follow the keyword table */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create data table */ + tab = alloc(TABLE); + tab->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(tab->name, mpl->image); + get_token(mpl /* <symbolic name> */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { tab->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(tab->alias, mpl->image); + get_token(mpl /* <string literal> */); + } + else + tab->alias = NULL; + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { /* this is output table */ + tab->type = A_OUTPUT; + tab->u.out.domain = indexing_expression(mpl); + if (!is_keyword(mpl, "OUT")) + error(mpl, "keyword OUT missing where expected"); + get_token(mpl /* OUT */); + } + else + { /* this is input table */ + tab->type = A_INPUT; + if (!is_keyword(mpl, "IN")) + error(mpl, "keyword IN missing where expected"); + get_token(mpl /* IN */); + } + /* parse argument list */ + tab->arg = last_arg = NULL; + for (;;) + { /* create argument list entry */ + arg = alloc(TABARG); + /* parse argument expression */ + if (mpl->token == T_COMMA || mpl->token == T_COLON || + mpl->token == T_SEMICOLON) + error(mpl, "argument expression missing where expected"); + arg->code = expression_5(mpl); + /* convert the result to symbolic type, if necessary */ + if (arg->code->type == A_NUMERIC) + arg->code = + make_unary(mpl, O_CVTSYM, arg->code, A_SYMBOLIC, 0); + /* check that now the result is of symbolic type */ + if (arg->code->type != A_SYMBOLIC) + error(mpl, "argument expression has invalid type"); + /* add the entry to the end of the list */ + arg->next = NULL; + if (last_arg == NULL) + tab->arg = arg; + else + last_arg->next = arg; + last_arg = arg; + /* argument expression has been parsed */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_COLON || mpl->token == T_SEMICOLON) + break; + } + xassert(tab->arg != NULL); + /* argument list must end with colon */ + if (mpl->token == T_COLON) + get_token(mpl /* : */); + else + error(mpl, "colon missing where expected"); + /* parse specific part of the table statement */ + switch (tab->type) + { case A_INPUT: goto input_table; + case A_OUTPUT: goto output_table; + default: xassert(tab != tab); + } +input_table: + /* parse optional set name */ + if (mpl->token == T_NAME) + { node = avl_find_node(mpl->tree, mpl->image); + if (node == NULL) + error(mpl, "%s not defined", mpl->image); + if (avl_get_node_type(node) != A_SET) + error(mpl, "%s not a set", mpl->image); + tab->u.in.set = (SET *)avl_get_node_link(node); + if (tab->u.in.set->assign != NULL) + error(mpl, "%s needs no data", mpl->image); + if (tab->u.in.set->dim != 0) + error(mpl, "%s must be a simple set", mpl->image); + get_token(mpl /* <symbolic name> */); + if (mpl->token == T_INPUT) + get_token(mpl /* <- */); + else + error(mpl, "delimiter <- missing where expected"); + } + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + tab->u.in.set = NULL; + /* parse field list */ + tab->u.in.fld = last_fld = NULL; + nflds = 0; + if (mpl->token == T_LBRACKET) + get_token(mpl /* [ */); + else + error(mpl, "field list missing where expected"); + for (;;) + { /* create field list entry */ + fld = alloc(TABFLD); + /* parse field name */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, + "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "field name missing where expected"); + fld->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(fld->name, mpl->image); + get_token(mpl /* <symbolic name> */); + /* add the entry to the end of the list */ + fld->next = NULL; + if (last_fld == NULL) + tab->u.in.fld = fld; + else + last_fld->next = fld; + last_fld = fld; + nflds++; + /* field name has been parsed */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RBRACKET) + break; + else + error(mpl, "syntax error in field list"); + } + /* check that the set dimen is equal to the number of fields */ + if (tab->u.in.set != NULL && tab->u.in.set->dimen != nflds) + error(mpl, "there must be %d field%s rather than %d", + tab->u.in.set->dimen, tab->u.in.set->dimen == 1 ? "" : "s", + nflds); + get_token(mpl /* ] */); + /* parse optional input list */ + tab->u.in.list = last_in = NULL; + while (mpl->token == T_COMMA) + { get_token(mpl /* , */); + /* create input list entry */ + in = alloc(TABIN); + /* parse parameter name */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, + "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "parameter name missing where expected"); + node = avl_find_node(mpl->tree, mpl->image); + if (node == NULL) + error(mpl, "%s not defined", mpl->image); + if (avl_get_node_type(node) != A_PARAMETER) + error(mpl, "%s not a parameter", mpl->image); + in->par = (PARAMETER *)avl_get_node_link(node); + if (in->par->dim != nflds) + error(mpl, "%s must have %d subscript%s rather than %d", + mpl->image, nflds, nflds == 1 ? "" : "s", in->par->dim); + if (in->par->assign != NULL) + error(mpl, "%s needs no data", mpl->image); + get_token(mpl /* <symbolic name> */); + /* parse optional field name */ + if (mpl->token == T_TILDE) + { get_token(mpl /* ~ */); + /* parse field name */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, + "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "field name missing where expected"); + xassert(strlen(mpl->image) < sizeof(name)); + strcpy(name, mpl->image); + get_token(mpl /* <symbolic name> */); + } + else + { /* field name is the same as the parameter name */ + xassert(strlen(in->par->name) < sizeof(name)); + strcpy(name, in->par->name); + } + /* assign field name */ + in->name = dmp_get_atomv(mpl->pool, strlen(name)+1); + strcpy(in->name, name); + /* add the entry to the end of the list */ + in->next = NULL; + if (last_in == NULL) + tab->u.in.list = in; + else + last_in->next = in; + last_in = in; + } + goto end_of_table; +output_table: + /* parse output list */ + tab->u.out.list = last_out = NULL; + for (;;) + { /* create output list entry */ + out = alloc(TABOUT); + /* parse expression */ + if (mpl->token == T_COMMA || mpl->token == T_SEMICOLON) + error(mpl, "expression missing where expected"); + if (mpl->token == T_NAME) + { xassert(strlen(mpl->image) < sizeof(name)); + strcpy(name, mpl->image); + } + else + name[0] = '\0'; + out->code = expression_5(mpl); + /* parse optional field name */ + if (mpl->token == T_TILDE) + { get_token(mpl /* ~ */); + /* parse field name */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, + "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "field name missing where expected"); + xassert(strlen(mpl->image) < sizeof(name)); + strcpy(name, mpl->image); + get_token(mpl /* <symbolic name> */); + } + /* assign field name */ + if (name[0] == '\0') + error(mpl, "field name required"); + out->name = dmp_get_atomv(mpl->pool, strlen(name)+1); + strcpy(out->name, name); + /* add the entry to the end of the list */ + out->next = NULL; + if (last_out == NULL) + tab->u.out.list = out; + else + last_out->next = out; + last_out = out; + /* output item has been parsed */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_SEMICOLON) + break; + else + error(mpl, "syntax error in output list"); + } + /* close the domain scope */ + close_scope(mpl,tab->u.out.domain); +end_of_table: + /* the table statement must end with semicolon */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in table statement"); + get_token(mpl /* ; */); + return tab; +} +#endif + +/*---------------------------------------------------------------------- +-- solve_statement - parse solve statement. +-- +-- This routine parses solve statement using the syntax: +-- +-- <solve statement> ::= solve ; +-- +-- The solve statement can be used at most once. */ + +void *solve_statement(MPL *mpl) +{ xassert(is_keyword(mpl, "solve")); + if (mpl->flag_s) + error(mpl, "at most one solve statement allowed"); + mpl->flag_s = 1; + get_token(mpl /* solve */); + /* semicolon must follow solve statement */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in solve statement"); + get_token(mpl /* ; */); + return NULL; +} + +/*---------------------------------------------------------------------- +-- check_statement - parse check statement. +-- +-- This routine parses check statement using the syntax: +-- +-- <check statement> ::= check <domain> : <expression 13> ; +-- <domain> ::= <empty> +-- <domain> ::= <indexing expression> +-- +-- If <domain> is omitted, colon following it may also be omitted. */ + +CHECK *check_statement(MPL *mpl) +{ CHECK *chk; + xassert(is_keyword(mpl, "check")); + /* create check descriptor */ + chk = alloc(CHECK); + chk->domain = NULL; + chk->code = NULL; + get_token(mpl /* check */); + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { chk->domain = indexing_expression(mpl); +#if 0 + if (mpl->token != T_COLON) + error(mpl, "colon missing where expected"); +#endif + } + /* skip optional colon */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* parse logical expression */ + chk->code = expression_13(mpl); + if (chk->code->type != A_LOGICAL) + error(mpl, "expression has invalid type"); + xassert(chk->code->dim == 0); + /* close the domain scope */ + if (chk->domain != NULL) close_scope(mpl, chk->domain); + /* the check statement has been completely parsed */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in check statement"); + get_token(mpl /* ; */); + return chk; +} + +#if 1 /* 15/V-2010 */ +/*---------------------------------------------------------------------- +-- display_statement - parse display statement. +-- +-- This routine parses display statement using the syntax: +-- +-- <display statement> ::= display <domain> : <display list> ; +-- <display statement> ::= display <domain> <display list> ; +-- <domain> ::= <empty> +-- <domain> ::= <indexing expression> +-- <display list> ::= <display entry> +-- <display list> ::= <display list> , <display entry> +-- <display entry> ::= <dummy index> +-- <display entry> ::= <set name> +-- <display entry> ::= <set name> [ <subscript list> ] +-- <display entry> ::= <parameter name> +-- <display entry> ::= <parameter name> [ <subscript list> ] +-- <display entry> ::= <variable name> +-- <display entry> ::= <variable name> [ <subscript list> ] +-- <display entry> ::= <constraint name> +-- <display entry> ::= <constraint name> [ <subscript list> ] +-- <display entry> ::= <expression 13> */ + +DISPLAY *display_statement(MPL *mpl) +{ DISPLAY *dpy; + DISPLAY1 *entry, *last_entry; + xassert(is_keyword(mpl, "display")); + /* create display descriptor */ + dpy = alloc(DISPLAY); + dpy->domain = NULL; + dpy->list = last_entry = NULL; + get_token(mpl /* display */); + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + dpy->domain = indexing_expression(mpl); + /* skip optional colon */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* parse display list */ + for (;;) + { /* create new display entry */ + entry = alloc(DISPLAY1); + entry->type = 0; + entry->next = NULL; + /* and append it to the display list */ + if (dpy->list == NULL) + dpy->list = entry; + else + last_entry->next = entry; + last_entry = entry; + /* parse display entry */ + if (mpl->token == T_NAME) + { AVLNODE *node; + int next_token; + get_token(mpl /* <symbolic name> */); + next_token = mpl->token; + unget_token(mpl); + if (!(next_token == T_COMMA || next_token == T_SEMICOLON)) + { /* symbolic name begins expression */ + goto expr; + } + /* display entry is dummy index or model object */ + node = avl_find_node(mpl->tree, mpl->image); + if (node == NULL) + error(mpl, "%s not defined", mpl->image); + entry->type = avl_get_node_type(node); + switch (avl_get_node_type(node)) + { case A_INDEX: + entry->u.slot = + (DOMAIN_SLOT *)avl_get_node_link(node); + break; + case A_SET: + entry->u.set = (SET *)avl_get_node_link(node); + break; + case A_PARAMETER: + entry->u.par = (PARAMETER *)avl_get_node_link(node); + break; + case A_VARIABLE: + entry->u.var = (VARIABLE *)avl_get_node_link(node); + if (!mpl->flag_s) + error(mpl, "invalid reference to variable %s above" + " solve statement", entry->u.var->name); + break; + case A_CONSTRAINT: + entry->u.con = (CONSTRAINT *)avl_get_node_link(node); + if (!mpl->flag_s) + error(mpl, "invalid reference to %s %s above solve" + " statement", + entry->u.con->type == A_CONSTRAINT ? + "constraint" : "objective", entry->u.con->name); + break; + default: + xassert(node != node); + } + get_token(mpl /* <symbolic name> */); + } + else +expr: { /* display entry is expression */ + entry->type = A_EXPRESSION; + entry->u.code = expression_13(mpl); + } + /* check a token that follows the entry parsed */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else + break; + } + /* close the domain scope */ + if (dpy->domain != NULL) close_scope(mpl, dpy->domain); + /* the display statement has been completely parsed */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in display statement"); + get_token(mpl /* ; */); + return dpy; +} +#endif + +/*---------------------------------------------------------------------- +-- printf_statement - parse printf statement. +-- +-- This routine parses print statement using the syntax: +-- +-- <printf statement> ::= <printf clause> ; +-- <printf statement> ::= <printf clause> > <file name> ; +-- <printf statement> ::= <printf clause> >> <file name> ; +-- <printf clause> ::= printf <domain> : <format> <printf list> +-- <printf clause> ::= printf <domain> <format> <printf list> +-- <domain> ::= <empty> +-- <domain> ::= <indexing expression> +-- <format> ::= <expression 5> +-- <printf list> ::= <empty> +-- <printf list> ::= <printf list> , <printf entry> +-- <printf entry> ::= <expression 9> +-- <file name> ::= <expression 5> */ + +PRINTF *printf_statement(MPL *mpl) +{ PRINTF *prt; + PRINTF1 *entry, *last_entry; + xassert(is_keyword(mpl, "printf")); + /* create printf descriptor */ + prt = alloc(PRINTF); + prt->domain = NULL; + prt->fmt = NULL; + prt->list = last_entry = NULL; + get_token(mpl /* printf */); + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { prt->domain = indexing_expression(mpl); +#if 0 + if (mpl->token != T_COLON) + error(mpl, "colon missing where expected"); +#endif + } + /* skip optional colon */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* parse expression for format string */ + prt->fmt = expression_5(mpl); + /* convert it to symbolic type, if necessary */ + if (prt->fmt->type == A_NUMERIC) + prt->fmt = make_unary(mpl, O_CVTSYM, prt->fmt, A_SYMBOLIC, 0); + /* check that now the expression is of symbolic type */ + if (prt->fmt->type != A_SYMBOLIC) + error(mpl, "format expression has invalid type"); + /* parse printf list */ + while (mpl->token == T_COMMA) + { get_token(mpl /* , */); + /* create new printf entry */ + entry = alloc(PRINTF1); + entry->code = NULL; + entry->next = NULL; + /* and append it to the printf list */ + if (prt->list == NULL) + prt->list = entry; + else + last_entry->next = entry; + last_entry = entry; + /* parse printf entry */ + entry->code = expression_9(mpl); + if (!(entry->code->type == A_NUMERIC || + entry->code->type == A_SYMBOLIC || + entry->code->type == A_LOGICAL)) + error(mpl, "only numeric, symbolic, or logical expression a" + "llowed"); + } + /* close the domain scope */ + if (prt->domain != NULL) close_scope(mpl, prt->domain); +#if 1 /* 14/VII-2006 */ + /* parse optional redirection */ + prt->fname = NULL, prt->app = 0; + if (mpl->token == T_GT || mpl->token == T_APPEND) + { prt->app = (mpl->token == T_APPEND); + get_token(mpl /* > or >> */); + /* parse expression for file name string */ + prt->fname = expression_5(mpl); + /* convert it to symbolic type, if necessary */ + if (prt->fname->type == A_NUMERIC) + prt->fname = make_unary(mpl, O_CVTSYM, prt->fname, + A_SYMBOLIC, 0); + /* check that now the expression is of symbolic type */ + if (prt->fname->type != A_SYMBOLIC) + error(mpl, "file name expression has invalid type"); + } +#endif + /* the printf statement has been completely parsed */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in printf statement"); + get_token(mpl /* ; */); + return prt; +} + +/*---------------------------------------------------------------------- +-- for_statement - parse for statement. +-- +-- This routine parses for statement using the syntax: +-- +-- <for statement> ::= for <domain> <statement> +-- <for statement> ::= for <domain> { <statement list> } +-- <domain> ::= <indexing expression> +-- <statement list> ::= <empty> +-- <statement list> ::= <statement list> <statement> +-- <statement> ::= <check statement> +-- <statement> ::= <display statement> +-- <statement> ::= <printf statement> +-- <statement> ::= <for statement> */ + +FOR *for_statement(MPL *mpl) +{ FOR *fur; + STATEMENT *stmt, *last_stmt; + xassert(is_keyword(mpl, "for")); + /* create for descriptor */ + fur = alloc(FOR); + fur->domain = NULL; + fur->list = last_stmt = NULL; + get_token(mpl /* for */); + /* parse indexing expression */ + if (mpl->token != T_LBRACE) + error(mpl, "indexing expression missing where expected"); + fur->domain = indexing_expression(mpl); + /* skip optional colon */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* parse for statement body */ + if (mpl->token != T_LBRACE) + { /* parse simple statement */ + fur->list = simple_statement(mpl, 1); + } + else + { /* parse compound statement */ + get_token(mpl /* { */); + while (mpl->token != T_RBRACE) + { /* parse statement */ + stmt = simple_statement(mpl, 1); + /* and append it to the end of the statement list */ + if (last_stmt == NULL) + fur->list = stmt; + else + last_stmt->next = stmt; + last_stmt = stmt; + } + get_token(mpl /* } */); + } + /* close the domain scope */ + xassert(fur->domain != NULL); + close_scope(mpl, fur->domain); + /* the for statement has been completely parsed */ + return fur; +} + +/*---------------------------------------------------------------------- +-- end_statement - parse end statement. +-- +-- This routine parses end statement using the syntax: +-- +-- <end statement> ::= end ; <eof> */ + +void end_statement(MPL *mpl) +{ if (!mpl->flag_d && is_keyword(mpl, "end") || + mpl->flag_d && is_literal(mpl, "end")) + { get_token(mpl /* end */); + if (mpl->token == T_SEMICOLON) + get_token(mpl /* ; */); + else + warning(mpl, "no semicolon following end statement; missing" + " semicolon inserted"); + } + else + warning(mpl, "unexpected end of file; missing end statement in" + "serted"); + if (mpl->token != T_EOF) + warning(mpl, "some text detected beyond end statement; text ig" + "nored"); + return; +} + +/*---------------------------------------------------------------------- +-- simple_statement - parse simple statement. +-- +-- This routine parses simple statement using the syntax: +-- +-- <statement> ::= <set statement> +-- <statement> ::= <parameter statement> +-- <statement> ::= <variable statement> +-- <statement> ::= <constraint statement> +-- <statement> ::= <objective statement> +-- <statement> ::= <solve statement> +-- <statement> ::= <check statement> +-- <statement> ::= <display statement> +-- <statement> ::= <printf statement> +-- <statement> ::= <for statement> +-- +-- If the flag spec is set, some statements cannot be used. */ + +STATEMENT *simple_statement(MPL *mpl, int spec) +{ STATEMENT *stmt; + stmt = alloc(STATEMENT); + stmt->line = mpl->line; + stmt->next = NULL; + if (is_keyword(mpl, "set")) + { if (spec) + error(mpl, "set statement not allowed here"); + stmt->type = A_SET; + stmt->u.set = set_statement(mpl); + } + else if (is_keyword(mpl, "param")) + { if (spec) + error(mpl, "parameter statement not allowed here"); + stmt->type = A_PARAMETER; + stmt->u.par = parameter_statement(mpl); + } + else if (is_keyword(mpl, "var")) + { if (spec) + error(mpl, "variable statement not allowed here"); + stmt->type = A_VARIABLE; + stmt->u.var = variable_statement(mpl); + } + else if (is_keyword(mpl, "subject") || + is_keyword(mpl, "subj") || + mpl->token == T_SPTP) + { if (spec) + error(mpl, "constraint statement not allowed here"); + stmt->type = A_CONSTRAINT; + stmt->u.con = constraint_statement(mpl); + } + else if (is_keyword(mpl, "minimize") || + is_keyword(mpl, "maximize")) + { if (spec) + error(mpl, "objective statement not allowed here"); + stmt->type = A_CONSTRAINT; + stmt->u.con = objective_statement(mpl); + } +#if 1 /* 11/II-2008 */ + else if (is_keyword(mpl, "table")) + { if (spec) + error(mpl, "table statement not allowed here"); + stmt->type = A_TABLE; + stmt->u.tab = table_statement(mpl); + } +#endif + else if (is_keyword(mpl, "solve")) + { if (spec) + error(mpl, "solve statement not allowed here"); + stmt->type = A_SOLVE; + stmt->u.slv = solve_statement(mpl); + } + else if (is_keyword(mpl, "check")) + { stmt->type = A_CHECK; + stmt->u.chk = check_statement(mpl); + } + else if (is_keyword(mpl, "display")) + { stmt->type = A_DISPLAY; + stmt->u.dpy = display_statement(mpl); + } + else if (is_keyword(mpl, "printf")) + { stmt->type = A_PRINTF; + stmt->u.prt = printf_statement(mpl); + } + else if (is_keyword(mpl, "for")) + { stmt->type = A_FOR; + stmt->u.fur = for_statement(mpl); + } + else if (mpl->token == T_NAME) + { if (spec) + error(mpl, "constraint statement not allowed here"); + stmt->type = A_CONSTRAINT; + stmt->u.con = constraint_statement(mpl); + } + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "syntax error in model section"); + return stmt; +} + +/*---------------------------------------------------------------------- +-- model_section - parse model section. +-- +-- This routine parses model section using the syntax: +-- +-- <model section> ::= <empty> +-- <model section> ::= <model section> <statement> +-- +-- Parsing model section is terminated by either the keyword 'data', or +-- the keyword 'end', or the end of file. */ + +void model_section(MPL *mpl) +{ STATEMENT *stmt, *last_stmt; + xassert(mpl->model == NULL); + last_stmt = NULL; + while (!(mpl->token == T_EOF || is_keyword(mpl, "data") || + is_keyword(mpl, "end"))) + { /* parse statement */ + stmt = simple_statement(mpl, 0); + /* and append it to the end of the statement list */ + if (last_stmt == NULL) + mpl->model = stmt; + else + last_stmt->next = stmt; + last_stmt = stmt; + } + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl02.c b/resources/3rdparty/glpk-4.53/src/glpmpl02.c new file mode 100644 index 000000000..277593981 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpmpl02.c @@ -0,0 +1,1203 @@ +/* glpmpl02.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "glpmpl.h" + +/**********************************************************************/ +/* * * PROCESSING DATA SECTION * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_slice - create slice. +-- +-- This routine creates a slice, which initially has no components. */ + +SLICE *create_slice(MPL *mpl) +{ SLICE *slice; + xassert(mpl == mpl); + slice = NULL; + return slice; +} + +/*---------------------------------------------------------------------- +-- expand_slice - append new component to slice. +-- +-- This routine expands slice appending to it either a given symbol or +-- null component, which becomes the last component of the slice. */ + +SLICE *expand_slice +( MPL *mpl, + SLICE *slice, /* destroyed */ + SYMBOL *sym /* destroyed */ +) +{ SLICE *tail, *temp; + /* create a new component */ + tail = dmp_get_atom(mpl->tuples, sizeof(SLICE)); + tail->sym = sym; + tail->next = NULL; + /* and append it to the component list */ + if (slice == NULL) + slice = tail; + else + { for (temp = slice; temp->next != NULL; temp = temp->next); + temp->next = tail; + } + return slice; +} + +/*---------------------------------------------------------------------- +-- slice_dimen - determine dimension of slice. +-- +-- This routine returns dimension of slice, which is number of all its +-- components including null ones. */ + +int slice_dimen +( MPL *mpl, + SLICE *slice /* not changed */ +) +{ SLICE *temp; + int dim; + xassert(mpl == mpl); + dim = 0; + for (temp = slice; temp != NULL; temp = temp->next) dim++; + return dim; +} + +/*---------------------------------------------------------------------- +-- slice_arity - determine arity of slice. +-- +-- This routine returns arity of slice, i.e. number of null components +-- (indicated by asterisks) in the slice. */ + +int slice_arity +( MPL *mpl, + SLICE *slice /* not changed */ +) +{ SLICE *temp; + int arity; + xassert(mpl == mpl); + arity = 0; + for (temp = slice; temp != NULL; temp = temp->next) + if (temp->sym == NULL) arity++; + return arity; +} + +/*---------------------------------------------------------------------- +-- fake_slice - create fake slice of all asterisks. +-- +-- This routine creates a fake slice of given dimension, which contains +-- asterisks in all components. Zero dimension is allowed. */ + +SLICE *fake_slice(MPL *mpl, int dim) +{ SLICE *slice; + slice = create_slice(mpl); + while (dim-- > 0) slice = expand_slice(mpl, slice, NULL); + return slice; +} + +/*---------------------------------------------------------------------- +-- delete_slice - delete slice. +-- +-- This routine deletes specified slice. */ + +void delete_slice +( MPL *mpl, + SLICE *slice /* destroyed */ +) +{ SLICE *temp; + while (slice != NULL) + { temp = slice; + slice = temp->next; + if (temp->sym != NULL) delete_symbol(mpl, temp->sym); +xassert(sizeof(SLICE) == sizeof(TUPLE)); + dmp_free_atom(mpl->tuples, temp, sizeof(TUPLE)); + } + return; +} + +/*---------------------------------------------------------------------- +-- is_number - check if current token is number. +-- +-- If the current token is a number, this routine returns non-zero. +-- Otherwise zero is returned. */ + +int is_number(MPL *mpl) +{ return + mpl->token == T_NUMBER; +} + +/*---------------------------------------------------------------------- +-- is_symbol - check if current token is symbol. +-- +-- If the current token is suitable to be a symbol, the routine returns +-- non-zero. Otherwise zero is returned. */ + +int is_symbol(MPL *mpl) +{ return + mpl->token == T_NUMBER || + mpl->token == T_SYMBOL || + mpl->token == T_STRING; +} + +/*---------------------------------------------------------------------- +-- is_literal - check if current token is given symbolic literal. +-- +-- If the current token is given symbolic literal, this routine returns +-- non-zero. Otherwise zero is returned. +-- +-- This routine is used on processing the data section in the same way +-- as the routine is_keyword on processing the model section. */ + +int is_literal(MPL *mpl, char *literal) +{ return + is_symbol(mpl) && strcmp(mpl->image, literal) == 0; +} + +/*---------------------------------------------------------------------- +-- read_number - read number. +-- +-- This routine reads the current token, which must be a number, and +-- returns its numeric value. */ + +double read_number(MPL *mpl) +{ double num; + xassert(is_number(mpl)); + num = mpl->value; + get_token(mpl /* <number> */); + return num; +} + +/*---------------------------------------------------------------------- +-- read_symbol - read symbol. +-- +-- This routine reads the current token, which must be a symbol, and +-- returns its symbolic value. */ + +SYMBOL *read_symbol(MPL *mpl) +{ SYMBOL *sym; + xassert(is_symbol(mpl)); + if (is_number(mpl)) + sym = create_symbol_num(mpl, mpl->value); + else + sym = create_symbol_str(mpl, create_string(mpl, mpl->image)); + get_token(mpl /* <symbol> */); + return sym; +} + +/*---------------------------------------------------------------------- +-- read_slice - read slice. +-- +-- This routine reads slice using the syntax: +-- +-- <slice> ::= [ <symbol list> ] +-- <slice> ::= ( <symbol list> ) +-- <symbol list> ::= <symbol or star> +-- <symbol list> ::= <symbol list> , <symbol or star> +-- <symbol or star> ::= <symbol> +-- <symbol or star> ::= * +-- +-- The bracketed form of slice is used for members of multi-dimensional +-- objects while the parenthesized form is used for elemental sets. */ + +SLICE *read_slice +( MPL *mpl, + char *name, /* not changed */ + int dim +) +{ SLICE *slice; + int close; + xassert(name != NULL); + switch (mpl->token) + { case T_LBRACKET: + close = T_RBRACKET; + break; + case T_LEFT: + xassert(dim > 0); + close = T_RIGHT; + break; + default: + xassert(mpl != mpl); + } + if (dim == 0) + error(mpl, "%s cannot be subscripted", name); + get_token(mpl /* ( | [ */); + /* read slice components */ + slice = create_slice(mpl); + for (;;) + { /* the current token must be a symbol or asterisk */ + if (is_symbol(mpl)) + slice = expand_slice(mpl, slice, read_symbol(mpl)); + else if (mpl->token == T_ASTERISK) + { slice = expand_slice(mpl, slice, NULL); + get_token(mpl /* * */); + } + else + error(mpl, "number, symbol, or asterisk missing where expec" + "ted"); + /* check a token that follows the symbol */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == close) + break; + else + error(mpl, "syntax error in slice"); + } + /* number of slice components must be the same as the appropriate + dimension */ + if (slice_dimen(mpl, slice) != dim) + { switch (close) + { case T_RBRACKET: + error(mpl, "%s must have %d subscript%s, not %d", name, + dim, dim == 1 ? "" : "s", slice_dimen(mpl, slice)); + break; + case T_RIGHT: + error(mpl, "%s has dimension %d, not %d", name, dim, + slice_dimen(mpl, slice)); + break; + default: + xassert(close != close); + } + } + get_token(mpl /* ) | ] */); + return slice; +} + +/*---------------------------------------------------------------------- +-- select_set - select set to saturate it with elemental sets. +-- +-- This routine selects set to saturate it with elemental sets provided +-- in the data section. */ + +SET *select_set +( MPL *mpl, + char *name /* not changed */ +) +{ SET *set; + AVLNODE *node; + xassert(name != NULL); + node = avl_find_node(mpl->tree, name); + if (node == NULL || avl_get_node_type(node) != A_SET) + error(mpl, "%s not a set", name); + set = (SET *)avl_get_node_link(node); + if (set->assign != NULL || set->gadget != NULL) + error(mpl, "%s needs no data", name); + set->data = 1; + return set; +} + +/*---------------------------------------------------------------------- +-- simple_format - read set data block in simple format. +-- +-- This routine reads set data block using the syntax: +-- +-- <simple format> ::= <symbol> , <symbol> , ... , <symbol> +-- +-- where <symbols> are used to construct a complete n-tuple, which is +-- included in elemental set assigned to the set member. Commae between +-- symbols are optional and may be omitted anywhere. +-- +-- Number of components in the slice must be the same as dimension of +-- n-tuples in elemental sets assigned to the set members. To construct +-- complete n-tuple the routine replaces null positions in the slice by +-- corresponding <symbols>. +-- +-- If the slice contains at least one null position, the current token +-- must be symbol. Otherwise, the routine reads no symbols to construct +-- the n-tuple, so the current token is not checked. */ + +void simple_format +( MPL *mpl, + SET *set, /* not changed */ + MEMBER *memb, /* modified */ + SLICE *slice /* not changed */ +) +{ TUPLE *tuple; + SLICE *temp; + SYMBOL *sym, *with = NULL; + xassert(set != NULL); + xassert(memb != NULL); + xassert(slice != NULL); + xassert(set->dimen == slice_dimen(mpl, slice)); + xassert(memb->value.set->dim == set->dimen); + if (slice_arity(mpl, slice) > 0) xassert(is_symbol(mpl)); + /* read symbols and construct complete n-tuple */ + tuple = create_tuple(mpl); + for (temp = slice; temp != NULL; temp = temp->next) + { if (temp->sym == NULL) + { /* substitution is needed; read symbol */ + if (!is_symbol(mpl)) + { int lack = slice_arity(mpl, temp); + /* with cannot be null due to assertion above */ + xassert(with != NULL); + if (lack == 1) + error(mpl, "one item missing in data group beginning " + "with %s", format_symbol(mpl, with)); + else + error(mpl, "%d items missing in data group beginning " + "with %s", lack, format_symbol(mpl, with)); + } + sym = read_symbol(mpl); + if (with == NULL) with = sym; + } + else + { /* copy symbol from the slice */ + sym = copy_symbol(mpl, temp->sym); + } + /* append the symbol to the n-tuple */ + tuple = expand_tuple(mpl, tuple, sym); + /* skip optional comma *between* <symbols> */ + if (temp->next != NULL && mpl->token == T_COMMA) + get_token(mpl /* , */); + } + /* add constructed n-tuple to elemental set */ + check_then_add(mpl, memb->value.set, tuple); + return; +} + +/*---------------------------------------------------------------------- +-- matrix_format - read set data block in matrix format. +-- +-- This routine reads set data block using the syntax: +-- +-- <matrix format> ::= <column> <column> ... <column> := +-- <row> +/- +/- ... +/- +-- <row> +/- +/- ... +/- +-- . . . . . . . . . . . +-- <row> +/- +/- ... +/- +-- +-- where <rows> are symbols that denote rows of the matrix, <columns> +-- are symbols that denote columns of the matrix, "+" and "-" indicate +-- whether corresponding n-tuple needs to be included in the elemental +-- set or not, respectively. +-- +-- Number of the slice components must be the same as dimension of the +-- elemental set. The slice must have two null positions. To construct +-- complete n-tuple for particular element of the matrix the routine +-- replaces first null position of the slice by the corresponding <row> +-- (or <column>, if the flag tr is on) and second null position by the +-- corresponding <column> (or by <row>, if the flag tr is on). */ + +void matrix_format +( MPL *mpl, + SET *set, /* not changed */ + MEMBER *memb, /* modified */ + SLICE *slice, /* not changed */ + int tr +) +{ SLICE *list, *col, *temp; + TUPLE *tuple; + SYMBOL *row; + xassert(set != NULL); + xassert(memb != NULL); + xassert(slice != NULL); + xassert(set->dimen == slice_dimen(mpl, slice)); + xassert(memb->value.set->dim == set->dimen); + xassert(slice_arity(mpl, slice) == 2); + /* read the matrix heading that contains column symbols (there + may be no columns at all) */ + list = create_slice(mpl); + while (mpl->token != T_ASSIGN) + { /* read column symbol and append it to the column list */ + if (!is_symbol(mpl)) + error(mpl, "number, symbol, or := missing where expected"); + list = expand_slice(mpl, list, read_symbol(mpl)); + } + get_token(mpl /* := */); + /* read zero or more rows that contain matrix data */ + while (is_symbol(mpl)) + { /* read row symbol (if the matrix has no columns, row symbols + are just ignored) */ + row = read_symbol(mpl); + /* read the matrix row accordingly to the column list */ + for (col = list; col != NULL; col = col->next) + { int which = 0; + /* check indicator */ + if (is_literal(mpl, "+")) + ; + else if (is_literal(mpl, "-")) + { get_token(mpl /* - */); + continue; + } + else + { int lack = slice_dimen(mpl, col); + if (lack == 1) + error(mpl, "one item missing in data group beginning " + "with %s", format_symbol(mpl, row)); + else + error(mpl, "%d items missing in data group beginning " + "with %s", lack, format_symbol(mpl, row)); + } + /* construct complete n-tuple */ + tuple = create_tuple(mpl); + for (temp = slice; temp != NULL; temp = temp->next) + { if (temp->sym == NULL) + { /* substitution is needed */ + switch (++which) + { case 1: + /* substitute in the first null position */ + tuple = expand_tuple(mpl, tuple, + copy_symbol(mpl, tr ? col->sym : row)); + break; + case 2: + /* substitute in the second null position */ + tuple = expand_tuple(mpl, tuple, + copy_symbol(mpl, tr ? row : col->sym)); + break; + default: + xassert(which != which); + } + } + else + { /* copy symbol from the slice */ + tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, + temp->sym)); + } + } + xassert(which == 2); + /* add constructed n-tuple to elemental set */ + check_then_add(mpl, memb->value.set, tuple); + get_token(mpl /* + */); + } + /* delete the row symbol */ + delete_symbol(mpl, row); + } + /* delete the column list */ + delete_slice(mpl, list); + return; +} + +/*---------------------------------------------------------------------- +-- set_data - read set data. +-- +-- This routine reads set data using the syntax: +-- +-- <set data> ::= set <set name> <assignments> ; +-- <set data> ::= set <set name> [ <symbol list> ] <assignments> ; +-- <set name> ::= <symbolic name> +-- <assignments> ::= <empty> +-- <assignments> ::= <assignments> , := +-- <assignments> ::= <assignments> , ( <symbol list> ) +-- <assignments> ::= <assignments> , <simple format> +-- <assignments> ::= <assignments> , : <matrix format> +-- <assignments> ::= <assignments> , (tr) <matrix format> +-- <assignments> ::= <assignments> , (tr) : <matrix format> +-- +-- Commae in <assignments> are optional and may be omitted anywhere. */ + +void set_data(MPL *mpl) +{ SET *set; + TUPLE *tuple; + MEMBER *memb; + SLICE *slice; + int tr = 0; + xassert(is_literal(mpl, "set")); + get_token(mpl /* set */); + /* symbolic name of set must follows the keyword 'set' */ + if (!is_symbol(mpl)) + error(mpl, "set name missing where expected"); + /* select the set to saturate it with data */ + set = select_set(mpl, mpl->image); + get_token(mpl /* <symbolic name> */); + /* read optional subscript list, which identifies member of the + set to be read */ + tuple = create_tuple(mpl); + if (mpl->token == T_LBRACKET) + { /* subscript list is specified */ + if (set->dim == 0) + error(mpl, "%s cannot be subscripted", set->name); + get_token(mpl /* [ */); + /* read symbols and construct subscript list */ + for (;;) + { if (!is_symbol(mpl)) + error(mpl, "number or symbol missing where expected"); + tuple = expand_tuple(mpl, tuple, read_symbol(mpl)); + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RBRACKET) + break; + else + error(mpl, "syntax error in subscript list"); + } + if (set->dim != tuple_dimen(mpl, tuple)) + error(mpl, "%s must have %d subscript%s rather than %d", + set->name, set->dim, set->dim == 1 ? "" : "s", + tuple_dimen(mpl, tuple)); + get_token(mpl /* ] */); + } + else + { /* subscript list is not specified */ + if (set->dim != 0) + error(mpl, "%s must be subscripted", set->name); + } + /* there must be no member with the same subscript list */ + if (find_member(mpl, set->array, tuple) != NULL) + error(mpl, "%s%s already defined", + set->name, format_tuple(mpl, '[', tuple)); + /* add new member to the set and assign it empty elemental set */ + memb = add_member(mpl, set->array, tuple); + memb->value.set = create_elemset(mpl, set->dimen); + /* create an initial fake slice of all asterisks */ + slice = fake_slice(mpl, set->dimen); + /* read zero or more data assignments */ + for (;;) + { /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + /* process assignment element */ + if (mpl->token == T_ASSIGN) + { /* assignment ligature is non-significant element */ + get_token(mpl /* := */); + } + else if (mpl->token == T_LEFT) + { /* left parenthesis begins either new slice or "transpose" + indicator */ + int is_tr; + get_token(mpl /* ( */); + is_tr = is_literal(mpl, "tr"); + unget_token(mpl /* ( */); + if (is_tr) goto left; + /* delete the current slice and read new one */ + delete_slice(mpl, slice); + slice = read_slice(mpl, set->name, set->dimen); + /* each new slice resets the "transpose" indicator */ + tr = 0; + /* if the new slice is 0-ary, formally there is one 0-tuple + (in the simple format) that follows it */ + if (slice_arity(mpl, slice) == 0) + simple_format(mpl, set, memb, slice); + } + else if (is_symbol(mpl)) + { /* number or symbol begins data in the simple format */ + simple_format(mpl, set, memb, slice); + } + else if (mpl->token == T_COLON) + { /* colon begins data in the matrix format */ + if (slice_arity(mpl, slice) != 2) +err1: error(mpl, "slice currently used must specify 2 asterisk" + "s, not %d", slice_arity(mpl, slice)); + get_token(mpl /* : */); + /* read elemental set data in the matrix format */ + matrix_format(mpl, set, memb, slice, tr); + } + else if (mpl->token == T_LEFT) +left: { /* left parenthesis begins the "transpose" indicator, which + is followed by data in the matrix format */ + get_token(mpl /* ( */); + if (!is_literal(mpl, "tr")) +err2: error(mpl, "transpose indicator (tr) incomplete"); + if (slice_arity(mpl, slice) != 2) goto err1; + get_token(mpl /* tr */); + if (mpl->token != T_RIGHT) goto err2; + get_token(mpl /* ) */); + /* in this case the colon is optional */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* set the "transpose" indicator */ + tr = 1; + /* read elemental set data in the matrix format */ + matrix_format(mpl, set, memb, slice, tr); + } + else if (mpl->token == T_SEMICOLON) + { /* semicolon terminates the data block */ + get_token(mpl /* ; */); + break; + } + else + error(mpl, "syntax error in set data block"); + } + /* delete the current slice */ + delete_slice(mpl, slice); + return; +} + +/*---------------------------------------------------------------------- +-- select_parameter - select parameter to saturate it with data. +-- +-- This routine selects parameter to saturate it with data provided in +-- the data section. */ + +PARAMETER *select_parameter +( MPL *mpl, + char *name /* not changed */ +) +{ PARAMETER *par; + AVLNODE *node; + xassert(name != NULL); + node = avl_find_node(mpl->tree, name); + if (node == NULL || avl_get_node_type(node) != A_PARAMETER) + error(mpl, "%s not a parameter", name); + par = (PARAMETER *)avl_get_node_link(node); + if (par->assign != NULL) + error(mpl, "%s needs no data", name); + if (par->data) + error(mpl, "%s already provided with data", name); + par->data = 1; + return par; +} + +/*---------------------------------------------------------------------- +-- set_default - set default parameter value. +-- +-- This routine sets default value for specified parameter. */ + +void set_default +( MPL *mpl, + PARAMETER *par, /* not changed */ + SYMBOL *altval /* destroyed */ +) +{ xassert(par != NULL); + xassert(altval != NULL); + if (par->option != NULL) + error(mpl, "default value for %s already specified in model se" + "ction", par->name); + xassert(par->defval == NULL); + par->defval = altval; + return; +} + +/*---------------------------------------------------------------------- +-- read_value - read value and assign it to parameter member. +-- +-- This routine reads numeric or symbolic value from the input stream +-- and assigns to new parameter member specified by its n-tuple, which +-- (the member) is created and added to the parameter array. */ + +MEMBER *read_value +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* destroyed */ +) +{ MEMBER *memb; + xassert(par != NULL); + xassert(is_symbol(mpl)); + /* there must be no member with the same n-tuple */ + if (find_member(mpl, par->array, tuple) != NULL) + error(mpl, "%s%s already defined", + par->name, format_tuple(mpl, '[', tuple)); + /* create new parameter member with given n-tuple */ + memb = add_member(mpl, par->array, tuple); + /* read value and assigns it to the new parameter member */ + switch (par->type) + { case A_NUMERIC: + case A_INTEGER: + case A_BINARY: + if (!is_number(mpl)) + error(mpl, "%s requires numeric data", par->name); + memb->value.num = read_number(mpl); + break; + case A_SYMBOLIC: + memb->value.sym = read_symbol(mpl); + break; + default: + xassert(par != par); + } + return memb; +} + +/*---------------------------------------------------------------------- +-- plain_format - read parameter data block in plain format. +-- +-- This routine reads parameter data block using the syntax: +-- +-- <plain format> ::= <symbol> , <symbol> , ... , <symbol> , <value> +-- +-- where <symbols> are used to determine a complete subscript list for +-- parameter member, <value> is a numeric or symbolic value assigned to +-- the parameter member. Commae between data items are optional and may +-- be omitted anywhere. +-- +-- Number of components in the slice must be the same as dimension of +-- the parameter. To construct the complete subscript list the routine +-- replaces null positions in the slice by corresponding <symbols>. */ + +void plain_format +( MPL *mpl, + PARAMETER *par, /* not changed */ + SLICE *slice /* not changed */ +) +{ TUPLE *tuple; + SLICE *temp; + SYMBOL *sym, *with = NULL; + xassert(par != NULL); + xassert(par->dim == slice_dimen(mpl, slice)); + xassert(is_symbol(mpl)); + /* read symbols and construct complete subscript list */ + tuple = create_tuple(mpl); + for (temp = slice; temp != NULL; temp = temp->next) + { if (temp->sym == NULL) + { /* substitution is needed; read symbol */ + if (!is_symbol(mpl)) + { int lack = slice_arity(mpl, temp) + 1; + xassert(with != NULL); + xassert(lack > 1); + error(mpl, "%d items missing in data group beginning wit" + "h %s", lack, format_symbol(mpl, with)); + } + sym = read_symbol(mpl); + if (with == NULL) with = sym; + } + else + { /* copy symbol from the slice */ + sym = copy_symbol(mpl, temp->sym); + } + /* append the symbol to the subscript list */ + tuple = expand_tuple(mpl, tuple, sym); + /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + } + /* read value and assign it to new parameter member */ + if (!is_symbol(mpl)) + { xassert(with != NULL); + error(mpl, "one item missing in data group beginning with %s", + format_symbol(mpl, with)); + } + read_value(mpl, par, tuple); + return; +} + +/*---------------------------------------------------------------------- +-- tabular_format - read parameter data block in tabular format. +-- +-- This routine reads parameter data block using the syntax: +-- +-- <tabular format> ::= <column> <column> ... <column> := +-- <row> <value> <value> ... <value> +-- <row> <value> <value> ... <value> +-- . . . . . . . . . . . +-- <row> <value> <value> ... <value> +-- +-- where <rows> are symbols that denote rows of the table, <columns> +-- are symbols that denote columns of the table, <values> are numeric +-- or symbolic values assigned to the corresponding parameter members. +-- If <value> is specified as single point, no value is provided. +-- +-- Number of components in the slice must be the same as dimension of +-- the parameter. The slice must have two null positions. To construct +-- complete subscript list for particular <value> the routine replaces +-- the first null position of the slice by the corresponding <row> (or +-- <column>, if the flag tr is on) and the second null position by the +-- corresponding <column> (or by <row>, if the flag tr is on). */ + +void tabular_format +( MPL *mpl, + PARAMETER *par, /* not changed */ + SLICE *slice, /* not changed */ + int tr +) +{ SLICE *list, *col, *temp; + TUPLE *tuple; + SYMBOL *row; + xassert(par != NULL); + xassert(par->dim == slice_dimen(mpl, slice)); + xassert(slice_arity(mpl, slice) == 2); + /* read the table heading that contains column symbols (the table + may have no columns) */ + list = create_slice(mpl); + while (mpl->token != T_ASSIGN) + { /* read column symbol and append it to the column list */ + if (!is_symbol(mpl)) + error(mpl, "number, symbol, or := missing where expected"); + list = expand_slice(mpl, list, read_symbol(mpl)); + } + get_token(mpl /* := */); + /* read zero or more rows that contain tabular data */ + while (is_symbol(mpl)) + { /* read row symbol (if the table has no columns, these symbols + are just ignored) */ + row = read_symbol(mpl); + /* read values accordingly to the column list */ + for (col = list; col != NULL; col = col->next) + { int which = 0; + /* if the token is single point, no value is provided */ + if (is_literal(mpl, ".")) + { get_token(mpl /* . */); + continue; + } + /* construct complete subscript list */ + tuple = create_tuple(mpl); + for (temp = slice; temp != NULL; temp = temp->next) + { if (temp->sym == NULL) + { /* substitution is needed */ + switch (++which) + { case 1: + /* substitute in the first null position */ + tuple = expand_tuple(mpl, tuple, + copy_symbol(mpl, tr ? col->sym : row)); + break; + case 2: + /* substitute in the second null position */ + tuple = expand_tuple(mpl, tuple, + copy_symbol(mpl, tr ? row : col->sym)); + break; + default: + xassert(which != which); + } + } + else + { /* copy symbol from the slice */ + tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, + temp->sym)); + } + } + xassert(which == 2); + /* read value and assign it to new parameter member */ + if (!is_symbol(mpl)) + { int lack = slice_dimen(mpl, col); + if (lack == 1) + error(mpl, "one item missing in data group beginning " + "with %s", format_symbol(mpl, row)); + else + error(mpl, "%d items missing in data group beginning " + "with %s", lack, format_symbol(mpl, row)); + } + read_value(mpl, par, tuple); + } + /* delete the row symbol */ + delete_symbol(mpl, row); + } + /* delete the column list */ + delete_slice(mpl, list); + return; +} + +/*---------------------------------------------------------------------- +-- tabbing_format - read parameter data block in tabbing format. +-- +-- This routine reads parameter data block using the syntax: +-- +-- <tabbing format> ::= <prefix> <name> , ... , <name> , := , +-- <symbol> , ... , <symbol> , <value> , ... , <value> , +-- <symbol> , ... , <symbol> , <value> , ... , <value> , +-- . . . . . . . . . . . . . . . . . +-- <symbol> , ... , <symbol> , <value> , ... , <value> +-- <prefix> ::= <empty> +-- <prefix> ::= <set name> : +-- +-- where <names> are names of parameters (all the parameters must be +-- subscripted and have identical dimensions), <symbols> are symbols +-- used to define subscripts of parameter members, <values> are numeric +-- or symbolic values assigned to the corresponding parameter members. +-- Optional <prefix> may specify a simple set, in which case n-tuples +-- built of <symbols> for each row of the data table (i.e. subscripts +-- of parameter members) are added to the specified set. Commae between +-- data items are optional and may be omitted anywhere. +-- +-- If the parameter altval is not NULL, it specifies a default value +-- provided for all the parameters specified in the data block. */ + +void tabbing_format +( MPL *mpl, + SYMBOL *altval /* not changed */ +) +{ SET *set = NULL; + PARAMETER *par; + SLICE *list, *col; + TUPLE *tuple; + int next_token, j, dim = 0; + char *last_name = NULL; + /* read the optional <prefix> */ + if (is_symbol(mpl)) + { get_token(mpl /* <symbol> */); + next_token = mpl->token; + unget_token(mpl /* <symbol> */); + if (next_token == T_COLON) + { /* select the set to saturate it with data */ + set = select_set(mpl, mpl->image); + /* the set must be simple (i.e. not set of sets) */ + if (set->dim != 0) + error(mpl, "%s must be a simple set", set->name); + /* and must not be defined yet */ + if (set->array->head != NULL) + error(mpl, "%s already defined", set->name); + /* add new (the only) member to the set and assign it empty + elemental set */ + add_member(mpl, set->array, NULL)->value.set = + create_elemset(mpl, set->dimen); + last_name = set->name, dim = set->dimen; + get_token(mpl /* <symbol> */); + xassert(mpl->token == T_COLON); + get_token(mpl /* : */); + } + } + /* read the table heading that contains parameter names */ + list = create_slice(mpl); + while (mpl->token != T_ASSIGN) + { /* there must be symbolic name of parameter */ + if (!is_symbol(mpl)) + error(mpl, "parameter name or := missing where expected"); + /* select the parameter to saturate it with data */ + par = select_parameter(mpl, mpl->image); + /* the parameter must be subscripted */ + if (par->dim == 0) + error(mpl, "%s not a subscripted parameter", mpl->image); + /* the set (if specified) and all the parameters in the data + block must have identical dimension */ + if (dim != 0 && par->dim != dim) + { xassert(last_name != NULL); + error(mpl, "%s has dimension %d while %s has dimension %d", + last_name, dim, par->name, par->dim); + } + /* set default value for the parameter (if specified) */ + if (altval != NULL) + set_default(mpl, par, copy_symbol(mpl, altval)); + /* append the parameter to the column list */ + list = expand_slice(mpl, list, (SYMBOL *)par); + last_name = par->name, dim = par->dim; + get_token(mpl /* <symbol> */); + /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + } + if (slice_dimen(mpl, list) == 0) + error(mpl, "at least one parameter name required"); + get_token(mpl /* := */); + /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + /* read rows that contain tabbing data */ + while (is_symbol(mpl)) + { /* read subscript list */ + tuple = create_tuple(mpl); + for (j = 1; j <= dim; j++) + { /* read j-th subscript */ + if (!is_symbol(mpl)) + { int lack = slice_dimen(mpl, list) + dim - j + 1; + xassert(tuple != NULL); + xassert(lack > 1); + error(mpl, "%d items missing in data group beginning wit" + "h %s", lack, format_symbol(mpl, tuple->sym)); + } + /* read and append j-th subscript to the n-tuple */ + tuple = expand_tuple(mpl, tuple, read_symbol(mpl)); + /* skip optional comma *between* <symbols> */ + if (j < dim && mpl->token == T_COMMA) + get_token(mpl /* , */); + } + /* if the set is specified, add to it new n-tuple, which is a + copy of the subscript list just read */ + if (set != NULL) + check_then_add(mpl, set->array->head->value.set, + copy_tuple(mpl, tuple)); + /* skip optional comma between <symbol> and <value> */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + /* read values accordingly to the column list */ + for (col = list; col != NULL; col = col->next) + { /* if the token is single point, no value is provided */ + if (is_literal(mpl, ".")) + { get_token(mpl /* . */); + continue; + } + /* read value and assign it to new parameter member */ + if (!is_symbol(mpl)) + { int lack = slice_dimen(mpl, col); + xassert(tuple != NULL); + if (lack == 1) + error(mpl, "one item missing in data group beginning " + "with %s", format_symbol(mpl, tuple->sym)); + else + error(mpl, "%d items missing in data group beginning " + "with %s", lack, format_symbol(mpl, tuple->sym)); + } + read_value(mpl, (PARAMETER *)col->sym, copy_tuple(mpl, + tuple)); + /* skip optional comma preceding the next value */ + if (col->next != NULL && mpl->token == T_COMMA) + get_token(mpl /* , */); + } + /* delete the original subscript list */ + delete_tuple(mpl, tuple); + /* skip optional comma (only if there is next data group) */ + if (mpl->token == T_COMMA) + { get_token(mpl /* , */); + if (!is_symbol(mpl)) unget_token(mpl /* , */); + } + } + /* delete the column list (it contains parameters, not symbols, + so nullify it before) */ + for (col = list; col != NULL; col = col->next) col->sym = NULL; + delete_slice(mpl, list); + return; +} + +/*---------------------------------------------------------------------- +-- parameter_data - read parameter data. +-- +-- This routine reads parameter data using the syntax: +-- +-- <parameter data> ::= param <default value> : <tabbing format> ; +-- <parameter data> ::= param <parameter name> <default value> +-- <assignments> ; +-- <parameter name> ::= <symbolic name> +-- <default value> ::= <empty> +-- <default value> ::= default <symbol> +-- <assignments> ::= <empty> +-- <assignments> ::= <assignments> , := +-- <assignments> ::= <assignments> , [ <symbol list> ] +-- <assignments> ::= <assignments> , <plain format> +-- <assignemnts> ::= <assignments> , : <tabular format> +-- <assignments> ::= <assignments> , (tr) <tabular format> +-- <assignments> ::= <assignments> , (tr) : <tabular format> +-- +-- Commae in <assignments> are optional and may be omitted anywhere. */ + +void parameter_data(MPL *mpl) +{ PARAMETER *par; + SYMBOL *altval = NULL; + SLICE *slice; + int tr = 0; + xassert(is_literal(mpl, "param")); + get_token(mpl /* param */); + /* read optional default value */ + if (is_literal(mpl, "default")) + { get_token(mpl /* default */); + if (!is_symbol(mpl)) + error(mpl, "default value missing where expected"); + altval = read_symbol(mpl); + /* if the default value follows the keyword 'param', the next + token must be only the colon */ + if (mpl->token != T_COLON) + error(mpl, "colon missing where expected"); + } + /* being used after the keyword 'param' or the optional default + value the colon begins data in the tabbing format */ + if (mpl->token == T_COLON) + { get_token(mpl /* : */); + /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + /* read parameter data in the tabbing format */ + tabbing_format(mpl, altval); + /* on reading data in the tabbing format the default value is + always copied, so delete the original symbol */ + if (altval != NULL) delete_symbol(mpl, altval); + /* the next token must be only semicolon */ + if (mpl->token != T_SEMICOLON) + error(mpl, "symbol, number, or semicolon missing where expe" + "cted"); + get_token(mpl /* ; */); + goto done; + } + /* in other cases there must be symbolic name of parameter, which + follows the keyword 'param' */ + if (!is_symbol(mpl)) + error(mpl, "parameter name missing where expected"); + /* select the parameter to saturate it with data */ + par = select_parameter(mpl, mpl->image); + get_token(mpl /* <symbol> */); + /* read optional default value */ + if (is_literal(mpl, "default")) + { get_token(mpl /* default */); + if (!is_symbol(mpl)) + error(mpl, "default value missing where expected"); + altval = read_symbol(mpl); + /* set default value for the parameter */ + set_default(mpl, par, altval); + } + /* create initial fake slice of all asterisks */ + slice = fake_slice(mpl, par->dim); + /* read zero or more data assignments */ + for (;;) + { /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + /* process current assignment */ + if (mpl->token == T_ASSIGN) + { /* assignment ligature is non-significant element */ + get_token(mpl /* := */); + } + else if (mpl->token == T_LBRACKET) + { /* left bracket begins new slice; delete the current slice + and read new one */ + delete_slice(mpl, slice); + slice = read_slice(mpl, par->name, par->dim); + /* each new slice resets the "transpose" indicator */ + tr = 0; + } + else if (is_symbol(mpl)) + { /* number or symbol begins data in the plain format */ + plain_format(mpl, par, slice); + } + else if (mpl->token == T_COLON) + { /* colon begins data in the tabular format */ + if (par->dim == 0) +err1: error(mpl, "%s not a subscripted parameter", + par->name); + if (slice_arity(mpl, slice) != 2) +err2: error(mpl, "slice currently used must specify 2 asterisk" + "s, not %d", slice_arity(mpl, slice)); + get_token(mpl /* : */); + /* read parameter data in the tabular format */ + tabular_format(mpl, par, slice, tr); + } + else if (mpl->token == T_LEFT) + { /* left parenthesis begins the "transpose" indicator, which + is followed by data in the tabular format */ + get_token(mpl /* ( */); + if (!is_literal(mpl, "tr")) +err3: error(mpl, "transpose indicator (tr) incomplete"); + if (par->dim == 0) goto err1; + if (slice_arity(mpl, slice) != 2) goto err2; + get_token(mpl /* tr */); + if (mpl->token != T_RIGHT) goto err3; + get_token(mpl /* ) */); + /* in this case the colon is optional */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* set the "transpose" indicator */ + tr = 1; + /* read parameter data in the tabular format */ + tabular_format(mpl, par, slice, tr); + } + else if (mpl->token == T_SEMICOLON) + { /* semicolon terminates the data block */ + get_token(mpl /* ; */); + break; + } + else + error(mpl, "syntax error in parameter data block"); + } + /* delete the current slice */ + delete_slice(mpl, slice); +done: return; +} + +/*---------------------------------------------------------------------- +-- data_section - read data section. +-- +-- This routine reads data section using the syntax: +-- +-- <data section> ::= <empty> +-- <data section> ::= <data section> <data block> ; +-- <data block> ::= <set data> +-- <data block> ::= <parameter data> +-- +-- Reading data section is terminated by either the keyword 'end' or +-- the end of file. */ + +void data_section(MPL *mpl) +{ while (!(mpl->token == T_EOF || is_literal(mpl, "end"))) + { if (is_literal(mpl, "set")) + set_data(mpl); + else if (is_literal(mpl, "param")) + parameter_data(mpl); + else + error(mpl, "syntax error in data section"); + } + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl03.c b/resources/3rdparty/glpk-4.53/src/glpmpl03.c new file mode 100644 index 000000000..b84dd7ccf --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpmpl03.c @@ -0,0 +1,6085 @@ +/* glpmpl03.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "glpmpl.h" + +/**********************************************************************/ +/* * * FLOATING-POINT NUMBERS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- fp_add - floating-point addition. +-- +-- This routine computes the sum x + y. */ + +double fp_add(MPL *mpl, double x, double y) +{ if (x > 0.0 && y > 0.0 && x > + 0.999 * DBL_MAX - y || + x < 0.0 && y < 0.0 && x < - 0.999 * DBL_MAX - y) + error(mpl, "%.*g + %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + return x + y; +} + +/*---------------------------------------------------------------------- +-- fp_sub - floating-point subtraction. +-- +-- This routine computes the difference x - y. */ + +double fp_sub(MPL *mpl, double x, double y) +{ if (x > 0.0 && y < 0.0 && x > + 0.999 * DBL_MAX + y || + x < 0.0 && y > 0.0 && x < - 0.999 * DBL_MAX + y) + error(mpl, "%.*g - %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + return x - y; +} + +/*---------------------------------------------------------------------- +-- fp_less - floating-point non-negative subtraction. +-- +-- This routine computes the non-negative difference max(0, x - y). */ + +double fp_less(MPL *mpl, double x, double y) +{ if (x < y) return 0.0; + if (x > 0.0 && y < 0.0 && x > + 0.999 * DBL_MAX + y) + error(mpl, "%.*g less %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + return x - y; +} + +/*---------------------------------------------------------------------- +-- fp_mul - floating-point multiplication. +-- +-- This routine computes the product x * y. */ + +double fp_mul(MPL *mpl, double x, double y) +{ if (fabs(y) > 1.0 && fabs(x) > (0.999 * DBL_MAX) / fabs(y)) + error(mpl, "%.*g * %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + return x * y; +} + +/*---------------------------------------------------------------------- +-- fp_div - floating-point division. +-- +-- This routine computes the quotient x / y. */ + +double fp_div(MPL *mpl, double x, double y) +{ if (fabs(y) < DBL_MIN) + error(mpl, "%.*g / %.*g; floating-point zero divide", + DBL_DIG, x, DBL_DIG, y); + if (fabs(y) < 1.0 && fabs(x) > (0.999 * DBL_MAX) * fabs(y)) + error(mpl, "%.*g / %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + return x / y; +} + +/*---------------------------------------------------------------------- +-- fp_idiv - floating-point quotient of exact division. +-- +-- This routine computes the quotient of exact division x div y. */ + +double fp_idiv(MPL *mpl, double x, double y) +{ if (fabs(y) < DBL_MIN) + error(mpl, "%.*g div %.*g; floating-point zero divide", + DBL_DIG, x, DBL_DIG, y); + if (fabs(y) < 1.0 && fabs(x) > (0.999 * DBL_MAX) * fabs(y)) + error(mpl, "%.*g div %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + x /= y; + return x > 0.0 ? floor(x) : x < 0.0 ? ceil(x) : 0.0; +} + +/*---------------------------------------------------------------------- +-- fp_mod - floating-point remainder of exact division. +-- +-- This routine computes the remainder of exact division x mod y. +-- +-- NOTE: By definition x mod y = x - y * floor(x / y). */ + +double fp_mod(MPL *mpl, double x, double y) +{ double r; + xassert(mpl == mpl); + if (x == 0.0) + r = 0.0; + else if (y == 0.0) + r = x; + else + { r = fmod(fabs(x), fabs(y)); + if (r != 0.0) + { if (x < 0.0) r = - r; + if (x > 0.0 && y < 0.0 || x < 0.0 && y > 0.0) r += y; + } + } + return r; +} + +/*---------------------------------------------------------------------- +-- fp_power - floating-point exponentiation (raise to power). +-- +-- This routine computes the exponentiation x ** y. */ + +double fp_power(MPL *mpl, double x, double y) +{ double r; + if (x == 0.0 && y <= 0.0 || x < 0.0 && y != floor(y)) + error(mpl, "%.*g ** %.*g; result undefined", + DBL_DIG, x, DBL_DIG, y); + if (x == 0.0) goto eval; + if (fabs(x) > 1.0 && y > +1.0 && + +log(fabs(x)) > (0.999 * log(DBL_MAX)) / y || + fabs(x) < 1.0 && y < -1.0 && + +log(fabs(x)) < (0.999 * log(DBL_MAX)) / y) + error(mpl, "%.*g ** %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + if (fabs(x) > 1.0 && y < -1.0 && + -log(fabs(x)) < (0.999 * log(DBL_MAX)) / y || + fabs(x) < 1.0 && y > +1.0 && + -log(fabs(x)) > (0.999 * log(DBL_MAX)) / y) + r = 0.0; + else +eval: r = pow(x, y); + return r; +} + +/*---------------------------------------------------------------------- +-- fp_exp - floating-point base-e exponential. +-- +-- This routine computes the base-e exponential e ** x. */ + +double fp_exp(MPL *mpl, double x) +{ if (x > 0.999 * log(DBL_MAX)) + error(mpl, "exp(%.*g); floating-point overflow", DBL_DIG, x); + return exp(x); +} + +/*---------------------------------------------------------------------- +-- fp_log - floating-point natural logarithm. +-- +-- This routine computes the natural logarithm log x. */ + +double fp_log(MPL *mpl, double x) +{ if (x <= 0.0) + error(mpl, "log(%.*g); non-positive argument", DBL_DIG, x); + return log(x); +} + +/*---------------------------------------------------------------------- +-- fp_log10 - floating-point common (decimal) logarithm. +-- +-- This routine computes the common (decimal) logarithm lg x. */ + +double fp_log10(MPL *mpl, double x) +{ if (x <= 0.0) + error(mpl, "log10(%.*g); non-positive argument", DBL_DIG, x); + return log10(x); +} + +/*---------------------------------------------------------------------- +-- fp_sqrt - floating-point square root. +-- +-- This routine computes the square root x ** 0.5. */ + +double fp_sqrt(MPL *mpl, double x) +{ if (x < 0.0) + error(mpl, "sqrt(%.*g); negative argument", DBL_DIG, x); + return sqrt(x); +} + +/*---------------------------------------------------------------------- +-- fp_sin - floating-point trigonometric sine. +-- +-- This routine computes the trigonometric sine sin(x). */ + +double fp_sin(MPL *mpl, double x) +{ if (!(-1e6 <= x && x <= +1e6)) + error(mpl, "sin(%.*g); argument too large", DBL_DIG, x); + return sin(x); +} + +/*---------------------------------------------------------------------- +-- fp_cos - floating-point trigonometric cosine. +-- +-- This routine computes the trigonometric cosine cos(x). */ + +double fp_cos(MPL *mpl, double x) +{ if (!(-1e6 <= x && x <= +1e6)) + error(mpl, "cos(%.*g); argument too large", DBL_DIG, x); + return cos(x); +} + +/*---------------------------------------------------------------------- +-- fp_atan - floating-point trigonometric arctangent. +-- +-- This routine computes the trigonometric arctangent atan(x). */ + +double fp_atan(MPL *mpl, double x) +{ xassert(mpl == mpl); + return atan(x); +} + +/*---------------------------------------------------------------------- +-- fp_atan2 - floating-point trigonometric arctangent. +-- +-- This routine computes the trigonometric arctangent atan(y / x). */ + +double fp_atan2(MPL *mpl, double y, double x) +{ xassert(mpl == mpl); + return atan2(y, x); +} + +/*---------------------------------------------------------------------- +-- fp_round - round floating-point value to n fractional digits. +-- +-- This routine rounds given floating-point value x to n fractional +-- digits with the formula: +-- +-- round(x, n) = floor(x * 10^n + 0.5) / 10^n. +-- +-- The parameter n is assumed to be integer. */ + +double fp_round(MPL *mpl, double x, double n) +{ double ten_to_n; + if (n != floor(n)) + error(mpl, "round(%.*g, %.*g); non-integer second argument", + DBL_DIG, x, DBL_DIG, n); + if (n <= DBL_DIG + 2) + { ten_to_n = pow(10.0, n); + if (fabs(x) < (0.999 * DBL_MAX) / ten_to_n) + { x = floor(x * ten_to_n + 0.5); + if (x != 0.0) x /= ten_to_n; + } + } + return x; +} + +/*---------------------------------------------------------------------- +-- fp_trunc - truncate floating-point value to n fractional digits. +-- +-- This routine truncates given floating-point value x to n fractional +-- digits with the formula: +-- +-- ( floor(x * 10^n) / 10^n, if x >= 0 +-- trunc(x, n) = < +-- ( ceil(x * 10^n) / 10^n, if x < 0 +-- +-- The parameter n is assumed to be integer. */ + +double fp_trunc(MPL *mpl, double x, double n) +{ double ten_to_n; + if (n != floor(n)) + error(mpl, "trunc(%.*g, %.*g); non-integer second argument", + DBL_DIG, x, DBL_DIG, n); + if (n <= DBL_DIG + 2) + { ten_to_n = pow(10.0, n); + if (fabs(x) < (0.999 * DBL_MAX) / ten_to_n) + { x = (x >= 0.0 ? floor(x * ten_to_n) : ceil(x * ten_to_n)); + if (x != 0.0) x /= ten_to_n; + } + } + return x; +} + +/**********************************************************************/ +/* * * PSEUDO-RANDOM NUMBER GENERATORS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- fp_irand224 - pseudo-random integer in the range [0, 2^24). +-- +-- This routine returns a next pseudo-random integer (converted to +-- floating-point) which is uniformly distributed between 0 and 2^24-1, +-- inclusive. */ + +#define two_to_the_24 0x1000000 + +double fp_irand224(MPL *mpl) +{ return + (double)rng_unif_rand(mpl->rand, two_to_the_24); +} + +/*---------------------------------------------------------------------- +-- fp_uniform01 - pseudo-random number in the range [0, 1). +-- +-- This routine returns a next pseudo-random number which is uniformly +-- distributed in the range [0, 1). */ + +#define two_to_the_31 ((unsigned int)0x80000000) + +double fp_uniform01(MPL *mpl) +{ return + (double)rng_next_rand(mpl->rand) / (double)two_to_the_31; +} + +/*---------------------------------------------------------------------- +-- fp_uniform - pseudo-random number in the range [a, b). +-- +-- This routine returns a next pseudo-random number which is uniformly +-- distributed in the range [a, b). */ + +double fp_uniform(MPL *mpl, double a, double b) +{ double x; + if (a >= b) + error(mpl, "Uniform(%.*g, %.*g); invalid range", + DBL_DIG, a, DBL_DIG, b); + x = fp_uniform01(mpl); +#if 0 + x = a * (1.0 - x) + b * x; +#else + x = fp_add(mpl, a * (1.0 - x), b * x); +#endif + return x; +} + +/*---------------------------------------------------------------------- +-- fp_normal01 - Gaussian random variate with mu = 0 and sigma = 1. +-- +-- This routine returns a Gaussian random variate with zero mean and +-- unit standard deviation. The polar (Box-Mueller) method is used. +-- +-- This code is a modified version of the routine gsl_ran_gaussian from +-- the GNU Scientific Library Version 1.0. */ + +double fp_normal01(MPL *mpl) +{ double x, y, r2; + do + { /* choose x, y in uniform square (-1,-1) to (+1,+1) */ + x = -1.0 + 2.0 * fp_uniform01(mpl); + y = -1.0 + 2.0 * fp_uniform01(mpl); + /* see if it is in the unit circle */ + r2 = x * x + y * y; + } while (r2 > 1.0 || r2 == 0.0); + /* Box-Muller transform */ + return y * sqrt(-2.0 * log (r2) / r2); +} + +/*---------------------------------------------------------------------- +-- fp_normal - Gaussian random variate with specified mu and sigma. +-- +-- This routine returns a Gaussian random variate with mean mu and +-- standard deviation sigma. */ + +double fp_normal(MPL *mpl, double mu, double sigma) +{ double x; +#if 0 + x = mu + sigma * fp_normal01(mpl); +#else + x = fp_add(mpl, mu, fp_mul(mpl, sigma, fp_normal01(mpl))); +#endif + return x; +} + +/**********************************************************************/ +/* * * SEGMENTED CHARACTER STRINGS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_string - create character string. +-- +-- This routine creates a segmented character string, which is exactly +-- equivalent to specified character string. */ + +STRING *create_string +( MPL *mpl, + char buf[MAX_LENGTH+1] /* not changed */ +) +#if 0 +{ STRING *head, *tail; + int i, j; + xassert(buf != NULL); + xassert(strlen(buf) <= MAX_LENGTH); + head = tail = dmp_get_atom(mpl->strings, sizeof(STRING)); + for (i = j = 0; ; i++) + { if ((tail->seg[j++] = buf[i]) == '\0') break; + if (j == STRSEG_SIZE) +tail = (tail->next = dmp_get_atom(mpl->strings, sizeof(STRING))), j = 0; + } + tail->next = NULL; + return head; +} +#else +{ STRING *str; + xassert(strlen(buf) <= MAX_LENGTH); + str = dmp_get_atom(mpl->strings, strlen(buf)+1); + strcpy(str, buf); + return str; +} +#endif + +/*---------------------------------------------------------------------- +-- copy_string - make copy of character string. +-- +-- This routine returns an exact copy of segmented character string. */ + +STRING *copy_string +( MPL *mpl, + STRING *str /* not changed */ +) +#if 0 +{ STRING *head, *tail; + xassert(str != NULL); + head = tail = dmp_get_atom(mpl->strings, sizeof(STRING)); + for (; str != NULL; str = str->next) + { memcpy(tail->seg, str->seg, STRSEG_SIZE); + if (str->next != NULL) +tail = (tail->next = dmp_get_atom(mpl->strings, sizeof(STRING))); + } + tail->next = NULL; + return head; +} +#else +{ xassert(mpl == mpl); + return create_string(mpl, str); +} +#endif + +/*---------------------------------------------------------------------- +-- compare_strings - compare one character string with another. +-- +-- This routine compares one segmented character strings with another +-- and returns the result of comparison as follows: +-- +-- = 0 - both strings are identical; +-- < 0 - the first string precedes the second one; +-- > 0 - the first string follows the second one. */ + +int compare_strings +( MPL *mpl, + STRING *str1, /* not changed */ + STRING *str2 /* not changed */ +) +#if 0 +{ int j, c1, c2; + xassert(mpl == mpl); + for (;; str1 = str1->next, str2 = str2->next) + { xassert(str1 != NULL); + xassert(str2 != NULL); + for (j = 0; j < STRSEG_SIZE; j++) + { c1 = (unsigned char)str1->seg[j]; + c2 = (unsigned char)str2->seg[j]; + if (c1 < c2) return -1; + if (c1 > c2) return +1; + if (c1 == '\0') goto done; + } + } +done: return 0; +} +#else +{ xassert(mpl == mpl); + return strcmp(str1, str2); +} +#endif + +/*---------------------------------------------------------------------- +-- fetch_string - extract content of character string. +-- +-- This routine returns a character string, which is exactly equivalent +-- to specified segmented character string. */ + +char *fetch_string +( MPL *mpl, + STRING *str, /* not changed */ + char buf[MAX_LENGTH+1] /* modified */ +) +#if 0 +{ int i, j; + xassert(mpl == mpl); + xassert(buf != NULL); + for (i = 0; ; str = str->next) + { xassert(str != NULL); + for (j = 0; j < STRSEG_SIZE; j++) + if ((buf[i++] = str->seg[j]) == '\0') goto done; + } +done: xassert(strlen(buf) <= MAX_LENGTH); + return buf; +} +#else +{ xassert(mpl == mpl); + return strcpy(buf, str); +} +#endif + +/*---------------------------------------------------------------------- +-- delete_string - delete character string. +-- +-- This routine deletes specified segmented character string. */ + +void delete_string +( MPL *mpl, + STRING *str /* destroyed */ +) +#if 0 +{ STRING *temp; + xassert(str != NULL); + while (str != NULL) + { temp = str; + str = str->next; + dmp_free_atom(mpl->strings, temp, sizeof(STRING)); + } + return; +} +#else +{ dmp_free_atom(mpl->strings, str, strlen(str)+1); + return; +} +#endif + +/**********************************************************************/ +/* * * SYMBOLS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_symbol_num - create symbol of numeric type. +-- +-- This routine creates a symbol, which has a numeric value specified +-- as floating-point number. */ + +SYMBOL *create_symbol_num(MPL *mpl, double num) +{ SYMBOL *sym; + sym = dmp_get_atom(mpl->symbols, sizeof(SYMBOL)); + sym->num = num; + sym->str = NULL; + return sym; +} + +/*---------------------------------------------------------------------- +-- create_symbol_str - create symbol of abstract type. +-- +-- This routine creates a symbol, which has an abstract value specified +-- as segmented character string. */ + +SYMBOL *create_symbol_str +( MPL *mpl, + STRING *str /* destroyed */ +) +{ SYMBOL *sym; + xassert(str != NULL); + sym = dmp_get_atom(mpl->symbols, sizeof(SYMBOL)); + sym->num = 0.0; + sym->str = str; + return sym; +} + +/*---------------------------------------------------------------------- +-- copy_symbol - make copy of symbol. +-- +-- This routine returns an exact copy of symbol. */ + +SYMBOL *copy_symbol +( MPL *mpl, + SYMBOL *sym /* not changed */ +) +{ SYMBOL *copy; + xassert(sym != NULL); + copy = dmp_get_atom(mpl->symbols, sizeof(SYMBOL)); + if (sym->str == NULL) + { copy->num = sym->num; + copy->str = NULL; + } + else + { copy->num = 0.0; + copy->str = copy_string(mpl, sym->str); + } + return copy; +} + +/*---------------------------------------------------------------------- +-- compare_symbols - compare one symbol with another. +-- +-- This routine compares one symbol with another and returns the result +-- of comparison as follows: +-- +-- = 0 - both symbols are identical; +-- < 0 - the first symbol precedes the second one; +-- > 0 - the first symbol follows the second one. +-- +-- Note that the linear order, in which symbols follow each other, is +-- implementation-dependent. It may be not an alphabetical order. */ + +int compare_symbols +( MPL *mpl, + SYMBOL *sym1, /* not changed */ + SYMBOL *sym2 /* not changed */ +) +{ xassert(sym1 != NULL); + xassert(sym2 != NULL); + /* let all numeric quantities precede all symbolic quantities */ + if (sym1->str == NULL && sym2->str == NULL) + { if (sym1->num < sym2->num) return -1; + if (sym1->num > sym2->num) return +1; + return 0; + } + if (sym1->str == NULL) return -1; + if (sym2->str == NULL) return +1; + return compare_strings(mpl, sym1->str, sym2->str); +} + +/*---------------------------------------------------------------------- +-- delete_symbol - delete symbol. +-- +-- This routine deletes specified symbol. */ + +void delete_symbol +( MPL *mpl, + SYMBOL *sym /* destroyed */ +) +{ xassert(sym != NULL); + if (sym->str != NULL) delete_string(mpl, sym->str); + dmp_free_atom(mpl->symbols, sym, sizeof(SYMBOL)); + return; +} + +/*---------------------------------------------------------------------- +-- format_symbol - format symbol for displaying or printing. +-- +-- This routine converts specified symbol to a charater string, which +-- is suitable for displaying or printing. +-- +-- The resultant string is never longer than 255 characters. If it gets +-- longer, it is truncated from the right and appended by dots. */ + +char *format_symbol +( MPL *mpl, + SYMBOL *sym /* not changed */ +) +{ char *buf = mpl->sym_buf; + xassert(sym != NULL); + if (sym->str == NULL) + sprintf(buf, "%.*g", DBL_DIG, sym->num); + else + { char str[MAX_LENGTH+1]; + int quoted, j, len; + fetch_string(mpl, sym->str, str); + if (!(isalpha((unsigned char)str[0]) || str[0] == '_')) + quoted = 1; + else + { quoted = 0; + for (j = 1; str[j] != '\0'; j++) + { if (!(isalnum((unsigned char)str[j]) || + strchr("+-._", (unsigned char)str[j]) != NULL)) + { quoted = 1; + break; + } + } + } +# define safe_append(c) \ + (void)(len < 255 ? (buf[len++] = (char)(c)) : 0) + buf[0] = '\0', len = 0; + if (quoted) safe_append('\''); + for (j = 0; str[j] != '\0'; j++) + { if (quoted && str[j] == '\'') safe_append('\''); + safe_append(str[j]); + } + if (quoted) safe_append('\''); +# undef safe_append + buf[len] = '\0'; + if (len == 255) strcpy(buf+252, "..."); + } + xassert(strlen(buf) <= 255); + return buf; +} + +/*---------------------------------------------------------------------- +-- concat_symbols - concatenate one symbol with another. +-- +-- This routine concatenates values of two given symbols and assigns +-- the resultant character string to a new symbol, which is returned on +-- exit. Both original symbols are destroyed. */ + +SYMBOL *concat_symbols +( MPL *mpl, + SYMBOL *sym1, /* destroyed */ + SYMBOL *sym2 /* destroyed */ +) +{ char str1[MAX_LENGTH+1], str2[MAX_LENGTH+1]; + xassert(MAX_LENGTH >= DBL_DIG + DBL_DIG); + if (sym1->str == NULL) + sprintf(str1, "%.*g", DBL_DIG, sym1->num); + else + fetch_string(mpl, sym1->str, str1); + if (sym2->str == NULL) + sprintf(str2, "%.*g", DBL_DIG, sym2->num); + else + fetch_string(mpl, sym2->str, str2); + if (strlen(str1) + strlen(str2) > MAX_LENGTH) + { char buf[255+1]; + strcpy(buf, format_symbol(mpl, sym1)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s & %s; resultant symbol exceeds %d characters", + buf, format_symbol(mpl, sym2), MAX_LENGTH); + } + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + return create_symbol_str(mpl, create_string(mpl, strcat(str1, + str2))); +} + +/**********************************************************************/ +/* * * N-TUPLES * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_tuple - create n-tuple. +-- +-- This routine creates a n-tuple, which initially has no components, +-- i.e. which is 0-tuple. */ + +TUPLE *create_tuple(MPL *mpl) +{ TUPLE *tuple; + xassert(mpl == mpl); + tuple = NULL; + return tuple; +} + +/*---------------------------------------------------------------------- +-- expand_tuple - append symbol to n-tuple. +-- +-- This routine expands n-tuple appending to it a given symbol, which +-- becomes its new last component. */ + +TUPLE *expand_tuple +( MPL *mpl, + TUPLE *tuple, /* destroyed */ + SYMBOL *sym /* destroyed */ +) +{ TUPLE *tail, *temp; + xassert(sym != NULL); + /* create a new component */ + tail = dmp_get_atom(mpl->tuples, sizeof(TUPLE)); + tail->sym = sym; + tail->next = NULL; + /* and append it to the component list */ + if (tuple == NULL) + tuple = tail; + else + { for (temp = tuple; temp->next != NULL; temp = temp->next); + temp->next = tail; + } + return tuple; +} + +/*---------------------------------------------------------------------- +-- tuple_dimen - determine dimension of n-tuple. +-- +-- This routine returns dimension of n-tuple, i.e. number of components +-- in the n-tuple. */ + +int tuple_dimen +( MPL *mpl, + TUPLE *tuple /* not changed */ +) +{ TUPLE *temp; + int dim = 0; + xassert(mpl == mpl); + for (temp = tuple; temp != NULL; temp = temp->next) dim++; + return dim; +} + +/*---------------------------------------------------------------------- +-- copy_tuple - make copy of n-tuple. +-- +-- This routine returns an exact copy of n-tuple. */ + +TUPLE *copy_tuple +( MPL *mpl, + TUPLE *tuple /* not changed */ +) +{ TUPLE *head, *tail; + if (tuple == NULL) + head = NULL; + else + { head = tail = dmp_get_atom(mpl->tuples, sizeof(TUPLE)); + for (; tuple != NULL; tuple = tuple->next) + { xassert(tuple->sym != NULL); + tail->sym = copy_symbol(mpl, tuple->sym); + if (tuple->next != NULL) +tail = (tail->next = dmp_get_atom(mpl->tuples, sizeof(TUPLE))); + } + tail->next = NULL; + } + return head; +} + +/*---------------------------------------------------------------------- +-- compare_tuples - compare one n-tuple with another. +-- +-- This routine compares two given n-tuples, which must have the same +-- dimension (not checked for the sake of efficiency), and returns one +-- of the following codes: +-- +-- = 0 - both n-tuples are identical; +-- < 0 - the first n-tuple precedes the second one; +-- > 0 - the first n-tuple follows the second one. +-- +-- Note that the linear order, in which n-tuples follow each other, is +-- implementation-dependent. It may be not an alphabetical order. */ + +int compare_tuples +( MPL *mpl, + TUPLE *tuple1, /* not changed */ + TUPLE *tuple2 /* not changed */ +) +{ TUPLE *item1, *item2; + int ret; + xassert(mpl == mpl); + for (item1 = tuple1, item2 = tuple2; item1 != NULL; + item1 = item1->next, item2 = item2->next) + { xassert(item2 != NULL); + xassert(item1->sym != NULL); + xassert(item2->sym != NULL); + ret = compare_symbols(mpl, item1->sym, item2->sym); + if (ret != 0) return ret; + } + xassert(item2 == NULL); + return 0; +} + +/*---------------------------------------------------------------------- +-- build_subtuple - build subtuple of given n-tuple. +-- +-- This routine builds subtuple, which consists of first dim components +-- of given n-tuple. */ + +TUPLE *build_subtuple +( MPL *mpl, + TUPLE *tuple, /* not changed */ + int dim +) +{ TUPLE *head, *temp; + int j; + head = create_tuple(mpl); + for (j = 1, temp = tuple; j <= dim; j++, temp = temp->next) + { xassert(temp != NULL); + head = expand_tuple(mpl, head, copy_symbol(mpl, temp->sym)); + } + return head; +} + +/*---------------------------------------------------------------------- +-- delete_tuple - delete n-tuple. +-- +-- This routine deletes specified n-tuple. */ + +void delete_tuple +( MPL *mpl, + TUPLE *tuple /* destroyed */ +) +{ TUPLE *temp; + while (tuple != NULL) + { temp = tuple; + tuple = temp->next; + xassert(temp->sym != NULL); + delete_symbol(mpl, temp->sym); + dmp_free_atom(mpl->tuples, temp, sizeof(TUPLE)); + } + return; +} + +/*---------------------------------------------------------------------- +-- format_tuple - format n-tuple for displaying or printing. +-- +-- This routine converts specified n-tuple to a character string, which +-- is suitable for displaying or printing. +-- +-- The resultant string is never longer than 255 characters. If it gets +-- longer, it is truncated from the right and appended by dots. */ + +char *format_tuple +( MPL *mpl, + int c, + TUPLE *tuple /* not changed */ +) +{ TUPLE *temp; + int dim, j, len; + char *buf = mpl->tup_buf, str[255+1], *save; +# define safe_append(c) \ + (void)(len < 255 ? (buf[len++] = (char)(c)) : 0) + buf[0] = '\0', len = 0; + dim = tuple_dimen(mpl, tuple); + if (c == '[' && dim > 0) safe_append('['); + if (c == '(' && dim > 1) safe_append('('); + for (temp = tuple; temp != NULL; temp = temp->next) + { if (temp != tuple) safe_append(','); + xassert(temp->sym != NULL); + save = mpl->sym_buf; + mpl->sym_buf = str; + format_symbol(mpl, temp->sym); + mpl->sym_buf = save; + xassert(strlen(str) < sizeof(str)); + for (j = 0; str[j] != '\0'; j++) safe_append(str[j]); + } + if (c == '[' && dim > 0) safe_append(']'); + if (c == '(' && dim > 1) safe_append(')'); +# undef safe_append + buf[len] = '\0'; + if (len == 255) strcpy(buf+252, "..."); + xassert(strlen(buf) <= 255); + return buf; +} + +/**********************************************************************/ +/* * * ELEMENTAL SETS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_elemset - create elemental set. +-- +-- This routine creates an elemental set, whose members are n-tuples of +-- specified dimension. Being created the set is initially empty. */ + +ELEMSET *create_elemset(MPL *mpl, int dim) +{ ELEMSET *set; + xassert(dim > 0); + set = create_array(mpl, A_NONE, dim); + return set; +} + +/*---------------------------------------------------------------------- +-- find_tuple - check if elemental set contains given n-tuple. +-- +-- This routine finds given n-tuple in specified elemental set in order +-- to check if the set contains that n-tuple. If the n-tuple is found, +-- the routine returns pointer to corresponding array member. Otherwise +-- null pointer is returned. */ + +MEMBER *find_tuple +( MPL *mpl, + ELEMSET *set, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ xassert(set != NULL); + xassert(set->type == A_NONE); + xassert(set->dim == tuple_dimen(mpl, tuple)); + return find_member(mpl, set, tuple); +} + +/*---------------------------------------------------------------------- +-- add_tuple - add new n-tuple to elemental set. +-- +-- This routine adds given n-tuple to specified elemental set. +-- +-- For the sake of efficiency this routine doesn't check whether the +-- set already contains the same n-tuple or not. Therefore the calling +-- program should use the routine find_tuple (if necessary) in order to +-- make sure that the given n-tuple is not contained in the set, since +-- duplicate n-tuples within the same set are not allowed. */ + +MEMBER *add_tuple +( MPL *mpl, + ELEMSET *set, /* modified */ + TUPLE *tuple /* destroyed */ +) +{ MEMBER *memb; + xassert(set != NULL); + xassert(set->type == A_NONE); + xassert(set->dim == tuple_dimen(mpl, tuple)); + memb = add_member(mpl, set, tuple); + memb->value.none = NULL; + return memb; +} + +/*---------------------------------------------------------------------- +-- check_then_add - check and add new n-tuple to elemental set. +-- +-- This routine is equivalent to the routine add_tuple except that it +-- does check for duplicate n-tuples. */ + +MEMBER *check_then_add +( MPL *mpl, + ELEMSET *set, /* modified */ + TUPLE *tuple /* destroyed */ +) +{ if (find_tuple(mpl, set, tuple) != NULL) + error(mpl, "duplicate tuple %s detected", format_tuple(mpl, + '(', tuple)); + return add_tuple(mpl, set, tuple); +} + +/*---------------------------------------------------------------------- +-- copy_elemset - make copy of elemental set. +-- +-- This routine makes an exact copy of elemental set. */ + +ELEMSET *copy_elemset +( MPL *mpl, + ELEMSET *set /* not changed */ +) +{ ELEMSET *copy; + MEMBER *memb; + xassert(set != NULL); + xassert(set->type == A_NONE); + xassert(set->dim > 0); + copy = create_elemset(mpl, set->dim); + for (memb = set->head; memb != NULL; memb = memb->next) + add_tuple(mpl, copy, copy_tuple(mpl, memb->tuple)); + return copy; +} + +/*---------------------------------------------------------------------- +-- delete_elemset - delete elemental set. +-- +-- This routine deletes specified elemental set. */ + +void delete_elemset +( MPL *mpl, + ELEMSET *set /* destroyed */ +) +{ xassert(set != NULL); + xassert(set->type == A_NONE); + delete_array(mpl, set); + return; +} + +/*---------------------------------------------------------------------- +-- arelset_size - compute size of "arithmetic" elemental set. +-- +-- This routine computes the size of "arithmetic" elemental set, which +-- is specified in the form of arithmetic progression: +-- +-- { t0 .. tf by dt }. +-- +-- The size is computed using the formula: +-- +-- n = max(0, floor((tf - t0) / dt) + 1). */ + +int arelset_size(MPL *mpl, double t0, double tf, double dt) +{ double temp; + if (dt == 0.0) + error(mpl, "%.*g .. %.*g by %.*g; zero stride not allowed", + DBL_DIG, t0, DBL_DIG, tf, DBL_DIG, dt); + if (tf > 0.0 && t0 < 0.0 && tf > + 0.999 * DBL_MAX + t0) + temp = +DBL_MAX; + else if (tf < 0.0 && t0 > 0.0 && tf < - 0.999 * DBL_MAX + t0) + temp = -DBL_MAX; + else + temp = tf - t0; + if (fabs(dt) < 1.0 && fabs(temp) > (0.999 * DBL_MAX) * fabs(dt)) + { if (temp > 0.0 && dt > 0.0 || temp < 0.0 && dt < 0.0) + temp = +DBL_MAX; + else + temp = 0.0; + } + else + { temp = floor(temp / dt) + 1.0; + if (temp < 0.0) temp = 0.0; + } + xassert(temp >= 0.0); + if (temp > (double)(INT_MAX - 1)) + error(mpl, "%.*g .. %.*g by %.*g; set too large", + DBL_DIG, t0, DBL_DIG, tf, DBL_DIG, dt); + return (int)(temp + 0.5); +} + +/*---------------------------------------------------------------------- +-- arelset_member - compute member of "arithmetic" elemental set. +-- +-- This routine returns a numeric value of symbol, which is equivalent +-- to j-th member of given "arithmetic" elemental set specified in the +-- form of arithmetic progression: +-- +-- { t0 .. tf by dt }. +-- +-- The symbol value is computed with the formula: +-- +-- j-th member = t0 + (j - 1) * dt, +-- +-- The number j must satisfy to the restriction 1 <= j <= n, where n is +-- the set size computed by the routine arelset_size. */ + +double arelset_member(MPL *mpl, double t0, double tf, double dt, int j) +{ xassert(1 <= j && j <= arelset_size(mpl, t0, tf, dt)); + return t0 + (double)(j - 1) * dt; +} + +/*---------------------------------------------------------------------- +-- create_arelset - create "arithmetic" elemental set. +-- +-- This routine creates "arithmetic" elemental set, which is specified +-- in the form of arithmetic progression: +-- +-- { t0 .. tf by dt }. +-- +-- Components of this set are 1-tuples. */ + +ELEMSET *create_arelset(MPL *mpl, double t0, double tf, double dt) +{ ELEMSET *set; + int j, n; + set = create_elemset(mpl, 1); + n = arelset_size(mpl, t0, tf, dt); + for (j = 1; j <= n; j++) + { add_tuple + ( mpl, + set, + expand_tuple + ( mpl, + create_tuple(mpl), + create_symbol_num + ( mpl, + arelset_member(mpl, t0, tf, dt, j) + ) + ) + ); + } + return set; +} + +/*---------------------------------------------------------------------- +-- set_union - union of two elemental sets. +-- +-- This routine computes the union: +-- +-- X U Y = { j | (j in X) or (j in Y) }, +-- +-- where X and Y are given elemental sets (destroyed on exit). */ + +ELEMSET *set_union +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +) +{ MEMBER *memb; + xassert(X != NULL); + xassert(X->type == A_NONE); + xassert(X->dim > 0); + xassert(Y != NULL); + xassert(Y->type == A_NONE); + xassert(Y->dim > 0); + xassert(X->dim == Y->dim); + for (memb = Y->head; memb != NULL; memb = memb->next) + { if (find_tuple(mpl, X, memb->tuple) == NULL) + add_tuple(mpl, X, copy_tuple(mpl, memb->tuple)); + } + delete_elemset(mpl, Y); + return X; +} + +/*---------------------------------------------------------------------- +-- set_diff - difference between two elemental sets. +-- +-- This routine computes the difference: +-- +-- X \ Y = { j | (j in X) and (j not in Y) }, +-- +-- where X and Y are given elemental sets (destroyed on exit). */ + +ELEMSET *set_diff +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +) +{ ELEMSET *Z; + MEMBER *memb; + xassert(X != NULL); + xassert(X->type == A_NONE); + xassert(X->dim > 0); + xassert(Y != NULL); + xassert(Y->type == A_NONE); + xassert(Y->dim > 0); + xassert(X->dim == Y->dim); + Z = create_elemset(mpl, X->dim); + for (memb = X->head; memb != NULL; memb = memb->next) + { if (find_tuple(mpl, Y, memb->tuple) == NULL) + add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); + } + delete_elemset(mpl, X); + delete_elemset(mpl, Y); + return Z; +} + +/*---------------------------------------------------------------------- +-- set_symdiff - symmetric difference between two elemental sets. +-- +-- This routine computes the symmetric difference: +-- +-- X (+) Y = (X \ Y) U (Y \ X), +-- +-- where X and Y are given elemental sets (destroyed on exit). */ + +ELEMSET *set_symdiff +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +) +{ ELEMSET *Z; + MEMBER *memb; + xassert(X != NULL); + xassert(X->type == A_NONE); + xassert(X->dim > 0); + xassert(Y != NULL); + xassert(Y->type == A_NONE); + xassert(Y->dim > 0); + xassert(X->dim == Y->dim); + /* Z := X \ Y */ + Z = create_elemset(mpl, X->dim); + for (memb = X->head; memb != NULL; memb = memb->next) + { if (find_tuple(mpl, Y, memb->tuple) == NULL) + add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); + } + /* Z := Z U (Y \ X) */ + for (memb = Y->head; memb != NULL; memb = memb->next) + { if (find_tuple(mpl, X, memb->tuple) == NULL) + add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); + } + delete_elemset(mpl, X); + delete_elemset(mpl, Y); + return Z; +} + +/*---------------------------------------------------------------------- +-- set_inter - intersection of two elemental sets. +-- +-- This routine computes the intersection: +-- +-- X ^ Y = { j | (j in X) and (j in Y) }, +-- +-- where X and Y are given elemental sets (destroyed on exit). */ + +ELEMSET *set_inter +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +) +{ ELEMSET *Z; + MEMBER *memb; + xassert(X != NULL); + xassert(X->type == A_NONE); + xassert(X->dim > 0); + xassert(Y != NULL); + xassert(Y->type == A_NONE); + xassert(Y->dim > 0); + xassert(X->dim == Y->dim); + Z = create_elemset(mpl, X->dim); + for (memb = X->head; memb != NULL; memb = memb->next) + { if (find_tuple(mpl, Y, memb->tuple) != NULL) + add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); + } + delete_elemset(mpl, X); + delete_elemset(mpl, Y); + return Z; +} + +/*---------------------------------------------------------------------- +-- set_cross - cross (Cartesian) product of two elemental sets. +-- +-- This routine computes the cross (Cartesian) product: +-- +-- X x Y = { (i,j) | (i in X) and (j in Y) }, +-- +-- where X and Y are given elemental sets (destroyed on exit). */ + +ELEMSET *set_cross +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +) +{ ELEMSET *Z; + MEMBER *memx, *memy; + TUPLE *tuple, *temp; + xassert(X != NULL); + xassert(X->type == A_NONE); + xassert(X->dim > 0); + xassert(Y != NULL); + xassert(Y->type == A_NONE); + xassert(Y->dim > 0); + Z = create_elemset(mpl, X->dim + Y->dim); + for (memx = X->head; memx != NULL; memx = memx->next) + { for (memy = Y->head; memy != NULL; memy = memy->next) + { tuple = copy_tuple(mpl, memx->tuple); + for (temp = memy->tuple; temp != NULL; temp = temp->next) + tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, + temp->sym)); + add_tuple(mpl, Z, tuple); + } + } + delete_elemset(mpl, X); + delete_elemset(mpl, Y); + return Z; +} + +/**********************************************************************/ +/* * * ELEMENTAL VARIABLES * * */ +/**********************************************************************/ + +/* (there are no specific routines for elemental variables) */ + +/**********************************************************************/ +/* * * LINEAR FORMS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- constant_term - create constant term. +-- +-- This routine creates the linear form, which is a constant term. */ + +FORMULA *constant_term(MPL *mpl, double coef) +{ FORMULA *form; + if (coef == 0.0) + form = NULL; + else + { form = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + form->coef = coef; + form->var = NULL; + form->next = NULL; + } + return form; +} + +/*---------------------------------------------------------------------- +-- single_variable - create single variable. +-- +-- This routine creates the linear form, which is a single elemental +-- variable. */ + +FORMULA *single_variable +( MPL *mpl, + ELEMVAR *var /* referenced */ +) +{ FORMULA *form; + xassert(var != NULL); + form = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + form->coef = 1.0; + form->var = var; + form->next = NULL; + return form; +} + +/*---------------------------------------------------------------------- +-- copy_formula - make copy of linear form. +-- +-- This routine returns an exact copy of linear form. */ + +FORMULA *copy_formula +( MPL *mpl, + FORMULA *form /* not changed */ +) +{ FORMULA *head, *tail; + if (form == NULL) + head = NULL; + else + { head = tail = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + for (; form != NULL; form = form->next) + { tail->coef = form->coef; + tail->var = form->var; + if (form->next != NULL) +tail = (tail->next = dmp_get_atom(mpl->formulae, sizeof(FORMULA))); + } + tail->next = NULL; + } + return head; +} + +/*---------------------------------------------------------------------- +-- delete_formula - delete linear form. +-- +-- This routine deletes specified linear form. */ + +void delete_formula +( MPL *mpl, + FORMULA *form /* destroyed */ +) +{ FORMULA *temp; + while (form != NULL) + { temp = form; + form = form->next; + dmp_free_atom(mpl->formulae, temp, sizeof(FORMULA)); + } + return; +} + +/*---------------------------------------------------------------------- +-- linear_comb - linear combination of two linear forms. +-- +-- This routine computes the linear combination: +-- +-- a * fx + b * fy, +-- +-- where a and b are numeric coefficients, fx and fy are linear forms +-- (destroyed on exit). */ + +FORMULA *linear_comb +( MPL *mpl, + double a, FORMULA *fx, /* destroyed */ + double b, FORMULA *fy /* destroyed */ +) +{ FORMULA *form = NULL, *term, *temp; + double c0 = 0.0; + for (term = fx; term != NULL; term = term->next) + { if (term->var == NULL) + c0 = fp_add(mpl, c0, fp_mul(mpl, a, term->coef)); + else + term->var->temp = + fp_add(mpl, term->var->temp, fp_mul(mpl, a, term->coef)); + } + for (term = fy; term != NULL; term = term->next) + { if (term->var == NULL) + c0 = fp_add(mpl, c0, fp_mul(mpl, b, term->coef)); + else + term->var->temp = + fp_add(mpl, term->var->temp, fp_mul(mpl, b, term->coef)); + } + for (term = fx; term != NULL; term = term->next) + { if (term->var != NULL && term->var->temp != 0.0) + { temp = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + temp->coef = term->var->temp, temp->var = term->var; + temp->next = form, form = temp; + term->var->temp = 0.0; + } + } + for (term = fy; term != NULL; term = term->next) + { if (term->var != NULL && term->var->temp != 0.0) + { temp = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + temp->coef = term->var->temp, temp->var = term->var; + temp->next = form, form = temp; + term->var->temp = 0.0; + } + } + if (c0 != 0.0) + { temp = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + temp->coef = c0, temp->var = NULL; + temp->next = form, form = temp; + } + delete_formula(mpl, fx); + delete_formula(mpl, fy); + return form; +} + +/*---------------------------------------------------------------------- +-- remove_constant - remove constant term from linear form. +-- +-- This routine removes constant term from linear form and stores its +-- value to given location. */ + +FORMULA *remove_constant +( MPL *mpl, + FORMULA *form, /* destroyed */ + double *coef /* modified */ +) +{ FORMULA *head = NULL, *temp; + *coef = 0.0; + while (form != NULL) + { temp = form; + form = form->next; + if (temp->var == NULL) + { /* constant term */ + *coef = fp_add(mpl, *coef, temp->coef); + dmp_free_atom(mpl->formulae, temp, sizeof(FORMULA)); + } + else + { /* linear term */ + temp->next = head; + head = temp; + } + } + return head; +} + +/*---------------------------------------------------------------------- +-- reduce_terms - reduce identical terms in linear form. +-- +-- This routine reduces identical terms in specified linear form. */ + +FORMULA *reduce_terms +( MPL *mpl, + FORMULA *form /* destroyed */ +) +{ FORMULA *term, *next_term; + double c0 = 0.0; + for (term = form; term != NULL; term = term->next) + { if (term->var == NULL) + c0 = fp_add(mpl, c0, term->coef); + else + term->var->temp = fp_add(mpl, term->var->temp, term->coef); + } + next_term = form, form = NULL; + for (term = next_term; term != NULL; term = next_term) + { next_term = term->next; + if (term->var == NULL && c0 != 0.0) + { term->coef = c0, c0 = 0.0; + term->next = form, form = term; + } + else if (term->var != NULL && term->var->temp != 0.0) + { term->coef = term->var->temp, term->var->temp = 0.0; + term->next = form, form = term; + } + else + dmp_free_atom(mpl->formulae, term, sizeof(FORMULA)); + } + return form; +} + +/**********************************************************************/ +/* * * ELEMENTAL CONSTRAINTS * * */ +/**********************************************************************/ + +/* (there are no specific routines for elemental constraints) */ + +/**********************************************************************/ +/* * * GENERIC VALUES * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- delete_value - delete generic value. +-- +-- This routine deletes specified generic value. +-- +-- NOTE: The generic value to be deleted must be valid. */ + +void delete_value +( MPL *mpl, + int type, + VALUE *value /* content destroyed */ +) +{ xassert(value != NULL); + switch (type) + { case A_NONE: + value->none = NULL; + break; + case A_NUMERIC: + value->num = 0.0; + break; + case A_SYMBOLIC: + delete_symbol(mpl, value->sym), value->sym = NULL; + break; + case A_LOGICAL: + value->bit = 0; + break; + case A_TUPLE: + delete_tuple(mpl, value->tuple), value->tuple = NULL; + break; + case A_ELEMSET: + delete_elemset(mpl, value->set), value->set = NULL; + break; + case A_ELEMVAR: + value->var = NULL; + break; + case A_FORMULA: + delete_formula(mpl, value->form), value->form = NULL; + break; + case A_ELEMCON: + value->con = NULL; + break; + default: + xassert(type != type); + } + return; +} + +/**********************************************************************/ +/* * * SYMBOLICALLY INDEXED ARRAYS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_array - create array. +-- +-- This routine creates an array of specified type and dimension. Being +-- created the array is initially empty. +-- +-- The type indicator determines generic values, which can be assigned +-- to the array members: +-- +-- A_NONE - none (members have no assigned values) +-- A_NUMERIC - floating-point numbers +-- A_SYMBOLIC - symbols +-- A_ELEMSET - elemental sets +-- A_ELEMVAR - elemental variables +-- A_ELEMCON - elemental constraints +-- +-- The dimension may be 0, in which case the array consists of the only +-- member (such arrays represent 0-dimensional objects). */ + +ARRAY *create_array(MPL *mpl, int type, int dim) +{ ARRAY *array; + xassert(type == A_NONE || type == A_NUMERIC || + type == A_SYMBOLIC || type == A_ELEMSET || + type == A_ELEMVAR || type == A_ELEMCON); + xassert(dim >= 0); + array = dmp_get_atom(mpl->arrays, sizeof(ARRAY)); + array->type = type; + array->dim = dim; + array->size = 0; + array->head = NULL; + array->tail = NULL; + array->tree = NULL; + array->prev = NULL; + array->next = mpl->a_list; + /* include the array in the global array list */ + if (array->next != NULL) array->next->prev = array; + mpl->a_list = array; + return array; +} + +/*---------------------------------------------------------------------- +-- find_member - find array member with given n-tuple. +-- +-- This routine finds an array member, which has given n-tuple. If the +-- array is short, the linear search is used. Otherwise the routine +-- autimatically creates the search tree (i.e. the array index) to find +-- members for logarithmic time. */ + +static int compare_member_tuples(void *info, const void *key1, + const void *key2) +{ /* this is an auxiliary routine used to compare keys, which are + n-tuples assigned to array members */ + return compare_tuples((MPL *)info, (TUPLE *)key1, (TUPLE *)key2); +} + +MEMBER *find_member +( MPL *mpl, + ARRAY *array, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + xassert(array != NULL); + /* the n-tuple must have the same dimension as the array */ + xassert(tuple_dimen(mpl, tuple) == array->dim); + /* if the array is large enough, create the search tree and index + all existing members of the array */ + if (array->size > 30 && array->tree == NULL) + { array->tree = avl_create_tree(compare_member_tuples, mpl); + for (memb = array->head; memb != NULL; memb = memb->next) +avl_set_node_link(avl_insert_node(array->tree, memb->tuple), + (void *)memb); + } + /* find a member, which has the given tuple */ + if (array->tree == NULL) + { /* the search tree doesn't exist; use the linear search */ + for (memb = array->head; memb != NULL; memb = memb->next) + if (compare_tuples(mpl, memb->tuple, tuple) == 0) break; + } + else + { /* the search tree exists; use the binary search */ + AVLNODE *node; + node = avl_find_node(array->tree, tuple); +memb = (MEMBER *)(node == NULL ? NULL : avl_get_node_link(node)); + } + return memb; +} + +/*---------------------------------------------------------------------- +-- add_member - add new member to array. +-- +-- This routine creates a new member with given n-tuple and adds it to +-- specified array. +-- +-- For the sake of efficiency this routine doesn't check whether the +-- array already contains a member with the given n-tuple or not. Thus, +-- if necessary, the calling program should use the routine find_member +-- in order to be sure that the array contains no member with the same +-- n-tuple, because members with duplicate n-tuples are not allowed. +-- +-- This routine assigns no generic value to the new member, because the +-- calling program must do that. */ + +MEMBER *add_member +( MPL *mpl, + ARRAY *array, /* modified */ + TUPLE *tuple /* destroyed */ +) +{ MEMBER *memb; + xassert(array != NULL); + /* the n-tuple must have the same dimension as the array */ + xassert(tuple_dimen(mpl, tuple) == array->dim); + /* create new member */ + memb = dmp_get_atom(mpl->members, sizeof(MEMBER)); + memb->tuple = tuple; + memb->next = NULL; + memset(&memb->value, '?', sizeof(VALUE)); + /* and append it to the member list */ + array->size++; + if (array->head == NULL) + array->head = memb; + else + array->tail->next = memb; + array->tail = memb; + /* if the search tree exists, index the new member */ + if (array->tree != NULL) +avl_set_node_link(avl_insert_node(array->tree, memb->tuple), + (void *)memb); + return memb; +} + +/*---------------------------------------------------------------------- +-- delete_array - delete array. +-- +-- This routine deletes specified array. +-- +-- Generic values assigned to the array members are not deleted by this +-- routine. The calling program itself must delete all assigned generic +-- values before deleting the array. */ + +void delete_array +( MPL *mpl, + ARRAY *array /* destroyed */ +) +{ MEMBER *memb; + xassert(array != NULL); + /* delete all existing array members */ + while (array->head != NULL) + { memb = array->head; + array->head = memb->next; + delete_tuple(mpl, memb->tuple); + dmp_free_atom(mpl->members, memb, sizeof(MEMBER)); + } + /* if the search tree exists, also delete it */ + if (array->tree != NULL) avl_delete_tree(array->tree); + /* remove the array from the global array list */ + if (array->prev == NULL) + mpl->a_list = array->next; + else + array->prev->next = array->next; + if (array->next == NULL) + ; + else + array->next->prev = array->prev; + /* delete the array descriptor */ + dmp_free_atom(mpl->arrays, array, sizeof(ARRAY)); + return; +} + +/**********************************************************************/ +/* * * DOMAINS AND DUMMY INDICES * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- assign_dummy_index - assign new value to dummy index. +-- +-- This routine assigns new value to specified dummy index and, that is +-- important, invalidates all temporary resultant values, which depends +-- on that dummy index. */ + +void assign_dummy_index +( MPL *mpl, + DOMAIN_SLOT *slot, /* modified */ + SYMBOL *value /* not changed */ +) +{ CODE *leaf, *code; + xassert(slot != NULL); + xassert(value != NULL); + /* delete the current value assigned to the dummy index */ + if (slot->value != NULL) + { /* if the current value and the new one are identical, actual + assignment is not needed */ + if (compare_symbols(mpl, slot->value, value) == 0) goto done; + /* delete a symbol, which is the current value */ + delete_symbol(mpl, slot->value), slot->value = NULL; + } + /* now walk through all the pseudo-codes with op = O_INDEX, which + refer to the dummy index to be changed (these pseudo-codes are + leaves in the forest of *all* expressions in the database) */ + for (leaf = slot->list; leaf != NULL; leaf = leaf->arg.index. + next) + { xassert(leaf->op == O_INDEX); + /* invalidate all resultant values, which depend on the dummy + index, walking from the current leaf toward the root of the + corresponding expression tree */ + for (code = leaf; code != NULL; code = code->up) + { if (code->valid) + { /* invalidate and delete resultant value */ + code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + } + } + /* assign new value to the dummy index */ + slot->value = copy_symbol(mpl, value); +done: return; +} + +/*---------------------------------------------------------------------- +-- update_dummy_indices - update current values of dummy indices. +-- +-- This routine assigns components of "backup" n-tuple to dummy indices +-- of specified domain block. If no "backup" n-tuple is defined for the +-- domain block, values of the dummy indices remain untouched. */ + +void update_dummy_indices +( MPL *mpl, + DOMAIN_BLOCK *block /* not changed */ +) +{ DOMAIN_SLOT *slot; + TUPLE *temp; + if (block->backup != NULL) + { for (slot = block->list, temp = block->backup; slot != NULL; + slot = slot->next, temp = temp->next) + { xassert(temp != NULL); + xassert(temp->sym != NULL); + assign_dummy_index(mpl, slot, temp->sym); + } + } + return; +} + +/*---------------------------------------------------------------------- +-- enter_domain_block - enter domain block. +-- +-- Let specified domain block have the form: +-- +-- { ..., (j1, j2, ..., jn) in J, ... } +-- +-- where j1, j2, ..., jn are dummy indices, J is a basic set. +-- +-- This routine does the following: +-- +-- 1. Checks if the given n-tuple is a member of the basic set J. Note +-- that J being *out of the scope* of the domain block cannot depend +-- on the dummy indices in the same and inner domain blocks, so it +-- can be computed before the dummy indices are assigned new values. +-- If this check fails, the routine returns with non-zero code. +-- +-- 2. Saves current values of the dummy indices j1, j2, ..., jn. +-- +-- 3. Assigns new values, which are components of the given n-tuple, to +-- the dummy indices j1, j2, ..., jn. If dimension of the n-tuple is +-- larger than n, its extra components n+1, n+2, ... are not used. +-- +-- 4. Calls the formal routine func which either enters the next domain +-- block or evaluates some code within the domain scope. +-- +-- 5. Restores former values of the dummy indices j1, j2, ..., jn. +-- +-- Since current values assigned to the dummy indices on entry to this +-- routine are restored on exit, the formal routine func is allowed to +-- call this routine recursively. */ + +int enter_domain_block +( MPL *mpl, + DOMAIN_BLOCK *block, /* not changed */ + TUPLE *tuple, /* not changed */ + void *info, void (*func)(MPL *mpl, void *info) +) +{ TUPLE *backup; + int ret = 0; + /* check if the given n-tuple is a member of the basic set */ + xassert(block->code != NULL); + if (!is_member(mpl, block->code, tuple)) + { ret = 1; + goto done; + } + /* save reference to "backup" n-tuple, which was used to assign + current values of the dummy indices (it is sufficient to save + reference, not value, because that n-tuple is defined in some + outer level of recursion and therefore cannot be changed on + this and deeper recursive calls) */ + backup = block->backup; + /* set up new "backup" n-tuple, which defines new values of the + dummy indices */ + block->backup = tuple; + /* assign new values to the dummy indices */ + update_dummy_indices(mpl, block); + /* call the formal routine that does the rest part of the job */ + func(mpl, info); + /* restore reference to the former "backup" n-tuple */ + block->backup = backup; + /* restore former values of the dummy indices; note that if the + domain block just escaped has no other active instances which + may exist due to recursion (it is indicated by a null pointer + to the former n-tuple), former values of the dummy indices are + undefined; therefore in this case the routine keeps currently + assigned values of the dummy indices that involves keeping all + dependent temporary results and thereby, if this domain block + is not used recursively, allows improving efficiency */ + update_dummy_indices(mpl, block); +done: return ret; +} + +/*---------------------------------------------------------------------- +-- eval_within_domain - perform evaluation within domain scope. +-- +-- This routine assigns new values (symbols) to all dummy indices of +-- specified domain and calls the formal routine func, which is used to +-- evaluate some code in the domain scope. Each free dummy index in the +-- domain is assigned a value specified in the corresponding component +-- of given n-tuple. Non-free dummy indices are assigned values, which +-- are computed by this routine. +-- +-- Number of components in the given n-tuple must be the same as number +-- of free indices in the domain. +-- +-- If the given n-tuple is not a member of the domain set, the routine +-- func is not called, and non-zero code is returned. +-- +-- For the sake of convenience it is allowed to specify domain as NULL +-- (then n-tuple also must be 0-tuple, i.e. empty), in which case this +-- routine just calls the routine func and returns zero. +-- +-- This routine allows recursive calls from the routine func providing +-- correct values of dummy indices for each instance. +-- +-- NOTE: The n-tuple passed to this routine must not be changed by any +-- other routines called from the formal routine func until this +-- routine has returned. */ + +struct eval_domain_info +{ /* working info used by the routine eval_within_domain */ + DOMAIN *domain; + /* domain, which has to be entered */ + DOMAIN_BLOCK *block; + /* domain block, which is currently processed */ + TUPLE *tuple; + /* tail of original n-tuple, whose components have to be assigned + to free dummy indices in the current domain block */ + void *info; + /* transit pointer passed to the formal routine func */ + void (*func)(MPL *mpl, void *info); + /* routine, which has to be executed in the domain scope */ + int failure; + /* this flag indicates that given n-tuple is not a member of the + domain set */ +}; + +static void eval_domain_func(MPL *mpl, void *_my_info) +{ /* this routine recursively enters into the domain scope and then + calls the routine func */ + struct eval_domain_info *my_info = _my_info; + if (my_info->block != NULL) + { /* the current domain block to be entered exists */ + DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + TUPLE *tuple = NULL, *temp = NULL; + /* save pointer to the current domain block */ + block = my_info->block; + /* and get ready to enter the next block (if it exists) */ + my_info->block = block->next; + /* construct temporary n-tuple, whose components correspond to + dummy indices (slots) of the current domain; components of + the temporary n-tuple that correspond to free dummy indices + are assigned references (not values!) to symbols specified + in the corresponding components of the given n-tuple, while + other components that correspond to non-free dummy indices + are assigned symbolic values computed here */ + for (slot = block->list; slot != NULL; slot = slot->next) + { /* create component that corresponds to the current slot */ + if (tuple == NULL) + tuple = temp = dmp_get_atom(mpl->tuples, sizeof(TUPLE)); + else +temp = (temp->next = dmp_get_atom(mpl->tuples, sizeof(TUPLE))); + if (slot->code == NULL) + { /* dummy index is free; take reference to symbol, which + is specified in the corresponding component of given + n-tuple */ + xassert(my_info->tuple != NULL); + temp->sym = my_info->tuple->sym; + xassert(temp->sym != NULL); + my_info->tuple = my_info->tuple->next; + } + else + { /* dummy index is non-free; compute symbolic value to be + temporarily assigned to the dummy index */ + temp->sym = eval_symbolic(mpl, slot->code); + } + } + temp->next = NULL; + /* enter the current domain block */ + if (enter_domain_block(mpl, block, tuple, my_info, + eval_domain_func)) my_info->failure = 1; + /* delete temporary n-tuple as well as symbols that correspond + to non-free dummy indices (they were computed here) */ + for (slot = block->list; slot != NULL; slot = slot->next) + { xassert(tuple != NULL); + temp = tuple; + tuple = tuple->next; + if (slot->code != NULL) + { /* dummy index is non-free; delete symbolic value */ + delete_symbol(mpl, temp->sym); + } + /* delete component that corresponds to the current slot */ + dmp_free_atom(mpl->tuples, temp, sizeof(TUPLE)); + } + } + else + { /* there are no more domain blocks, i.e. we have reached the + domain scope */ + xassert(my_info->tuple == NULL); + /* check optional predicate specified for the domain */ + if (my_info->domain->code != NULL && !eval_logical(mpl, + my_info->domain->code)) + { /* the predicate is false */ + my_info->failure = 2; + } + else + { /* the predicate is true; do the job */ + my_info->func(mpl, my_info->info); + } + } + return; +} + +int eval_within_domain +( MPL *mpl, + DOMAIN *domain, /* not changed */ + TUPLE *tuple, /* not changed */ + void *info, void (*func)(MPL *mpl, void *info) +) +{ /* this routine performs evaluation within domain scope */ + struct eval_domain_info _my_info, *my_info = &_my_info; + if (domain == NULL) + { xassert(tuple == NULL); + func(mpl, info); + my_info->failure = 0; + } + else + { xassert(tuple != NULL); + my_info->domain = domain; + my_info->block = domain->list; + my_info->tuple = tuple; + my_info->info = info; + my_info->func = func; + my_info->failure = 0; + /* enter the very first domain block */ + eval_domain_func(mpl, my_info); + } + return my_info->failure; +} + +/*---------------------------------------------------------------------- +-- loop_within_domain - perform iterations within domain scope. +-- +-- This routine iteratively assigns new values (symbols) to the dummy +-- indices of specified domain by enumerating all n-tuples, which are +-- members of the domain set, and for every n-tuple it calls the formal +-- routine func to evaluate some code within the domain scope. +-- +-- If the routine func returns non-zero, enumeration within the domain +-- is prematurely terminated. +-- +-- For the sake of convenience it is allowed to specify domain as NULL, +-- in which case this routine just calls the routine func only once and +-- returns zero. +-- +-- This routine allows recursive calls from the routine func providing +-- correct values of dummy indices for each instance. */ + +struct loop_domain_info +{ /* working info used by the routine loop_within_domain */ + DOMAIN *domain; + /* domain, which has to be entered */ + DOMAIN_BLOCK *block; + /* domain block, which is currently processed */ + int looping; + /* clearing this flag leads to terminating enumeration */ + void *info; + /* transit pointer passed to the formal routine func */ + int (*func)(MPL *mpl, void *info); + /* routine, which needs to be executed in the domain scope */ +}; + +static void loop_domain_func(MPL *mpl, void *_my_info) +{ /* this routine enumerates all n-tuples in the basic set of the + current domain block, enters recursively into the domain scope + for every n-tuple, and then calls the routine func */ + struct loop_domain_info *my_info = _my_info; + if (my_info->block != NULL) + { /* the current domain block to be entered exists */ + DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + TUPLE *bound; + /* save pointer to the current domain block */ + block = my_info->block; + /* and get ready to enter the next block (if it exists) */ + my_info->block = block->next; + /* compute symbolic values, at which non-free dummy indices of + the current domain block are bound; since that values don't + depend on free dummy indices of the current block, they can + be computed once out of the enumeration loop */ + bound = create_tuple(mpl); + for (slot = block->list; slot != NULL; slot = slot->next) + { if (slot->code != NULL) + bound = expand_tuple(mpl, bound, eval_symbolic(mpl, + slot->code)); + } + /* start enumeration */ + xassert(block->code != NULL); + if (block->code->op == O_DOTS) + { /* the basic set is "arithmetic", in which case it doesn't + need to be computed explicitly */ + TUPLE *tuple; + int n, j; + double t0, tf, dt; + /* compute "parameters" of the basic set */ + t0 = eval_numeric(mpl, block->code->arg.arg.x); + tf = eval_numeric(mpl, block->code->arg.arg.y); + if (block->code->arg.arg.z == NULL) + dt = 1.0; + else + dt = eval_numeric(mpl, block->code->arg.arg.z); + /* determine cardinality of the basic set */ + n = arelset_size(mpl, t0, tf, dt); + /* create dummy 1-tuple for members of the basic set */ + tuple = expand_tuple(mpl, create_tuple(mpl), + create_symbol_num(mpl, 0.0)); + /* in case of "arithmetic" set there is exactly one dummy + index, which cannot be non-free */ + xassert(bound == NULL); + /* walk through 1-tuples of the basic set */ + for (j = 1; j <= n && my_info->looping; j++) + { /* construct dummy 1-tuple for the current member */ + tuple->sym->num = arelset_member(mpl, t0, tf, dt, j); + /* enter the current domain block */ + enter_domain_block(mpl, block, tuple, my_info, + loop_domain_func); + } + /* delete dummy 1-tuple */ + delete_tuple(mpl, tuple); + } + else + { /* the basic set is of general kind, in which case it needs + to be explicitly computed */ + ELEMSET *set; + MEMBER *memb; + TUPLE *temp1, *temp2; + /* compute the basic set */ + set = eval_elemset(mpl, block->code); + /* walk through all n-tuples of the basic set */ + for (memb = set->head; memb != NULL && my_info->looping; + memb = memb->next) + { /* all components of the current n-tuple that correspond + to non-free dummy indices must be feasible; otherwise + the n-tuple is not in the basic set */ + temp1 = memb->tuple; + temp2 = bound; + for (slot = block->list; slot != NULL; slot = slot->next) + { xassert(temp1 != NULL); + if (slot->code != NULL) + { /* non-free dummy index */ + xassert(temp2 != NULL); + if (compare_symbols(mpl, temp1->sym, temp2->sym) + != 0) + { /* the n-tuple is not in the basic set */ + goto skip; + } + temp2 = temp2->next; + } + temp1 = temp1->next; + } + xassert(temp1 == NULL); + xassert(temp2 == NULL); + /* enter the current domain block */ + enter_domain_block(mpl, block, memb->tuple, my_info, + loop_domain_func); +skip: ; + } + /* delete the basic set */ + delete_elemset(mpl, set); + } + /* delete symbolic values binding non-free dummy indices */ + delete_tuple(mpl, bound); + /* restore pointer to the current domain block */ + my_info->block = block; + } + else + { /* there are no more domain blocks, i.e. we have reached the + domain scope */ + /* check optional predicate specified for the domain */ + if (my_info->domain->code != NULL && !eval_logical(mpl, + my_info->domain->code)) + { /* the predicate is false */ + /* nop */; + } + else + { /* the predicate is true; do the job */ + my_info->looping = !my_info->func(mpl, my_info->info); + } + } + return; +} + +void loop_within_domain +( MPL *mpl, + DOMAIN *domain, /* not changed */ + void *info, int (*func)(MPL *mpl, void *info) +) +{ /* this routine performs iterations within domain scope */ + struct loop_domain_info _my_info, *my_info = &_my_info; + if (domain == NULL) + func(mpl, info); + else + { my_info->domain = domain; + my_info->block = domain->list; + my_info->looping = 1; + my_info->info = info; + my_info->func = func; + /* enter the very first domain block */ + loop_domain_func(mpl, my_info); + } + return; +} + +/*---------------------------------------------------------------------- +-- out_of_domain - raise domain exception. +-- +-- This routine is called when a reference is made to a member of some +-- model object, but its n-tuple is out of the object domain. */ + +void out_of_domain +( MPL *mpl, + char *name, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ xassert(name != NULL); + xassert(tuple != NULL); + error(mpl, "%s%s out of domain", name, format_tuple(mpl, '[', + tuple)); + /* no return */ +} + +/*---------------------------------------------------------------------- +-- get_domain_tuple - obtain current n-tuple from domain. +-- +-- This routine constructs n-tuple, whose components are current values +-- assigned to *free* dummy indices of specified domain. +-- +-- For the sake of convenience it is allowed to specify domain as NULL, +-- in which case this routine returns 0-tuple. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +TUPLE *get_domain_tuple +( MPL *mpl, + DOMAIN *domain /* not changed */ +) +{ DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + TUPLE *tuple; + tuple = create_tuple(mpl); + if (domain != NULL) + { for (block = domain->list; block != NULL; block = block->next) + { for (slot = block->list; slot != NULL; slot = slot->next) + { if (slot->code == NULL) + { xassert(slot->value != NULL); + tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, + slot->value)); + } + } + } + } + return tuple; +} + +/*---------------------------------------------------------------------- +-- clean_domain - clean domain. +-- +-- This routine cleans specified domain that assumes deleting all stuff +-- dynamically allocated during the generation phase. */ + +void clean_domain(MPL *mpl, DOMAIN *domain) +{ DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + /* if no domain is specified, do nothing */ + if (domain == NULL) goto done; + /* clean all domain blocks */ + for (block = domain->list; block != NULL; block = block->next) + { /* clean all domain slots */ + for (slot = block->list; slot != NULL; slot = slot->next) + { /* clean pseudo-code for computing bound value */ + clean_code(mpl, slot->code); + /* delete symbolic value assigned to dummy index */ + if (slot->value != NULL) + delete_symbol(mpl, slot->value), slot->value = NULL; + } + /* clean pseudo-code for computing basic set */ + clean_code(mpl, block->code); + } + /* clean pseudo-code for computing domain predicate */ + clean_code(mpl, domain->code); +done: return; +} + +/**********************************************************************/ +/* * * MODEL SETS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- check_elem_set - check elemental set assigned to set member. +-- +-- This routine checks if given elemental set being assigned to member +-- of specified model set satisfies to all restrictions. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +void check_elem_set +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple, /* not changed */ + ELEMSET *refer /* not changed */ +) +{ WITHIN *within; + MEMBER *memb; + int eqno; + /* elemental set must be within all specified supersets */ + for (within = set->within, eqno = 1; within != NULL; within = + within->next, eqno++) + { xassert(within->code != NULL); + for (memb = refer->head; memb != NULL; memb = memb->next) + { if (!is_member(mpl, within->code, memb->tuple)) + { char buf[255+1]; + strcpy(buf, format_tuple(mpl, '(', memb->tuple)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s contains %s which not within specified " + "set; see (%d)", set->name, format_tuple(mpl, '[', + tuple), buf, eqno); + } + } + } + return; +} + +/*---------------------------------------------------------------------- +-- take_member_set - obtain elemental set assigned to set member. +-- +-- This routine obtains a reference to elemental set assigned to given +-- member of specified model set and returns it on exit. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +ELEMSET *take_member_set /* returns reference, not value */ +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + ELEMSET *refer; + /* find member in the set array */ + memb = find_member(mpl, set->array, tuple); + if (memb != NULL) + { /* member exists, so just take the reference */ + refer = memb->value.set; + } + else if (set->assign != NULL) + { /* compute value using assignment expression */ + refer = eval_elemset(mpl, set->assign); +add: /* check that the elemental set satisfies to all restrictions, + assign it to new member, and add the member to the array */ + check_elem_set(mpl, set, tuple, refer); + memb = add_member(mpl, set->array, copy_tuple(mpl, tuple)); + memb->value.set = refer; + } + else if (set->option != NULL) + { /* compute default elemental set */ + refer = eval_elemset(mpl, set->option); + goto add; + } + else + { /* no value (elemental set) is provided */ + error(mpl, "no value for %s%s", set->name, format_tuple(mpl, + '[', tuple)); + } + return refer; +} + +/*---------------------------------------------------------------------- +-- eval_member_set - evaluate elemental set assigned to set member. +-- +-- This routine evaluates a reference to elemental set assigned to given +-- member of specified model set and returns it on exit. */ + +struct eval_set_info +{ /* working info used by the routine eval_member_set */ + SET *set; + /* model set */ + TUPLE *tuple; + /* n-tuple, which defines set member */ + MEMBER *memb; + /* normally this pointer is NULL; the routine uses this pointer + to check data provided in the data section, in which case it + points to a member currently checked; this check is performed + automatically only once when a reference to any member occurs + for the first time */ + ELEMSET *refer; + /* evaluated reference to elemental set */ +}; + +static void eval_set_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine to work within domain scope */ + struct eval_set_info *info = _info; + if (info->memb != NULL) + { /* checking call; check elemental set being assigned */ + check_elem_set(mpl, info->set, info->memb->tuple, + info->memb->value.set); + } + else + { /* normal call; evaluate member, which has given n-tuple */ + info->refer = take_member_set(mpl, info->set, info->tuple); + } + return; +} + +#if 1 /* 12/XII-2008 */ +static void saturate_set(MPL *mpl, SET *set) +{ GADGET *gadget = set->gadget; + ELEMSET *data; + MEMBER *elem, *memb; + TUPLE *tuple, *work[20]; + int i; + xprintf("Generating %s...\n", set->name); + eval_whole_set(mpl, gadget->set); + /* gadget set must have exactly one member */ + xassert(gadget->set->array != NULL); + xassert(gadget->set->array->head != NULL); + xassert(gadget->set->array->head == gadget->set->array->tail); + data = gadget->set->array->head->value.set; + xassert(data->type == A_NONE); + xassert(data->dim == gadget->set->dimen); + /* walk thru all elements of the plain set */ + for (elem = data->head; elem != NULL; elem = elem->next) + { /* create a copy of n-tuple */ + tuple = copy_tuple(mpl, elem->tuple); + /* rearrange component of the n-tuple */ + for (i = 0; i < gadget->set->dimen; i++) + work[i] = NULL; + for (i = 0; tuple != NULL; tuple = tuple->next) + work[gadget->ind[i++]-1] = tuple; + xassert(i == gadget->set->dimen); + for (i = 0; i < gadget->set->dimen; i++) + { xassert(work[i] != NULL); + work[i]->next = work[i+1]; + } + /* construct subscript list from first set->dim components */ + if (set->dim == 0) + tuple = NULL; + else + tuple = work[0], work[set->dim-1]->next = NULL; + /* find corresponding member of the set to be initialized */ + memb = find_member(mpl, set->array, tuple); + if (memb == NULL) + { /* not found; add new member to the set and assign it empty + elemental set */ + memb = add_member(mpl, set->array, tuple); + memb->value.set = create_elemset(mpl, set->dimen); + } + else + { /* found; free subscript list */ + delete_tuple(mpl, tuple); + } + /* construct new n-tuple from rest set->dimen components */ + tuple = work[set->dim]; + xassert(set->dim + set->dimen == gadget->set->dimen); + work[gadget->set->dimen-1]->next = NULL; + /* and add it to the elemental set assigned to the member + (no check for duplicates is needed) */ + add_tuple(mpl, memb->value.set, tuple); + } + /* the set has been saturated with data */ + set->data = 1; + return; +} +#endif + +ELEMSET *eval_member_set /* returns reference, not value */ +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ /* this routine evaluates set member */ + struct eval_set_info _info, *info = &_info; + xassert(set->dim == tuple_dimen(mpl, tuple)); + info->set = set; + info->tuple = tuple; +#if 1 /* 12/XII-2008 */ + if (set->gadget != NULL && set->data == 0) + { /* initialize the set with data from a plain set */ + saturate_set(mpl, set); + } +#endif + if (set->data == 1) + { /* check data, which are provided in the data section, but not + checked yet */ + /* save pointer to the last array member; note that during the + check new members may be added beyond the last member due to + references to the same parameter from default expression as + well as from expressions that define restricting supersets; + however, values assigned to the new members will be checked + by other routine, so we don't need to check them here */ + MEMBER *tail = set->array->tail; + /* change the data status to prevent infinite recursive loop + due to references to the same set during the check */ + set->data = 2; + /* check elemental sets assigned to array members in the data + section until the marked member has been reached */ + for (info->memb = set->array->head; info->memb != NULL; + info->memb = info->memb->next) + { if (eval_within_domain(mpl, set->domain, info->memb->tuple, + info, eval_set_func)) + out_of_domain(mpl, set->name, info->memb->tuple); + if (info->memb == tail) break; + } + /* the check has been finished */ + } + /* evaluate member, which has given n-tuple */ + info->memb = NULL; + if (eval_within_domain(mpl, info->set->domain, info->tuple, info, + eval_set_func)) + out_of_domain(mpl, set->name, info->tuple); + /* bring evaluated reference to the calling program */ + return info->refer; +} + +/*---------------------------------------------------------------------- +-- eval_whole_set - evaluate model set over entire domain. +-- +-- This routine evaluates all members of specified model set over entire +-- domain. */ + +static int whole_set_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + SET *set = (SET *)info; + TUPLE *tuple = get_domain_tuple(mpl, set->domain); + eval_member_set(mpl, set, tuple); + delete_tuple(mpl, tuple); + return 0; +} + +void eval_whole_set(MPL *mpl, SET *set) +{ loop_within_domain(mpl, set->domain, set, whole_set_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean set - clean model set. +-- +-- This routine cleans specified model set that assumes deleting all +-- stuff dynamically allocated during the generation phase. */ + +void clean_set(MPL *mpl, SET *set) +{ WITHIN *within; + MEMBER *memb; + /* clean subscript domain */ + clean_domain(mpl, set->domain); + /* clean pseudo-code for computing supersets */ + for (within = set->within; within != NULL; within = within->next) + clean_code(mpl, within->code); + /* clean pseudo-code for computing assigned value */ + clean_code(mpl, set->assign); + /* clean pseudo-code for computing default value */ + clean_code(mpl, set->option); + /* reset data status flag */ + set->data = 0; + /* delete content array */ + for (memb = set->array->head; memb != NULL; memb = memb->next) + delete_value(mpl, set->array->type, &memb->value); + delete_array(mpl, set->array), set->array = NULL; + return; +} + +/**********************************************************************/ +/* * * MODEL PARAMETERS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- check_value_num - check numeric value assigned to parameter member. +-- +-- This routine checks if numeric value being assigned to some member +-- of specified numeric model parameter satisfies to all restrictions. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +void check_value_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple, /* not changed */ + double value +) +{ CONDITION *cond; + WITHIN *in; + int eqno; + /* the value must satisfy to the parameter type */ + switch (par->type) + { case A_NUMERIC: + break; + case A_INTEGER: + if (value != floor(value)) + error(mpl, "%s%s = %.*g not integer", par->name, + format_tuple(mpl, '[', tuple), DBL_DIG, value); + break; + case A_BINARY: + if (!(value == 0.0 || value == 1.0)) + error(mpl, "%s%s = %.*g not binary", par->name, + format_tuple(mpl, '[', tuple), DBL_DIG, value); + break; + default: + xassert(par != par); + } + /* the value must satisfy to all specified conditions */ + for (cond = par->cond, eqno = 1; cond != NULL; cond = cond->next, + eqno++) + { double bound; + char *rho; + xassert(cond->code != NULL); + bound = eval_numeric(mpl, cond->code); + switch (cond->rho) + { case O_LT: + if (!(value < bound)) + { rho = "<"; +err: error(mpl, "%s%s = %.*g not %s %.*g; see (%d)", + par->name, format_tuple(mpl, '[', tuple), DBL_DIG, + value, rho, DBL_DIG, bound, eqno); + } + break; + case O_LE: + if (!(value <= bound)) { rho = "<="; goto err; } + break; + case O_EQ: + if (!(value == bound)) { rho = "="; goto err; } + break; + case O_GE: + if (!(value >= bound)) { rho = ">="; goto err; } + break; + case O_GT: + if (!(value > bound)) { rho = ">"; goto err; } + break; + case O_NE: + if (!(value != bound)) { rho = "<>"; goto err; } + break; + default: + xassert(cond != cond); + } + } + /* the value must be in all specified supersets */ + for (in = par->in, eqno = 1; in != NULL; in = in->next, eqno++) + { TUPLE *dummy; + xassert(in->code != NULL); + xassert(in->code->dim == 1); + dummy = expand_tuple(mpl, create_tuple(mpl), + create_symbol_num(mpl, value)); + if (!is_member(mpl, in->code, dummy)) + error(mpl, "%s%s = %.*g not in specified set; see (%d)", + par->name, format_tuple(mpl, '[', tuple), DBL_DIG, + value, eqno); + delete_tuple(mpl, dummy); + } + return; +} + +/*---------------------------------------------------------------------- +-- take_member_num - obtain num. value assigned to parameter member. +-- +-- This routine obtains a numeric value assigned to member of specified +-- numeric model parameter and returns it on exit. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +double take_member_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + double value; + /* find member in the parameter array */ + memb = find_member(mpl, par->array, tuple); + if (memb != NULL) + { /* member exists, so just take its value */ + value = memb->value.num; + } + else if (par->assign != NULL) + { /* compute value using assignment expression */ + value = eval_numeric(mpl, par->assign); +add: /* check that the value satisfies to all restrictions, assign + it to new member, and add the member to the array */ + check_value_num(mpl, par, tuple, value); + memb = add_member(mpl, par->array, copy_tuple(mpl, tuple)); + memb->value.num = value; + } + else if (par->option != NULL) + { /* compute default value */ + value = eval_numeric(mpl, par->option); + goto add; + } + else if (par->defval != NULL) + { /* take default value provided in the data section */ + if (par->defval->str != NULL) + error(mpl, "cannot convert %s to floating-point number", + format_symbol(mpl, par->defval)); + value = par->defval->num; + goto add; + } + else + { /* no value is provided */ + error(mpl, "no value for %s%s", par->name, format_tuple(mpl, + '[', tuple)); + } + return value; +} + +/*---------------------------------------------------------------------- +-- eval_member_num - evaluate num. value assigned to parameter member. +-- +-- This routine evaluates a numeric value assigned to given member of +-- specified numeric model parameter and returns it on exit. */ + +struct eval_num_info +{ /* working info used by the routine eval_member_num */ + PARAMETER *par; + /* model parameter */ + TUPLE *tuple; + /* n-tuple, which defines parameter member */ + MEMBER *memb; + /* normally this pointer is NULL; the routine uses this pointer + to check data provided in the data section, in which case it + points to a member currently checked; this check is performed + automatically only once when a reference to any member occurs + for the first time */ + double value; + /* evaluated numeric value */ +}; + +static void eval_num_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine to work within domain scope */ + struct eval_num_info *info = _info; + if (info->memb != NULL) + { /* checking call; check numeric value being assigned */ + check_value_num(mpl, info->par, info->memb->tuple, + info->memb->value.num); + } + else + { /* normal call; evaluate member, which has given n-tuple */ + info->value = take_member_num(mpl, info->par, info->tuple); + } + return; +} + +double eval_member_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ /* this routine evaluates numeric parameter member */ + struct eval_num_info _info, *info = &_info; + xassert(par->type == A_NUMERIC || par->type == A_INTEGER || + par->type == A_BINARY); + xassert(par->dim == tuple_dimen(mpl, tuple)); + info->par = par; + info->tuple = tuple; + if (par->data == 1) + { /* check data, which are provided in the data section, but not + checked yet */ + /* save pointer to the last array member; note that during the + check new members may be added beyond the last member due to + references to the same parameter from default expression as + well as from expressions that define restricting conditions; + however, values assigned to the new members will be checked + by other routine, so we don't need to check them here */ + MEMBER *tail = par->array->tail; + /* change the data status to prevent infinite recursive loop + due to references to the same parameter during the check */ + par->data = 2; + /* check values assigned to array members in the data section + until the marked member has been reached */ + for (info->memb = par->array->head; info->memb != NULL; + info->memb = info->memb->next) + { if (eval_within_domain(mpl, par->domain, info->memb->tuple, + info, eval_num_func)) + out_of_domain(mpl, par->name, info->memb->tuple); + if (info->memb == tail) break; + } + /* the check has been finished */ + } + /* evaluate member, which has given n-tuple */ + info->memb = NULL; + if (eval_within_domain(mpl, info->par->domain, info->tuple, info, + eval_num_func)) + out_of_domain(mpl, par->name, info->tuple); + /* bring evaluated value to the calling program */ + return info->value; +} + +/*---------------------------------------------------------------------- +-- check_value_sym - check symbolic value assigned to parameter member. +-- +-- This routine checks if symbolic value being assigned to some member +-- of specified symbolic model parameter satisfies to all restrictions. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +void check_value_sym +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple, /* not changed */ + SYMBOL *value /* not changed */ +) +{ CONDITION *cond; + WITHIN *in; + int eqno; + /* the value must satisfy to all specified conditions */ + for (cond = par->cond, eqno = 1; cond != NULL; cond = cond->next, + eqno++) + { SYMBOL *bound; + char buf[255+1]; + xassert(cond->code != NULL); + bound = eval_symbolic(mpl, cond->code); + switch (cond->rho) + { +#if 1 /* 13/VIII-2008 */ + case O_LT: + if (!(compare_symbols(mpl, value, bound) < 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not < %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; + case O_LE: + if (!(compare_symbols(mpl, value, bound) <= 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not <= %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; +#endif + case O_EQ: + if (!(compare_symbols(mpl, value, bound) == 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not = %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; +#if 1 /* 13/VIII-2008 */ + case O_GE: + if (!(compare_symbols(mpl, value, bound) >= 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not >= %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; + case O_GT: + if (!(compare_symbols(mpl, value, bound) > 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not > %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; +#endif + case O_NE: + if (!(compare_symbols(mpl, value, bound) != 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not <> %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; + default: + xassert(cond != cond); + } + delete_symbol(mpl, bound); + } + /* the value must be in all specified supersets */ + for (in = par->in, eqno = 1; in != NULL; in = in->next, eqno++) + { TUPLE *dummy; + xassert(in->code != NULL); + xassert(in->code->dim == 1); + dummy = expand_tuple(mpl, create_tuple(mpl), copy_symbol(mpl, + value)); + if (!is_member(mpl, in->code, dummy)) + error(mpl, "%s%s = %s not in specified set; see (%d)", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), eqno); + delete_tuple(mpl, dummy); + } + return; +} + +/*---------------------------------------------------------------------- +-- take_member_sym - obtain symb. value assigned to parameter member. +-- +-- This routine obtains a symbolic value assigned to member of specified +-- symbolic model parameter and returns it on exit. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +SYMBOL *take_member_sym /* returns value, not reference */ +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + SYMBOL *value; + /* find member in the parameter array */ + memb = find_member(mpl, par->array, tuple); + if (memb != NULL) + { /* member exists, so just take its value */ + value = copy_symbol(mpl, memb->value.sym); + } + else if (par->assign != NULL) + { /* compute value using assignment expression */ + value = eval_symbolic(mpl, par->assign); +add: /* check that the value satisfies to all restrictions, assign + it to new member, and add the member to the array */ + check_value_sym(mpl, par, tuple, value); + memb = add_member(mpl, par->array, copy_tuple(mpl, tuple)); + memb->value.sym = copy_symbol(mpl, value); + } + else if (par->option != NULL) + { /* compute default value */ + value = eval_symbolic(mpl, par->option); + goto add; + } + else if (par->defval != NULL) + { /* take default value provided in the data section */ + value = copy_symbol(mpl, par->defval); + goto add; + } + else + { /* no value is provided */ + error(mpl, "no value for %s%s", par->name, format_tuple(mpl, + '[', tuple)); + } + return value; +} + +/*---------------------------------------------------------------------- +-- eval_member_sym - evaluate symb. value assigned to parameter member. +-- +-- This routine evaluates a symbolic value assigned to given member of +-- specified symbolic model parameter and returns it on exit. */ + +struct eval_sym_info +{ /* working info used by the routine eval_member_sym */ + PARAMETER *par; + /* model parameter */ + TUPLE *tuple; + /* n-tuple, which defines parameter member */ + MEMBER *memb; + /* normally this pointer is NULL; the routine uses this pointer + to check data provided in the data section, in which case it + points to a member currently checked; this check is performed + automatically only once when a reference to any member occurs + for the first time */ + SYMBOL *value; + /* evaluated symbolic value */ +}; + +static void eval_sym_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine to work within domain scope */ + struct eval_sym_info *info = _info; + if (info->memb != NULL) + { /* checking call; check symbolic value being assigned */ + check_value_sym(mpl, info->par, info->memb->tuple, + info->memb->value.sym); + } + else + { /* normal call; evaluate member, which has given n-tuple */ + info->value = take_member_sym(mpl, info->par, info->tuple); + } + return; +} + +SYMBOL *eval_member_sym /* returns value, not reference */ +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ /* this routine evaluates symbolic parameter member */ + struct eval_sym_info _info, *info = &_info; + xassert(par->type == A_SYMBOLIC); + xassert(par->dim == tuple_dimen(mpl, tuple)); + info->par = par; + info->tuple = tuple; + if (par->data == 1) + { /* check data, which are provided in the data section, but not + checked yet */ + /* save pointer to the last array member; note that during the + check new members may be added beyond the last member due to + references to the same parameter from default expression as + well as from expressions that define restricting conditions; + however, values assigned to the new members will be checked + by other routine, so we don't need to check them here */ + MEMBER *tail = par->array->tail; + /* change the data status to prevent infinite recursive loop + due to references to the same parameter during the check */ + par->data = 2; + /* check values assigned to array members in the data section + until the marked member has been reached */ + for (info->memb = par->array->head; info->memb != NULL; + info->memb = info->memb->next) + { if (eval_within_domain(mpl, par->domain, info->memb->tuple, + info, eval_sym_func)) + out_of_domain(mpl, par->name, info->memb->tuple); + if (info->memb == tail) break; + } + /* the check has been finished */ + } + /* evaluate member, which has given n-tuple */ + info->memb = NULL; + if (eval_within_domain(mpl, info->par->domain, info->tuple, info, + eval_sym_func)) + out_of_domain(mpl, par->name, info->tuple); + /* bring evaluated value to the calling program */ + return info->value; +} + +/*---------------------------------------------------------------------- +-- eval_whole_par - evaluate model parameter over entire domain. +-- +-- This routine evaluates all members of specified model parameter over +-- entire domain. */ + +static int whole_par_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + PARAMETER *par = (PARAMETER *)info; + TUPLE *tuple = get_domain_tuple(mpl, par->domain); + switch (par->type) + { case A_NUMERIC: + case A_INTEGER: + case A_BINARY: + eval_member_num(mpl, par, tuple); + break; + case A_SYMBOLIC: + delete_symbol(mpl, eval_member_sym(mpl, par, tuple)); + break; + default: + xassert(par != par); + } + delete_tuple(mpl, tuple); + return 0; +} + +void eval_whole_par(MPL *mpl, PARAMETER *par) +{ loop_within_domain(mpl, par->domain, par, whole_par_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_parameter - clean model parameter. +-- +-- This routine cleans specified model parameter that assumes deleting +-- all stuff dynamically allocated during the generation phase. */ + +void clean_parameter(MPL *mpl, PARAMETER *par) +{ CONDITION *cond; + WITHIN *in; + MEMBER *memb; + /* clean subscript domain */ + clean_domain(mpl, par->domain); + /* clean pseudo-code for computing restricting conditions */ + for (cond = par->cond; cond != NULL; cond = cond->next) + clean_code(mpl, cond->code); + /* clean pseudo-code for computing restricting supersets */ + for (in = par->in; in != NULL; in = in->next) + clean_code(mpl, in->code); + /* clean pseudo-code for computing assigned value */ + clean_code(mpl, par->assign); + /* clean pseudo-code for computing default value */ + clean_code(mpl, par->option); + /* reset data status flag */ + par->data = 0; + /* delete default symbolic value */ + if (par->defval != NULL) + delete_symbol(mpl, par->defval), par->defval = NULL; + /* delete content array */ + for (memb = par->array->head; memb != NULL; memb = memb->next) + delete_value(mpl, par->array->type, &memb->value); + delete_array(mpl, par->array), par->array = NULL; + return; +} + +/**********************************************************************/ +/* * * MODEL VARIABLES * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- take_member_var - obtain reference to elemental variable. +-- +-- This routine obtains a reference to elemental variable assigned to +-- given member of specified model variable and returns it on exit. If +-- necessary, new elemental variable is created. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +ELEMVAR *take_member_var /* returns reference */ +( MPL *mpl, + VARIABLE *var, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + ELEMVAR *refer; + /* find member in the variable array */ + memb = find_member(mpl, var->array, tuple); + if (memb != NULL) + { /* member exists, so just take the reference */ + refer = memb->value.var; + } + else + { /* member is referenced for the first time and therefore does + not exist; create new elemental variable, assign it to new + member, and add the member to the variable array */ + memb = add_member(mpl, var->array, copy_tuple(mpl, tuple)); + refer = (memb->value.var = + dmp_get_atom(mpl->elemvars, sizeof(ELEMVAR))); + refer->j = 0; + refer->var = var; + refer->memb = memb; + /* compute lower bound */ + if (var->lbnd == NULL) + refer->lbnd = 0.0; + else + refer->lbnd = eval_numeric(mpl, var->lbnd); + /* compute upper bound */ + if (var->ubnd == NULL) + refer->ubnd = 0.0; + else if (var->ubnd == var->lbnd) + refer->ubnd = refer->lbnd; + else + refer->ubnd = eval_numeric(mpl, var->ubnd); + /* nullify working quantity */ + refer->temp = 0.0; +#if 1 /* 15/V-2010 */ + /* solution has not been obtained by the solver yet */ + refer->stat = 0; + refer->prim = refer->dual = 0.0; +#endif + } + return refer; +} + +/*---------------------------------------------------------------------- +-- eval_member_var - evaluate reference to elemental variable. +-- +-- This routine evaluates a reference to elemental variable assigned to +-- member of specified model variable and returns it on exit. */ + +struct eval_var_info +{ /* working info used by the routine eval_member_var */ + VARIABLE *var; + /* model variable */ + TUPLE *tuple; + /* n-tuple, which defines variable member */ + ELEMVAR *refer; + /* evaluated reference to elemental variable */ +}; + +static void eval_var_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine to work within domain scope */ + struct eval_var_info *info = _info; + info->refer = take_member_var(mpl, info->var, info->tuple); + return; +} + +ELEMVAR *eval_member_var /* returns reference */ +( MPL *mpl, + VARIABLE *var, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ /* this routine evaluates variable member */ + struct eval_var_info _info, *info = &_info; + xassert(var->dim == tuple_dimen(mpl, tuple)); + info->var = var; + info->tuple = tuple; + /* evaluate member, which has given n-tuple */ + if (eval_within_domain(mpl, info->var->domain, info->tuple, info, + eval_var_func)) + out_of_domain(mpl, var->name, info->tuple); + /* bring evaluated reference to the calling program */ + return info->refer; +} + +/*---------------------------------------------------------------------- +-- eval_whole_var - evaluate model variable over entire domain. +-- +-- This routine evaluates all members of specified model variable over +-- entire domain. */ + +static int whole_var_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + VARIABLE *var = (VARIABLE *)info; + TUPLE *tuple = get_domain_tuple(mpl, var->domain); + eval_member_var(mpl, var, tuple); + delete_tuple(mpl, tuple); + return 0; +} + +void eval_whole_var(MPL *mpl, VARIABLE *var) +{ loop_within_domain(mpl, var->domain, var, whole_var_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_variable - clean model variable. +-- +-- This routine cleans specified model variable that assumes deleting +-- all stuff dynamically allocated during the generation phase. */ + +void clean_variable(MPL *mpl, VARIABLE *var) +{ MEMBER *memb; + /* clean subscript domain */ + clean_domain(mpl, var->domain); + /* clean code for computing lower bound */ + clean_code(mpl, var->lbnd); + /* clean code for computing upper bound */ + if (var->ubnd != var->lbnd) clean_code(mpl, var->ubnd); + /* delete content array */ + for (memb = var->array->head; memb != NULL; memb = memb->next) + dmp_free_atom(mpl->elemvars, memb->value.var, sizeof(ELEMVAR)); + delete_array(mpl, var->array), var->array = NULL; + return; +} + +/**********************************************************************/ +/* * * MODEL CONSTRAINTS AND OBJECTIVES * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- take_member_con - obtain reference to elemental constraint. +-- +-- This routine obtains a reference to elemental constraint assigned +-- to given member of specified model constraint and returns it on exit. +-- If necessary, new elemental constraint is created. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +ELEMCON *take_member_con /* returns reference */ +( MPL *mpl, + CONSTRAINT *con, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + ELEMCON *refer; + /* find member in the constraint array */ + memb = find_member(mpl, con->array, tuple); + if (memb != NULL) + { /* member exists, so just take the reference */ + refer = memb->value.con; + } + else + { /* member is referenced for the first time and therefore does + not exist; create new elemental constraint, assign it to new + member, and add the member to the constraint array */ + memb = add_member(mpl, con->array, copy_tuple(mpl, tuple)); + refer = (memb->value.con = + dmp_get_atom(mpl->elemcons, sizeof(ELEMCON))); + refer->i = 0; + refer->con = con; + refer->memb = memb; + /* compute linear form */ + xassert(con->code != NULL); + refer->form = eval_formula(mpl, con->code); + /* compute lower and upper bounds */ + if (con->lbnd == NULL && con->ubnd == NULL) + { /* objective has no bounds */ + double temp; + xassert(con->type == A_MINIMIZE || con->type == A_MAXIMIZE); + /* carry the constant term to the right-hand side */ + refer->form = remove_constant(mpl, refer->form, &temp); + refer->lbnd = refer->ubnd = - temp; + } + else if (con->lbnd != NULL && con->ubnd == NULL) + { /* constraint a * x + b >= c * y + d is transformed to the + standard form a * x - c * y >= d - b */ + double temp; + xassert(con->type == A_CONSTRAINT); + refer->form = linear_comb(mpl, + +1.0, refer->form, + -1.0, eval_formula(mpl, con->lbnd)); + refer->form = remove_constant(mpl, refer->form, &temp); + refer->lbnd = - temp; + refer->ubnd = 0.0; + } + else if (con->lbnd == NULL && con->ubnd != NULL) + { /* constraint a * x + b <= c * y + d is transformed to the + standard form a * x - c * y <= d - b */ + double temp; + xassert(con->type == A_CONSTRAINT); + refer->form = linear_comb(mpl, + +1.0, refer->form, + -1.0, eval_formula(mpl, con->ubnd)); + refer->form = remove_constant(mpl, refer->form, &temp); + refer->lbnd = 0.0; + refer->ubnd = - temp; + } + else if (con->lbnd == con->ubnd) + { /* constraint a * x + b = c * y + d is transformed to the + standard form a * x - c * y = d - b */ + double temp; + xassert(con->type == A_CONSTRAINT); + refer->form = linear_comb(mpl, + +1.0, refer->form, + -1.0, eval_formula(mpl, con->lbnd)); + refer->form = remove_constant(mpl, refer->form, &temp); + refer->lbnd = refer->ubnd = - temp; + } + else + { /* ranged constraint c <= a * x + b <= d is transformed to + the standard form c - b <= a * x <= d - b */ + double temp, temp1, temp2; + xassert(con->type == A_CONSTRAINT); + refer->form = remove_constant(mpl, refer->form, &temp); + xassert(remove_constant(mpl, eval_formula(mpl, con->lbnd), + &temp1) == NULL); + xassert(remove_constant(mpl, eval_formula(mpl, con->ubnd), + &temp2) == NULL); + refer->lbnd = fp_sub(mpl, temp1, temp); + refer->ubnd = fp_sub(mpl, temp2, temp); + } +#if 1 /* 15/V-2010 */ + /* solution has not been obtained by the solver yet */ + refer->stat = 0; + refer->prim = refer->dual = 0.0; +#endif + } + return refer; +} + +/*---------------------------------------------------------------------- +-- eval_member_con - evaluate reference to elemental constraint. +-- +-- This routine evaluates a reference to elemental constraint assigned +-- to member of specified model constraint and returns it on exit. */ + +struct eval_con_info +{ /* working info used by the routine eval_member_con */ + CONSTRAINT *con; + /* model constraint */ + TUPLE *tuple; + /* n-tuple, which defines constraint member */ + ELEMCON *refer; + /* evaluated reference to elemental constraint */ +}; + +static void eval_con_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine to work within domain scope */ + struct eval_con_info *info = _info; + info->refer = take_member_con(mpl, info->con, info->tuple); + return; +} + +ELEMCON *eval_member_con /* returns reference */ +( MPL *mpl, + CONSTRAINT *con, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ /* this routine evaluates constraint member */ + struct eval_con_info _info, *info = &_info; + xassert(con->dim == tuple_dimen(mpl, tuple)); + info->con = con; + info->tuple = tuple; + /* evaluate member, which has given n-tuple */ + if (eval_within_domain(mpl, info->con->domain, info->tuple, info, + eval_con_func)) + out_of_domain(mpl, con->name, info->tuple); + /* bring evaluated reference to the calling program */ + return info->refer; +} + +/*---------------------------------------------------------------------- +-- eval_whole_con - evaluate model constraint over entire domain. +-- +-- This routine evaluates all members of specified model constraint over +-- entire domain. */ + +static int whole_con_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + CONSTRAINT *con = (CONSTRAINT *)info; + TUPLE *tuple = get_domain_tuple(mpl, con->domain); + eval_member_con(mpl, con, tuple); + delete_tuple(mpl, tuple); + return 0; +} + +void eval_whole_con(MPL *mpl, CONSTRAINT *con) +{ loop_within_domain(mpl, con->domain, con, whole_con_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_constraint - clean model constraint. +-- +-- This routine cleans specified model constraint that assumes deleting +-- all stuff dynamically allocated during the generation phase. */ + +void clean_constraint(MPL *mpl, CONSTRAINT *con) +{ MEMBER *memb; + /* clean subscript domain */ + clean_domain(mpl, con->domain); + /* clean code for computing main linear form */ + clean_code(mpl, con->code); + /* clean code for computing lower bound */ + clean_code(mpl, con->lbnd); + /* clean code for computing upper bound */ + if (con->ubnd != con->lbnd) clean_code(mpl, con->ubnd); + /* delete content array */ + for (memb = con->array->head; memb != NULL; memb = memb->next) + { delete_formula(mpl, memb->value.con->form); + dmp_free_atom(mpl->elemcons, memb->value.con, sizeof(ELEMCON)); + } + delete_array(mpl, con->array), con->array = NULL; + return; +} + +/**********************************************************************/ +/* * * PSEUDO-CODE * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- eval_numeric - evaluate pseudo-code to determine numeric value. +-- +-- This routine evaluates specified pseudo-code to determine resultant +-- numeric value, which is returned on exit. */ + +struct iter_num_info +{ /* working info used by the routine iter_num_func */ + CODE *code; + /* pseudo-code for iterated operation to be performed */ + double value; + /* resultant value */ +}; + +static int iter_num_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine used to perform iterated operation + on numeric "integrand" within domain scope */ + struct iter_num_info *info = _info; + double temp; + temp = eval_numeric(mpl, info->code->arg.loop.x); + switch (info->code->op) + { case O_SUM: + /* summation over domain */ + info->value = fp_add(mpl, info->value, temp); + break; + case O_PROD: + /* multiplication over domain */ + info->value = fp_mul(mpl, info->value, temp); + break; + case O_MINIMUM: + /* minimum over domain */ + if (info->value > temp) info->value = temp; + break; + case O_MAXIMUM: + /* maximum over domain */ + if (info->value < temp) info->value = temp; + break; + default: + xassert(info != info); + } + return 0; +} + +double eval_numeric(MPL *mpl, CODE *code) +{ double value; + xassert(code != NULL); + xassert(code->type == A_NUMERIC); + xassert(code->dim == 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = code->value.num; + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_NUMBER: + /* take floating-point number */ + value = code->arg.num; + break; + case O_MEMNUM: + /* take member of numeric parameter */ + { TUPLE *tuple; + ARG_LIST *e; + tuple = create_tuple(mpl); + for (e = code->arg.par.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); + value = eval_member_num(mpl, code->arg.par.par, tuple); + delete_tuple(mpl, tuple); + } + break; + case O_MEMVAR: + /* take computed value of elemental variable */ + { TUPLE *tuple; + ARG_LIST *e; +#if 1 /* 15/V-2010 */ + ELEMVAR *var; +#endif + tuple = create_tuple(mpl); + for (e = code->arg.var.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); +#if 0 /* 15/V-2010 */ + value = eval_member_var(mpl, code->arg.var.var, tuple) + ->value; +#else + var = eval_member_var(mpl, code->arg.var.var, tuple); + switch (code->arg.var.suff) + { case DOT_LB: + if (var->var->lbnd == NULL) + value = -DBL_MAX; + else + value = var->lbnd; + break; + case DOT_UB: + if (var->var->ubnd == NULL) + value = +DBL_MAX; + else + value = var->ubnd; + break; + case DOT_STATUS: + value = var->stat; + break; + case DOT_VAL: + value = var->prim; + break; + case DOT_DUAL: + value = var->dual; + break; + default: + xassert(code != code); + } +#endif + delete_tuple(mpl, tuple); + } + break; +#if 1 /* 15/V-2010 */ + case O_MEMCON: + /* take computed value of elemental constraint */ + { TUPLE *tuple; + ARG_LIST *e; + ELEMCON *con; + tuple = create_tuple(mpl); + for (e = code->arg.con.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); + con = eval_member_con(mpl, code->arg.con.con, tuple); + switch (code->arg.con.suff) + { case DOT_LB: + if (con->con->lbnd == NULL) + value = -DBL_MAX; + else + value = con->lbnd; + break; + case DOT_UB: + if (con->con->ubnd == NULL) + value = +DBL_MAX; + else + value = con->ubnd; + break; + case DOT_STATUS: + value = con->stat; + break; + case DOT_VAL: + value = con->prim; + break; + case DOT_DUAL: + value = con->dual; + break; + default: + xassert(code != code); + } + delete_tuple(mpl, tuple); + } + break; +#endif + case O_IRAND224: + /* pseudo-random in [0, 2^24-1] */ + value = fp_irand224(mpl); + break; + case O_UNIFORM01: + /* pseudo-random in [0, 1) */ + value = fp_uniform01(mpl); + break; + case O_NORMAL01: + /* gaussian random, mu = 0, sigma = 1 */ + value = fp_normal01(mpl); + break; + case O_GMTIME: + /* current calendar time */ + value = fn_gmtime(mpl); + break; + case O_CVTNUM: + /* conversion to numeric */ + { SYMBOL *sym; + sym = eval_symbolic(mpl, code->arg.arg.x); +#if 0 /* 23/XI-2008 */ + if (sym->str != NULL) + error(mpl, "cannot convert %s to floating-point numbe" + "r", format_symbol(mpl, sym)); + value = sym->num; +#else + if (sym->str == NULL) + value = sym->num; + else + { if (str2num(sym->str, &value)) + error(mpl, "cannot convert %s to floating-point nu" + "mber", format_symbol(mpl, sym)); + } +#endif + delete_symbol(mpl, sym); + } + break; + case O_PLUS: + /* unary plus */ + value = + eval_numeric(mpl, code->arg.arg.x); + break; + case O_MINUS: + /* unary minus */ + value = - eval_numeric(mpl, code->arg.arg.x); + break; + case O_ABS: + /* absolute value */ + value = fabs(eval_numeric(mpl, code->arg.arg.x)); + break; + case O_CEIL: + /* round upward ("ceiling of x") */ + value = ceil(eval_numeric(mpl, code->arg.arg.x)); + break; + case O_FLOOR: + /* round downward ("floor of x") */ + value = floor(eval_numeric(mpl, code->arg.arg.x)); + break; + case O_EXP: + /* base-e exponential */ + value = fp_exp(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_LOG: + /* natural logarithm */ + value = fp_log(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_LOG10: + /* common (decimal) logarithm */ + value = fp_log10(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_SQRT: + /* square root */ + value = fp_sqrt(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_SIN: + /* trigonometric sine */ + value = fp_sin(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_COS: + /* trigonometric cosine */ + value = fp_cos(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_ATAN: + /* trigonometric arctangent (one argument) */ + value = fp_atan(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_ATAN2: + /* trigonometric arctangent (two arguments) */ + value = fp_atan2(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_ROUND: + /* round to nearest integer */ + value = fp_round(mpl, + eval_numeric(mpl, code->arg.arg.x), 0.0); + break; + case O_ROUND2: + /* round to n fractional digits */ + value = fp_round(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_TRUNC: + /* truncate to nearest integer */ + value = fp_trunc(mpl, + eval_numeric(mpl, code->arg.arg.x), 0.0); + break; + case O_TRUNC2: + /* truncate to n fractional digits */ + value = fp_trunc(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_ADD: + /* addition */ + value = fp_add(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_SUB: + /* subtraction */ + value = fp_sub(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_LESS: + /* non-negative subtraction */ + value = fp_less(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_MUL: + /* multiplication */ + value = fp_mul(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_DIV: + /* division */ + value = fp_div(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_IDIV: + /* quotient of exact division */ + value = fp_idiv(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_MOD: + /* remainder of exact division */ + value = fp_mod(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_POWER: + /* exponentiation (raise to power) */ + value = fp_power(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_UNIFORM: + /* pseudo-random in [a, b) */ + value = fp_uniform(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_NORMAL: + /* gaussian random, given mu and sigma */ + value = fp_normal(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_CARD: + { ELEMSET *set; + set = eval_elemset(mpl, code->arg.arg.x); + value = set->size; + delete_array(mpl, set); + } + break; + case O_LENGTH: + { SYMBOL *sym; + char str[MAX_LENGTH+1]; + sym = eval_symbolic(mpl, code->arg.arg.x); + if (sym->str == NULL) + sprintf(str, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, str); + delete_symbol(mpl, sym); + value = strlen(str); + } + break; + case O_STR2TIME: + { SYMBOL *sym; + char str[MAX_LENGTH+1], fmt[MAX_LENGTH+1]; + sym = eval_symbolic(mpl, code->arg.arg.x); + if (sym->str == NULL) + sprintf(str, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, str); + delete_symbol(mpl, sym); + sym = eval_symbolic(mpl, code->arg.arg.y); + if (sym->str == NULL) + sprintf(fmt, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, fmt); + delete_symbol(mpl, sym); + value = fn_str2time(mpl, str, fmt); + } + break; + case O_FORK: + /* if-then-else */ + if (eval_logical(mpl, code->arg.arg.x)) + value = eval_numeric(mpl, code->arg.arg.y); + else if (code->arg.arg.z == NULL) + value = 0.0; + else + value = eval_numeric(mpl, code->arg.arg.z); + break; + case O_MIN: + /* minimal value (n-ary) */ + { ARG_LIST *e; + double temp; + value = +DBL_MAX; + for (e = code->arg.list; e != NULL; e = e->next) + { temp = eval_numeric(mpl, e->x); + if (value > temp) value = temp; + } + } + break; + case O_MAX: + /* maximal value (n-ary) */ + { ARG_LIST *e; + double temp; + value = -DBL_MAX; + for (e = code->arg.list; e != NULL; e = e->next) + { temp = eval_numeric(mpl, e->x); + if (value < temp) value = temp; + } + } + break; + case O_SUM: + /* summation over domain */ + { struct iter_num_info _info, *info = &_info; + info->code = code; + info->value = 0.0; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_num_func); + value = info->value; + } + break; + case O_PROD: + /* multiplication over domain */ + { struct iter_num_info _info, *info = &_info; + info->code = code; + info->value = 1.0; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_num_func); + value = info->value; + } + break; + case O_MINIMUM: + /* minimum over domain */ + { struct iter_num_info _info, *info = &_info; + info->code = code; + info->value = +DBL_MAX; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_num_func); + if (info->value == +DBL_MAX) + error(mpl, "min{} over empty set; result undefined"); + value = info->value; + } + break; + case O_MAXIMUM: + /* maximum over domain */ + { struct iter_num_info _info, *info = &_info; + info->code = code; + info->value = -DBL_MAX; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_num_func); + if (info->value == -DBL_MAX) + error(mpl, "max{} over empty set; result undefined"); + value = info->value; + } + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.num = value; +done: return value; +} + +/*---------------------------------------------------------------------- +-- eval_symbolic - evaluate pseudo-code to determine symbolic value. +-- +-- This routine evaluates specified pseudo-code to determine resultant +-- symbolic value, which is returned on exit. */ + +SYMBOL *eval_symbolic(MPL *mpl, CODE *code) +{ SYMBOL *value; + xassert(code != NULL); + xassert(code->type == A_SYMBOLIC); + xassert(code->dim == 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = copy_symbol(mpl, code->value.sym); + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_STRING: + /* take character string */ + value = create_symbol_str(mpl, create_string(mpl, + code->arg.str)); + break; + case O_INDEX: + /* take dummy index */ + xassert(code->arg.index.slot->value != NULL); + value = copy_symbol(mpl, code->arg.index.slot->value); + break; + case O_MEMSYM: + /* take member of symbolic parameter */ + { TUPLE *tuple; + ARG_LIST *e; + tuple = create_tuple(mpl); + for (e = code->arg.par.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); + value = eval_member_sym(mpl, code->arg.par.par, tuple); + delete_tuple(mpl, tuple); + } + break; + case O_CVTSYM: + /* conversion to symbolic */ + value = create_symbol_num(mpl, eval_numeric(mpl, + code->arg.arg.x)); + break; + case O_CONCAT: + /* concatenation */ + value = concat_symbols(mpl, + eval_symbolic(mpl, code->arg.arg.x), + eval_symbolic(mpl, code->arg.arg.y)); + break; + case O_FORK: + /* if-then-else */ + if (eval_logical(mpl, code->arg.arg.x)) + value = eval_symbolic(mpl, code->arg.arg.y); + else if (code->arg.arg.z == NULL) + value = create_symbol_num(mpl, 0.0); + else + value = eval_symbolic(mpl, code->arg.arg.z); + break; + case O_SUBSTR: + case O_SUBSTR3: + { double pos, len; + char str[MAX_LENGTH+1]; + value = eval_symbolic(mpl, code->arg.arg.x); + if (value->str == NULL) + sprintf(str, "%.*g", DBL_DIG, value->num); + else + fetch_string(mpl, value->str, str); + delete_symbol(mpl, value); + if (code->op == O_SUBSTR) + { pos = eval_numeric(mpl, code->arg.arg.y); + if (pos != floor(pos)) + error(mpl, "substr('...', %.*g); non-integer secon" + "d argument", DBL_DIG, pos); + if (pos < 1 || pos > strlen(str) + 1) + error(mpl, "substr('...', %.*g); substring out of " + "range", DBL_DIG, pos); + } + else + { pos = eval_numeric(mpl, code->arg.arg.y); + len = eval_numeric(mpl, code->arg.arg.z); + if (pos != floor(pos) || len != floor(len)) + error(mpl, "substr('...', %.*g, %.*g); non-integer" + " second and/or third argument", DBL_DIG, pos, + DBL_DIG, len); + if (pos < 1 || len < 0 || pos + len > strlen(str) + 1) + error(mpl, "substr('...', %.*g, %.*g); substring o" + "ut of range", DBL_DIG, pos, DBL_DIG, len); + str[(int)pos + (int)len - 1] = '\0'; + } + value = create_symbol_str(mpl, create_string(mpl, str + + (int)pos - 1)); + } + break; + case O_TIME2STR: + { double num; + SYMBOL *sym; + char str[MAX_LENGTH+1], fmt[MAX_LENGTH+1]; + num = eval_numeric(mpl, code->arg.arg.x); + sym = eval_symbolic(mpl, code->arg.arg.y); + if (sym->str == NULL) + sprintf(fmt, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, fmt); + delete_symbol(mpl, sym); + fn_time2str(mpl, str, num, fmt); + value = create_symbol_str(mpl, create_string(mpl, str)); + } + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.sym = copy_symbol(mpl, value); +done: return value; +} + +/*---------------------------------------------------------------------- +-- eval_logical - evaluate pseudo-code to determine logical value. +-- +-- This routine evaluates specified pseudo-code to determine resultant +-- logical value, which is returned on exit. */ + +struct iter_log_info +{ /* working info used by the routine iter_log_func */ + CODE *code; + /* pseudo-code for iterated operation to be performed */ + int value; + /* resultant value */ +}; + +static int iter_log_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine used to perform iterated operation + on logical "integrand" within domain scope */ + struct iter_log_info *info = _info; + int ret = 0; + switch (info->code->op) + { case O_FORALL: + /* conjunction over domain */ + info->value &= eval_logical(mpl, info->code->arg.loop.x); + if (!info->value) ret = 1; + break; + case O_EXISTS: + /* disjunction over domain */ + info->value |= eval_logical(mpl, info->code->arg.loop.x); + if (info->value) ret = 1; + break; + default: + xassert(info != info); + } + return ret; +} + +int eval_logical(MPL *mpl, CODE *code) +{ int value; + xassert(code->type == A_LOGICAL); + xassert(code->dim == 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = code->value.bit; + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_CVTLOG: + /* conversion to logical */ + value = (eval_numeric(mpl, code->arg.arg.x) != 0.0); + break; + case O_NOT: + /* negation (logical "not") */ + value = !eval_logical(mpl, code->arg.arg.x); + break; + case O_LT: + /* comparison on 'less than' */ +#if 0 /* 02/VIII-2008 */ + value = (eval_numeric(mpl, code->arg.arg.x) < + eval_numeric(mpl, code->arg.arg.y)); +#else + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) < + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) < 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } +#endif + break; + case O_LE: + /* comparison on 'not greater than' */ +#if 0 /* 02/VIII-2008 */ + value = (eval_numeric(mpl, code->arg.arg.x) <= + eval_numeric(mpl, code->arg.arg.y)); +#else + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) <= + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) <= 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } +#endif + break; + case O_EQ: + /* comparison on 'equal to' */ + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) == + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) == 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } + break; + case O_GE: + /* comparison on 'not less than' */ +#if 0 /* 02/VIII-2008 */ + value = (eval_numeric(mpl, code->arg.arg.x) >= + eval_numeric(mpl, code->arg.arg.y)); +#else + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) >= + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) >= 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } +#endif + break; + case O_GT: + /* comparison on 'greater than' */ +#if 0 /* 02/VIII-2008 */ + value = (eval_numeric(mpl, code->arg.arg.x) > + eval_numeric(mpl, code->arg.arg.y)); +#else + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) > + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) > 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } +#endif + break; + case O_NE: + /* comparison on 'not equal to' */ + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) != + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) != 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } + break; + case O_AND: + /* conjunction (logical "and") */ + value = eval_logical(mpl, code->arg.arg.x) && + eval_logical(mpl, code->arg.arg.y); + break; + case O_OR: + /* disjunction (logical "or") */ + value = eval_logical(mpl, code->arg.arg.x) || + eval_logical(mpl, code->arg.arg.y); + break; + case O_IN: + /* test on 'x in Y' */ + { TUPLE *tuple; + tuple = eval_tuple(mpl, code->arg.arg.x); + value = is_member(mpl, code->arg.arg.y, tuple); + delete_tuple(mpl, tuple); + } + break; + case O_NOTIN: + /* test on 'x not in Y' */ + { TUPLE *tuple; + tuple = eval_tuple(mpl, code->arg.arg.x); + value = !is_member(mpl, code->arg.arg.y, tuple); + delete_tuple(mpl, tuple); + } + break; + case O_WITHIN: + /* test on 'X within Y' */ + { ELEMSET *set; + MEMBER *memb; + set = eval_elemset(mpl, code->arg.arg.x); + value = 1; + for (memb = set->head; memb != NULL; memb = memb->next) + { if (!is_member(mpl, code->arg.arg.y, memb->tuple)) + { value = 0; + break; + } + } + delete_elemset(mpl, set); + } + break; + case O_NOTWITHIN: + /* test on 'X not within Y' */ + { ELEMSET *set; + MEMBER *memb; + set = eval_elemset(mpl, code->arg.arg.x); + value = 1; + for (memb = set->head; memb != NULL; memb = memb->next) + { if (is_member(mpl, code->arg.arg.y, memb->tuple)) + { value = 0; + break; + } + } + delete_elemset(mpl, set); + } + break; + case O_FORALL: + /* conjunction (A-quantification) */ + { struct iter_log_info _info, *info = &_info; + info->code = code; + info->value = 1; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_log_func); + value = info->value; + } + break; + case O_EXISTS: + /* disjunction (E-quantification) */ + { struct iter_log_info _info, *info = &_info; + info->code = code; + info->value = 0; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_log_func); + value = info->value; + } + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.bit = value; +done: return value; +} + +/*---------------------------------------------------------------------- +-- eval_tuple - evaluate pseudo-code to construct n-tuple. +-- +-- This routine evaluates specified pseudo-code to construct resultant +-- n-tuple, which is returned on exit. */ + +TUPLE *eval_tuple(MPL *mpl, CODE *code) +{ TUPLE *value; + xassert(code != NULL); + xassert(code->type == A_TUPLE); + xassert(code->dim > 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = copy_tuple(mpl, code->value.tuple); + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_TUPLE: + /* make n-tuple */ + { ARG_LIST *e; + value = create_tuple(mpl); + for (e = code->arg.list; e != NULL; e = e->next) + value = expand_tuple(mpl, value, eval_symbolic(mpl, + e->x)); + } + break; + case O_CVTTUP: + /* convert to 1-tuple */ + value = expand_tuple(mpl, create_tuple(mpl), + eval_symbolic(mpl, code->arg.arg.x)); + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.tuple = copy_tuple(mpl, value); +done: return value; +} + +/*---------------------------------------------------------------------- +-- eval_elemset - evaluate pseudo-code to construct elemental set. +-- +-- This routine evaluates specified pseudo-code to construct resultant +-- elemental set, which is returned on exit. */ + +struct iter_set_info +{ /* working info used by the routine iter_set_func */ + CODE *code; + /* pseudo-code for iterated operation to be performed */ + ELEMSET *value; + /* resultant value */ +}; + +static int iter_set_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine used to perform iterated operation + on n-tuple "integrand" within domain scope */ + struct iter_set_info *info = _info; + TUPLE *tuple; + switch (info->code->op) + { case O_SETOF: + /* compute next n-tuple and add it to the set; in this case + duplicate n-tuples are silently ignored */ + tuple = eval_tuple(mpl, info->code->arg.loop.x); + if (find_tuple(mpl, info->value, tuple) == NULL) + add_tuple(mpl, info->value, tuple); + else + delete_tuple(mpl, tuple); + break; + case O_BUILD: + /* construct next n-tuple using current values assigned to + *free* dummy indices as its components and add it to the + set; in this case duplicate n-tuples cannot appear */ + add_tuple(mpl, info->value, get_domain_tuple(mpl, + info->code->arg.loop.domain)); + break; + default: + xassert(info != info); + } + return 0; +} + +ELEMSET *eval_elemset(MPL *mpl, CODE *code) +{ ELEMSET *value; + xassert(code != NULL); + xassert(code->type == A_ELEMSET); + xassert(code->dim > 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = copy_elemset(mpl, code->value.set); + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_MEMSET: + /* take member of set */ + { TUPLE *tuple; + ARG_LIST *e; + tuple = create_tuple(mpl); + for (e = code->arg.set.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); + value = copy_elemset(mpl, + eval_member_set(mpl, code->arg.set.set, tuple)); + delete_tuple(mpl, tuple); + } + break; + case O_MAKE: + /* make elemental set of n-tuples */ + { ARG_LIST *e; + value = create_elemset(mpl, code->dim); + for (e = code->arg.list; e != NULL; e = e->next) + check_then_add(mpl, value, eval_tuple(mpl, e->x)); + } + break; + case O_UNION: + /* union of two elemental sets */ + value = set_union(mpl, + eval_elemset(mpl, code->arg.arg.x), + eval_elemset(mpl, code->arg.arg.y)); + break; + case O_DIFF: + /* difference between two elemental sets */ + value = set_diff(mpl, + eval_elemset(mpl, code->arg.arg.x), + eval_elemset(mpl, code->arg.arg.y)); + break; + case O_SYMDIFF: + /* symmetric difference between two elemental sets */ + value = set_symdiff(mpl, + eval_elemset(mpl, code->arg.arg.x), + eval_elemset(mpl, code->arg.arg.y)); + break; + case O_INTER: + /* intersection of two elemental sets */ + value = set_inter(mpl, + eval_elemset(mpl, code->arg.arg.x), + eval_elemset(mpl, code->arg.arg.y)); + break; + case O_CROSS: + /* cross (Cartesian) product of two elemental sets */ + value = set_cross(mpl, + eval_elemset(mpl, code->arg.arg.x), + eval_elemset(mpl, code->arg.arg.y)); + break; + case O_DOTS: + /* build "arithmetic" elemental set */ + value = create_arelset(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y), + code->arg.arg.z == NULL ? 1.0 : eval_numeric(mpl, + code->arg.arg.z)); + break; + case O_FORK: + /* if-then-else */ + if (eval_logical(mpl, code->arg.arg.x)) + value = eval_elemset(mpl, code->arg.arg.y); + else + value = eval_elemset(mpl, code->arg.arg.z); + break; + case O_SETOF: + /* compute elemental set */ + { struct iter_set_info _info, *info = &_info; + info->code = code; + info->value = create_elemset(mpl, code->dim); + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_set_func); + value = info->value; + } + break; + case O_BUILD: + /* build elemental set identical to domain set */ + { struct iter_set_info _info, *info = &_info; + info->code = code; + info->value = create_elemset(mpl, code->dim); + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_set_func); + value = info->value; + } + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.set = copy_elemset(mpl, value); +done: return value; +} + +/*---------------------------------------------------------------------- +-- is_member - check if n-tuple is in set specified by pseudo-code. +-- +-- This routine checks if given n-tuple is a member of elemental set +-- specified in the form of pseudo-code (i.e. by expression). +-- +-- The n-tuple may have more components that dimension of the elemental +-- set, in which case the extra components are ignored. */ + +static void null_func(MPL *mpl, void *info) +{ /* this is dummy routine used to enter the domain scope */ + xassert(mpl == mpl); + xassert(info == NULL); + return; +} + +int is_member(MPL *mpl, CODE *code, TUPLE *tuple) +{ int value; + xassert(code != NULL); + xassert(code->type == A_ELEMSET); + xassert(code->dim > 0); + xassert(tuple != NULL); + switch (code->op) + { case O_MEMSET: + /* check if given n-tuple is member of elemental set, which + is assigned to member of model set */ + { ARG_LIST *e; + TUPLE *temp; + ELEMSET *set; + /* evaluate reference to elemental set */ + temp = create_tuple(mpl); + for (e = code->arg.set.list; e != NULL; e = e->next) + temp = expand_tuple(mpl, temp, eval_symbolic(mpl, + e->x)); + set = eval_member_set(mpl, code->arg.set.set, temp); + delete_tuple(mpl, temp); + /* check if the n-tuple is contained in the set array */ + temp = build_subtuple(mpl, tuple, set->dim); + value = (find_tuple(mpl, set, temp) != NULL); + delete_tuple(mpl, temp); + } + break; + case O_MAKE: + /* check if given n-tuple is member of literal set */ + { ARG_LIST *e; + TUPLE *temp, *that; + value = 0; + temp = build_subtuple(mpl, tuple, code->dim); + for (e = code->arg.list; e != NULL; e = e->next) + { that = eval_tuple(mpl, e->x); + value = (compare_tuples(mpl, temp, that) == 0); + delete_tuple(mpl, that); + if (value) break; + } + delete_tuple(mpl, temp); + } + break; + case O_UNION: + value = is_member(mpl, code->arg.arg.x, tuple) || + is_member(mpl, code->arg.arg.y, tuple); + break; + case O_DIFF: + value = is_member(mpl, code->arg.arg.x, tuple) && + !is_member(mpl, code->arg.arg.y, tuple); + break; + case O_SYMDIFF: + { int in1 = is_member(mpl, code->arg.arg.x, tuple); + int in2 = is_member(mpl, code->arg.arg.y, tuple); + value = (in1 && !in2) || (!in1 && in2); + } + break; + case O_INTER: + value = is_member(mpl, code->arg.arg.x, tuple) && + is_member(mpl, code->arg.arg.y, tuple); + break; + case O_CROSS: + { int j; + value = is_member(mpl, code->arg.arg.x, tuple); + if (value) + { for (j = 1; j <= code->arg.arg.x->dim; j++) + { xassert(tuple != NULL); + tuple = tuple->next; + } + value = is_member(mpl, code->arg.arg.y, tuple); + } + } + break; + case O_DOTS: + /* check if given 1-tuple is member of "arithmetic" set */ + { int j; + double x, t0, tf, dt; + xassert(code->dim == 1); + /* compute "parameters" of the "arithmetic" set */ + t0 = eval_numeric(mpl, code->arg.arg.x); + tf = eval_numeric(mpl, code->arg.arg.y); + if (code->arg.arg.z == NULL) + dt = 1.0; + else + dt = eval_numeric(mpl, code->arg.arg.z); + /* make sure the parameters are correct */ + arelset_size(mpl, t0, tf, dt); + /* if component of 1-tuple is symbolic, not numeric, the + 1-tuple cannot be member of "arithmetic" set */ + xassert(tuple->sym != NULL); + if (tuple->sym->str != NULL) + { value = 0; + break; + } + /* determine numeric value of the component */ + x = tuple->sym->num; + /* if the component value is out of the set range, the + 1-tuple is not in the set */ + if (dt > 0.0 && !(t0 <= x && x <= tf) || + dt < 0.0 && !(tf <= x && x <= t0)) + { value = 0; + break; + } + /* estimate ordinal number of the 1-tuple in the set */ + j = (int)(((x - t0) / dt) + 0.5) + 1; + /* perform the main check */ + value = (arelset_member(mpl, t0, tf, dt, j) == x); + } + break; + case O_FORK: + /* check if given n-tuple is member of conditional set */ + if (eval_logical(mpl, code->arg.arg.x)) + value = is_member(mpl, code->arg.arg.y, tuple); + else + value = is_member(mpl, code->arg.arg.z, tuple); + break; + case O_SETOF: + /* check if given n-tuple is member of computed set */ + /* it is not clear how to efficiently perform the check not + computing the entire elemental set :+( */ + error(mpl, "implementation restriction; in/within setof{} n" + "ot allowed"); + break; + case O_BUILD: + /* check if given n-tuple is member of domain set */ + { TUPLE *temp; + temp = build_subtuple(mpl, tuple, code->dim); + /* try to enter the domain scope; if it is successful, + the n-tuple is in the domain set */ + value = (eval_within_domain(mpl, code->arg.loop.domain, + temp, NULL, null_func) == 0); + delete_tuple(mpl, temp); + } + break; + default: + xassert(code != code); + } + return value; +} + +/*---------------------------------------------------------------------- +-- eval_formula - evaluate pseudo-code to construct linear form. +-- +-- This routine evaluates specified pseudo-code to construct resultant +-- linear form, which is returned on exit. */ + +struct iter_form_info +{ /* working info used by the routine iter_form_func */ + CODE *code; + /* pseudo-code for iterated operation to be performed */ + FORMULA *value; + /* resultant value */ + FORMULA *tail; + /* pointer to the last term */ +}; + +static int iter_form_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine used to perform iterated operation + on linear form "integrand" within domain scope */ + struct iter_form_info *info = _info; + switch (info->code->op) + { case O_SUM: + /* summation over domain */ +#if 0 + info->value = + linear_comb(mpl, + +1.0, info->value, + +1.0, eval_formula(mpl, info->code->arg.loop.x)); +#else + /* the routine linear_comb needs to look through all terms + of both linear forms to reduce identical terms, so using + it here is not a good idea (for example, evaluation of + sum{i in 1..n} x[i] required quadratic time); the better + idea is to gather all terms of the integrand in one list + and reduce identical terms only once after all terms of + the resultant linear form have been evaluated */ + { FORMULA *form, *term; + form = eval_formula(mpl, info->code->arg.loop.x); + if (info->value == NULL) + { xassert(info->tail == NULL); + info->value = form; + } + else + { xassert(info->tail != NULL); + info->tail->next = form; + } + for (term = form; term != NULL; term = term->next) + info->tail = term; + } +#endif + break; + default: + xassert(info != info); + } + return 0; +} + +FORMULA *eval_formula(MPL *mpl, CODE *code) +{ FORMULA *value; + xassert(code != NULL); + xassert(code->type == A_FORMULA); + xassert(code->dim == 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = copy_formula(mpl, code->value.form); + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_MEMVAR: + /* take member of variable */ + { TUPLE *tuple; + ARG_LIST *e; + tuple = create_tuple(mpl); + for (e = code->arg.var.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); +#if 1 /* 15/V-2010 */ + xassert(code->arg.var.suff == DOT_NONE); +#endif + value = single_variable(mpl, + eval_member_var(mpl, code->arg.var.var, tuple)); + delete_tuple(mpl, tuple); + } + break; + case O_CVTLFM: + /* convert to linear form */ + value = constant_term(mpl, eval_numeric(mpl, + code->arg.arg.x)); + break; + case O_PLUS: + /* unary plus */ + value = linear_comb(mpl, + 0.0, constant_term(mpl, 0.0), + +1.0, eval_formula(mpl, code->arg.arg.x)); + break; + case O_MINUS: + /* unary minus */ + value = linear_comb(mpl, + 0.0, constant_term(mpl, 0.0), + -1.0, eval_formula(mpl, code->arg.arg.x)); + break; + case O_ADD: + /* addition */ + value = linear_comb(mpl, + +1.0, eval_formula(mpl, code->arg.arg.x), + +1.0, eval_formula(mpl, code->arg.arg.y)); + break; + case O_SUB: + /* subtraction */ + value = linear_comb(mpl, + +1.0, eval_formula(mpl, code->arg.arg.x), + -1.0, eval_formula(mpl, code->arg.arg.y)); + break; + case O_MUL: + /* multiplication */ + xassert(code->arg.arg.x != NULL); + xassert(code->arg.arg.y != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + { xassert(code->arg.arg.y->type == A_FORMULA); + value = linear_comb(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_formula(mpl, code->arg.arg.y), + 0.0, constant_term(mpl, 0.0)); + } + else + { xassert(code->arg.arg.x->type == A_FORMULA); + xassert(code->arg.arg.y->type == A_NUMERIC); + value = linear_comb(mpl, + eval_numeric(mpl, code->arg.arg.y), + eval_formula(mpl, code->arg.arg.x), + 0.0, constant_term(mpl, 0.0)); + } + break; + case O_DIV: + /* division */ + value = linear_comb(mpl, + fp_div(mpl, 1.0, eval_numeric(mpl, code->arg.arg.y)), + eval_formula(mpl, code->arg.arg.x), + 0.0, constant_term(mpl, 0.0)); + break; + case O_FORK: + /* if-then-else */ + if (eval_logical(mpl, code->arg.arg.x)) + value = eval_formula(mpl, code->arg.arg.y); + else if (code->arg.arg.z == NULL) + value = constant_term(mpl, 0.0); + else + value = eval_formula(mpl, code->arg.arg.z); + break; + case O_SUM: + /* summation over domain */ + { struct iter_form_info _info, *info = &_info; + info->code = code; + info->value = constant_term(mpl, 0.0); + info->tail = NULL; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_form_func); + value = reduce_terms(mpl, info->value); + } + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.form = copy_formula(mpl, value); +done: return value; +} + +/*---------------------------------------------------------------------- +-- clean_code - clean pseudo-code. +-- +-- This routine recursively cleans specified pseudo-code that assumes +-- deleting all temporary resultant values. */ + +void clean_code(MPL *mpl, CODE *code) +{ ARG_LIST *e; + /* if no pseudo-code is specified, do nothing */ + if (code == NULL) goto done; + /* if resultant value is valid (exists), delete it */ + if (code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* recursively clean pseudo-code for operands */ + switch (code->op) + { case O_NUMBER: + case O_STRING: + case O_INDEX: + break; + case O_MEMNUM: + case O_MEMSYM: + for (e = code->arg.par.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; + case O_MEMSET: + for (e = code->arg.set.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; + case O_MEMVAR: + for (e = code->arg.var.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; +#if 1 /* 15/V-2010 */ + case O_MEMCON: + for (e = code->arg.con.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; +#endif + case O_TUPLE: + case O_MAKE: + for (e = code->arg.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; + case O_SLICE: + xassert(code != code); + case O_IRAND224: + case O_UNIFORM01: + case O_NORMAL01: + case O_GMTIME: + break; + case O_CVTNUM: + case O_CVTSYM: + case O_CVTLOG: + case O_CVTTUP: + case O_CVTLFM: + case O_PLUS: + case O_MINUS: + case O_NOT: + case O_ABS: + case O_CEIL: + case O_FLOOR: + case O_EXP: + case O_LOG: + case O_LOG10: + case O_SQRT: + case O_SIN: + case O_COS: + case O_ATAN: + case O_ROUND: + case O_TRUNC: + case O_CARD: + case O_LENGTH: + /* unary operation */ + clean_code(mpl, code->arg.arg.x); + break; + case O_ADD: + case O_SUB: + case O_LESS: + case O_MUL: + case O_DIV: + case O_IDIV: + case O_MOD: + case O_POWER: + case O_ATAN2: + case O_ROUND2: + case O_TRUNC2: + case O_UNIFORM: + case O_NORMAL: + case O_CONCAT: + case O_LT: + case O_LE: + case O_EQ: + case O_GE: + case O_GT: + case O_NE: + case O_AND: + case O_OR: + case O_UNION: + case O_DIFF: + case O_SYMDIFF: + case O_INTER: + case O_CROSS: + case O_IN: + case O_NOTIN: + case O_WITHIN: + case O_NOTWITHIN: + case O_SUBSTR: + case O_STR2TIME: + case O_TIME2STR: + /* binary operation */ + clean_code(mpl, code->arg.arg.x); + clean_code(mpl, code->arg.arg.y); + break; + case O_DOTS: + case O_FORK: + case O_SUBSTR3: + /* ternary operation */ + clean_code(mpl, code->arg.arg.x); + clean_code(mpl, code->arg.arg.y); + clean_code(mpl, code->arg.arg.z); + break; + case O_MIN: + case O_MAX: + /* n-ary operation */ + for (e = code->arg.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; + case O_SUM: + case O_PROD: + case O_MINIMUM: + case O_MAXIMUM: + case O_FORALL: + case O_EXISTS: + case O_SETOF: + case O_BUILD: + /* iterated operation */ + clean_domain(mpl, code->arg.loop.domain); + clean_code(mpl, code->arg.loop.x); + break; + default: + xassert(code->op != code->op); + } +done: return; +} + +#if 1 /* 11/II-2008 */ +/**********************************************************************/ +/* * * DATA TABLES * * */ +/**********************************************************************/ + +int mpl_tab_num_args(TABDCA *dca) +{ /* returns the number of arguments */ + return dca->na; +} + +const char *mpl_tab_get_arg(TABDCA *dca, int k) +{ /* returns pointer to k-th argument */ + xassert(1 <= k && k <= dca->na); + return dca->arg[k]; +} + +int mpl_tab_num_flds(TABDCA *dca) +{ /* returns the number of fields */ + return dca->nf; +} + +const char *mpl_tab_get_name(TABDCA *dca, int k) +{ /* returns pointer to name of k-th field */ + xassert(1 <= k && k <= dca->nf); + return dca->name[k]; +} + +int mpl_tab_get_type(TABDCA *dca, int k) +{ /* returns type of k-th field */ + xassert(1 <= k && k <= dca->nf); + return dca->type[k]; +} + +double mpl_tab_get_num(TABDCA *dca, int k) +{ /* returns numeric value of k-th field */ + xassert(1 <= k && k <= dca->nf); + xassert(dca->type[k] == 'N'); + return dca->num[k]; +} + +const char *mpl_tab_get_str(TABDCA *dca, int k) +{ /* returns pointer to string value of k-th field */ + xassert(1 <= k && k <= dca->nf); + xassert(dca->type[k] == 'S'); + xassert(dca->str[k] != NULL); + return dca->str[k]; +} + +void mpl_tab_set_num(TABDCA *dca, int k, double num) +{ /* assign numeric value to k-th field */ + xassert(1 <= k && k <= dca->nf); + xassert(dca->type[k] == '?'); + dca->type[k] = 'N'; + dca->num[k] = num; + return; +} + +void mpl_tab_set_str(TABDCA *dca, int k, const char *str) +{ /* assign string value to k-th field */ + xassert(1 <= k && k <= dca->nf); + xassert(dca->type[k] == '?'); + xassert(strlen(str) <= MAX_LENGTH); + xassert(dca->str[k] != NULL); + dca->type[k] = 'S'; + strcpy(dca->str[k], str); + return; +} + +static int write_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + TABLE *tab = info; + TABDCA *dca = mpl->dca; + TABOUT *out; + SYMBOL *sym; + int k; + char buf[MAX_LENGTH+1]; + /* evaluate field values */ + k = 0; + for (out = tab->u.out.list; out != NULL; out = out->next) + { k++; + switch (out->code->type) + { case A_NUMERIC: + dca->type[k] = 'N'; + dca->num[k] = eval_numeric(mpl, out->code); + dca->str[k][0] = '\0'; + break; + case A_SYMBOLIC: + sym = eval_symbolic(mpl, out->code); + if (sym->str == NULL) + { dca->type[k] = 'N'; + dca->num[k] = sym->num; + dca->str[k][0] = '\0'; + } + else + { dca->type[k] = 'S'; + dca->num[k] = 0.0; + fetch_string(mpl, sym->str, buf); + strcpy(dca->str[k], buf); + } + delete_symbol(mpl, sym); + break; + default: + xassert(out != out); + } + } + /* write record to output table */ + mpl_tab_drv_write(mpl); + return 0; +} + +void execute_table(MPL *mpl, TABLE *tab) +{ /* execute table statement */ + TABARG *arg; + TABFLD *fld; + TABIN *in; + TABOUT *out; + TABDCA *dca; + SET *set; + int k; + char buf[MAX_LENGTH+1]; + /* allocate table driver communication area */ + xassert(mpl->dca == NULL); + mpl->dca = dca = xmalloc(sizeof(TABDCA)); + dca->id = 0; + dca->link = NULL; + dca->na = 0; + dca->arg = NULL; + dca->nf = 0; + dca->name = NULL; + dca->type = NULL; + dca->num = NULL; + dca->str = NULL; + /* allocate arguments */ + xassert(dca->na == 0); + for (arg = tab->arg; arg != NULL; arg = arg->next) + dca->na++; + dca->arg = xcalloc(1+dca->na, sizeof(char *)); +#if 1 /* 28/IX-2008 */ + for (k = 1; k <= dca->na; k++) dca->arg[k] = NULL; +#endif + /* evaluate argument values */ + k = 0; + for (arg = tab->arg; arg != NULL; arg = arg->next) + { SYMBOL *sym; + k++; + xassert(arg->code->type == A_SYMBOLIC); + sym = eval_symbolic(mpl, arg->code); + if (sym->str == NULL) + sprintf(buf, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, buf); + delete_symbol(mpl, sym); + dca->arg[k] = xmalloc(strlen(buf)+1); + strcpy(dca->arg[k], buf); + } + /* perform table input/output */ + switch (tab->type) + { case A_INPUT: goto read_table; + case A_OUTPUT: goto write_table; + default: xassert(tab != tab); + } +read_table: + /* read data from input table */ + /* add the only member to the control set and assign it empty + elemental set */ + set = tab->u.in.set; + if (set != NULL) + { if (set->data) + error(mpl, "%s already provided with data", set->name); + xassert(set->array->head == NULL); + add_member(mpl, set->array, NULL)->value.set = + create_elemset(mpl, set->dimen); + set->data = 1; + } + /* check parameters specified in the input list */ + for (in = tab->u.in.list; in != NULL; in = in->next) + { if (in->par->data) + error(mpl, "%s already provided with data", in->par->name); + in->par->data = 1; + } + /* allocate and initialize fields */ + xassert(dca->nf == 0); + for (fld = tab->u.in.fld; fld != NULL; fld = fld->next) + dca->nf++; + for (in = tab->u.in.list; in != NULL; in = in->next) + dca->nf++; + dca->name = xcalloc(1+dca->nf, sizeof(char *)); + dca->type = xcalloc(1+dca->nf, sizeof(int)); + dca->num = xcalloc(1+dca->nf, sizeof(double)); + dca->str = xcalloc(1+dca->nf, sizeof(char *)); + k = 0; + for (fld = tab->u.in.fld; fld != NULL; fld = fld->next) + { k++; + dca->name[k] = fld->name; + dca->type[k] = '?'; + dca->num[k] = 0.0; + dca->str[k] = xmalloc(MAX_LENGTH+1); + dca->str[k][0] = '\0'; + } + for (in = tab->u.in.list; in != NULL; in = in->next) + { k++; + dca->name[k] = in->name; + dca->type[k] = '?'; + dca->num[k] = 0.0; + dca->str[k] = xmalloc(MAX_LENGTH+1); + dca->str[k][0] = '\0'; + } + /* open input table */ + mpl_tab_drv_open(mpl, 'R'); + /* read and process records */ + for (;;) + { TUPLE *tup; + /* reset field types */ + for (k = 1; k <= dca->nf; k++) + dca->type[k] = '?'; + /* read next record */ + if (mpl_tab_drv_read(mpl)) break; + /* all fields must be set by the driver */ + for (k = 1; k <= dca->nf; k++) + { if (dca->type[k] == '?') + error(mpl, "field %s missing in input table", + dca->name[k]); + } + /* construct n-tuple */ + tup = create_tuple(mpl); + k = 0; + for (fld = tab->u.in.fld; fld != NULL; fld = fld->next) + { k++; + xassert(k <= dca->nf); + switch (dca->type[k]) + { case 'N': + tup = expand_tuple(mpl, tup, create_symbol_num(mpl, + dca->num[k])); + break; + case 'S': + xassert(strlen(dca->str[k]) <= MAX_LENGTH); + tup = expand_tuple(mpl, tup, create_symbol_str(mpl, + create_string(mpl, dca->str[k]))); + break; + default: + xassert(dca != dca); + } + } + /* add n-tuple just read to the control set */ + if (tab->u.in.set != NULL) + check_then_add(mpl, tab->u.in.set->array->head->value.set, + copy_tuple(mpl, tup)); + /* assign values to the parameters in the input list */ + for (in = tab->u.in.list; in != NULL; in = in->next) + { MEMBER *memb; + k++; + xassert(k <= dca->nf); + /* there must be no member with the same n-tuple */ + if (find_member(mpl, in->par->array, tup) != NULL) + error(mpl, "%s%s already defined", in->par->name, + format_tuple(mpl, '[', tup)); + /* create new parameter member with given n-tuple */ + memb = add_member(mpl, in->par->array, copy_tuple(mpl, tup)) + ; + /* assign value to the parameter member */ + switch (in->par->type) + { case A_NUMERIC: + case A_INTEGER: + case A_BINARY: + if (dca->type[k] != 'N') + error(mpl, "%s requires numeric data", + in->par->name); + memb->value.num = dca->num[k]; + break; + case A_SYMBOLIC: + switch (dca->type[k]) + { case 'N': + memb->value.sym = create_symbol_num(mpl, + dca->num[k]); + break; + case 'S': + xassert(strlen(dca->str[k]) <= MAX_LENGTH); + memb->value.sym = create_symbol_str(mpl, + create_string(mpl,dca->str[k])); + break; + default: + xassert(dca != dca); + } + break; + default: + xassert(in != in); + } + } + /* n-tuple is no more needed */ + delete_tuple(mpl, tup); + } + /* close input table */ + mpl_tab_drv_close(mpl); + goto done; +write_table: + /* write data to output table */ + /* allocate and initialize fields */ + xassert(dca->nf == 0); + for (out = tab->u.out.list; out != NULL; out = out->next) + dca->nf++; + dca->name = xcalloc(1+dca->nf, sizeof(char *)); + dca->type = xcalloc(1+dca->nf, sizeof(int)); + dca->num = xcalloc(1+dca->nf, sizeof(double)); + dca->str = xcalloc(1+dca->nf, sizeof(char *)); + k = 0; + for (out = tab->u.out.list; out != NULL; out = out->next) + { k++; + dca->name[k] = out->name; + dca->type[k] = '?'; + dca->num[k] = 0.0; + dca->str[k] = xmalloc(MAX_LENGTH+1); + dca->str[k][0] = '\0'; + } + /* open output table */ + mpl_tab_drv_open(mpl, 'W'); + /* evaluate fields and write records */ + loop_within_domain(mpl, tab->u.out.domain, tab, write_func); + /* close output table */ + mpl_tab_drv_close(mpl); +done: /* free table driver communication area */ + free_dca(mpl); + return; +} + +void free_dca(MPL *mpl) +{ /* free table driver communucation area */ + TABDCA *dca = mpl->dca; + int k; + if (dca != NULL) + { if (dca->link != NULL) + mpl_tab_drv_close(mpl); + if (dca->arg != NULL) + { for (k = 1; k <= dca->na; k++) +#if 1 /* 28/IX-2008 */ + if (dca->arg[k] != NULL) +#endif + xfree(dca->arg[k]); + xfree(dca->arg); + } + if (dca->name != NULL) xfree(dca->name); + if (dca->type != NULL) xfree(dca->type); + if (dca->num != NULL) xfree(dca->num); + if (dca->str != NULL) + { for (k = 1; k <= dca->nf; k++) + xfree(dca->str[k]); + xfree(dca->str); + } + xfree(dca), mpl->dca = NULL; + } + return; +} + +void clean_table(MPL *mpl, TABLE *tab) +{ /* clean table statement */ + TABARG *arg; + TABOUT *out; + /* clean string list */ + for (arg = tab->arg; arg != NULL; arg = arg->next) + clean_code(mpl, arg->code); + switch (tab->type) + { case A_INPUT: + break; + case A_OUTPUT: + /* clean subscript domain */ + clean_domain(mpl, tab->u.out.domain); + /* clean output list */ + for (out = tab->u.out.list; out != NULL; out = out->next) + clean_code(mpl, out->code); + break; + default: + xassert(tab != tab); + } + return; +} +#endif + +/**********************************************************************/ +/* * * MODEL STATEMENTS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- execute_check - execute check statement. +-- +-- This routine executes specified check statement. */ + +static int check_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + CHECK *chk = (CHECK *)info; + if (!eval_logical(mpl, chk->code)) + error(mpl, "check%s failed", format_tuple(mpl, '[', + get_domain_tuple(mpl, chk->domain))); + return 0; +} + +void execute_check(MPL *mpl, CHECK *chk) +{ loop_within_domain(mpl, chk->domain, chk, check_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_check - clean check statement. +-- +-- This routine cleans specified check statement that assumes deleting +-- all stuff dynamically allocated on generating/postsolving phase. */ + +void clean_check(MPL *mpl, CHECK *chk) +{ /* clean subscript domain */ + clean_domain(mpl, chk->domain); + /* clean pseudo-code for computing predicate */ + clean_code(mpl, chk->code); + return; +} + +/*---------------------------------------------------------------------- +-- execute_display - execute display statement. +-- +-- This routine executes specified display statement. */ + +static void display_set(MPL *mpl, SET *set, MEMBER *memb) +{ /* display member of model set */ + ELEMSET *s = memb->value.set; + MEMBER *m; + write_text(mpl, "%s%s%s\n", set->name, + format_tuple(mpl, '[', memb->tuple), + s->head == NULL ? " is empty" : ":"); + for (m = s->head; m != NULL; m = m->next) + write_text(mpl, " %s\n", format_tuple(mpl, '(', m->tuple)); + return; +} + +static void display_par(MPL *mpl, PARAMETER *par, MEMBER *memb) +{ /* display member of model parameter */ + switch (par->type) + { case A_NUMERIC: + case A_INTEGER: + case A_BINARY: + write_text(mpl, "%s%s = %.*g\n", par->name, + format_tuple(mpl, '[', memb->tuple), + DBL_DIG, memb->value.num); + break; + case A_SYMBOLIC: + write_text(mpl, "%s%s = %s\n", par->name, + format_tuple(mpl, '[', memb->tuple), + format_symbol(mpl, memb->value.sym)); + break; + default: + xassert(par != par); + } + return; +} + +#if 1 /* 15/V-2010 */ +static void display_var(MPL *mpl, VARIABLE *var, MEMBER *memb, + int suff) +{ /* display member of model variable */ + if (suff == DOT_NONE || suff == DOT_VAL) + write_text(mpl, "%s%s.val = %.*g\n", var->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.var->prim); + else if (suff == DOT_LB) + write_text(mpl, "%s%s.lb = %.*g\n", var->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.var->var->lbnd == NULL ? -DBL_MAX : + memb->value.var->lbnd); + else if (suff == DOT_UB) + write_text(mpl, "%s%s.ub = %.*g\n", var->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.var->var->ubnd == NULL ? +DBL_MAX : + memb->value.var->ubnd); + else if (suff == DOT_STATUS) + write_text(mpl, "%s%s.status = %d\n", var->name, format_tuple + (mpl, '[', memb->tuple), memb->value.var->stat); + else if (suff == DOT_DUAL) + write_text(mpl, "%s%s.dual = %.*g\n", var->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.var->dual); + else + xassert(suff != suff); + return; +} +#endif + +#if 1 /* 15/V-2010 */ +static void display_con(MPL *mpl, CONSTRAINT *con, MEMBER *memb, + int suff) +{ /* display member of model constraint */ + if (suff == DOT_NONE || suff == DOT_VAL) + write_text(mpl, "%s%s.val = %.*g\n", con->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.con->prim); + else if (suff == DOT_LB) + write_text(mpl, "%s%s.lb = %.*g\n", con->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.con->con->lbnd == NULL ? -DBL_MAX : + memb->value.con->lbnd); + else if (suff == DOT_UB) + write_text(mpl, "%s%s.ub = %.*g\n", con->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.con->con->ubnd == NULL ? +DBL_MAX : + memb->value.con->ubnd); + else if (suff == DOT_STATUS) + write_text(mpl, "%s%s.status = %d\n", con->name, format_tuple + (mpl, '[', memb->tuple), memb->value.con->stat); + else if (suff == DOT_DUAL) + write_text(mpl, "%s%s.dual = %.*g\n", con->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.con->dual); + else + xassert(suff != suff); + return; +} +#endif + +static void display_memb(MPL *mpl, CODE *code) +{ /* display member specified by pseudo-code */ + MEMBER memb; + ARG_LIST *e; + xassert(code->op == O_MEMNUM || code->op == O_MEMSYM + || code->op == O_MEMSET || code->op == O_MEMVAR + || code->op == O_MEMCON); + memb.tuple = create_tuple(mpl); + for (e = code->arg.par.list; e != NULL; e = e->next) + memb.tuple = expand_tuple(mpl, memb.tuple, eval_symbolic(mpl, + e->x)); + switch (code->op) + { case O_MEMNUM: + memb.value.num = eval_member_num(mpl, code->arg.par.par, + memb.tuple); + display_par(mpl, code->arg.par.par, &memb); + break; + case O_MEMSYM: + memb.value.sym = eval_member_sym(mpl, code->arg.par.par, + memb.tuple); + display_par(mpl, code->arg.par.par, &memb); + delete_symbol(mpl, memb.value.sym); + break; + case O_MEMSET: + memb.value.set = eval_member_set(mpl, code->arg.set.set, + memb.tuple); + display_set(mpl, code->arg.set.set, &memb); + break; + case O_MEMVAR: + memb.value.var = eval_member_var(mpl, code->arg.var.var, + memb.tuple); + display_var + (mpl, code->arg.var.var, &memb, code->arg.var.suff); + break; + case O_MEMCON: + memb.value.con = eval_member_con(mpl, code->arg.con.con, + memb.tuple); + display_con + (mpl, code->arg.con.con, &memb, code->arg.con.suff); + break; + default: + xassert(code != code); + } + delete_tuple(mpl, memb.tuple); + return; +} + +static void display_code(MPL *mpl, CODE *code) +{ /* display value of expression */ + switch (code->type) + { case A_NUMERIC: + /* numeric value */ + { double num; + num = eval_numeric(mpl, code); + write_text(mpl, "%.*g\n", DBL_DIG, num); + } + break; + case A_SYMBOLIC: + /* symbolic value */ + { SYMBOL *sym; + sym = eval_symbolic(mpl, code); + write_text(mpl, "%s\n", format_symbol(mpl, sym)); + delete_symbol(mpl, sym); + } + break; + case A_LOGICAL: + /* logical value */ + { int bit; + bit = eval_logical(mpl, code); + write_text(mpl, "%s\n", bit ? "true" : "false"); + } + break; + case A_TUPLE: + /* n-tuple */ + { TUPLE *tuple; + tuple = eval_tuple(mpl, code); + write_text(mpl, "%s\n", format_tuple(mpl, '(', tuple)); + delete_tuple(mpl, tuple); + } + break; + case A_ELEMSET: + /* elemental set */ + { ELEMSET *set; + MEMBER *memb; + set = eval_elemset(mpl, code); + if (set->head == 0) + write_text(mpl, "set is empty\n"); + for (memb = set->head; memb != NULL; memb = memb->next) + write_text(mpl, " %s\n", format_tuple(mpl, '(', + memb->tuple)); + delete_elemset(mpl, set); + } + break; + case A_FORMULA: + /* linear form */ + { FORMULA *form, *term; + form = eval_formula(mpl, code); + if (form == NULL) + write_text(mpl, "linear form is empty\n"); + for (term = form; term != NULL; term = term->next) + { if (term->var == NULL) + write_text(mpl, " %.*g\n", term->coef); + else + write_text(mpl, " %.*g %s%s\n", DBL_DIG, + term->coef, term->var->var->name, + format_tuple(mpl, '[', term->var->memb->tuple)); + } + delete_formula(mpl, form); + } + break; + default: + xassert(code != code); + } + return; +} + +static int display_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + DISPLAY *dpy = (DISPLAY *)info; + DISPLAY1 *entry; + for (entry = dpy->list; entry != NULL; entry = entry->next) + { if (entry->type == A_INDEX) + { /* dummy index */ + DOMAIN_SLOT *slot = entry->u.slot; + write_text(mpl, "%s = %s\n", slot->name, + format_symbol(mpl, slot->value)); + } + else if (entry->type == A_SET) + { /* model set */ + SET *set = entry->u.set; + MEMBER *memb; + if (set->assign != NULL) + { /* the set has assignment expression; evaluate all its + members over entire domain */ + eval_whole_set(mpl, set); + } + else + { /* the set has no assignment expression; refer to its + any existing member ignoring resultant value to check + the data provided the data section */ +#if 1 /* 12/XII-2008 */ + if (set->gadget != NULL && set->data == 0) + { /* initialize the set with data from a plain set */ + saturate_set(mpl, set); + } +#endif + if (set->array->head != NULL) + eval_member_set(mpl, set, set->array->head->tuple); + } + /* display all members of the set array */ + if (set->array->head == NULL) + write_text(mpl, "%s has empty content\n", set->name); + for (memb = set->array->head; memb != NULL; memb = + memb->next) display_set(mpl, set, memb); + } + else if (entry->type == A_PARAMETER) + { /* model parameter */ + PARAMETER *par = entry->u.par; + MEMBER *memb; + if (par->assign != NULL) + { /* the parameter has an assignment expression; evaluate + all its member over entire domain */ + eval_whole_par(mpl, par); + } + else + { /* the parameter has no assignment expression; refer to + its any existing member ignoring resultant value to + check the data provided in the data section */ + if (par->array->head != NULL) + { if (par->type != A_SYMBOLIC) + eval_member_num(mpl, par, par->array->head->tuple); + else + delete_symbol(mpl, eval_member_sym(mpl, par, + par->array->head->tuple)); + } + } + /* display all members of the parameter array */ + if (par->array->head == NULL) + write_text(mpl, "%s has empty content\n", par->name); + for (memb = par->array->head; memb != NULL; memb = + memb->next) display_par(mpl, par, memb); + } + else if (entry->type == A_VARIABLE) + { /* model variable */ + VARIABLE *var = entry->u.var; + MEMBER *memb; + xassert(mpl->flag_p); + /* display all members of the variable array */ + if (var->array->head == NULL) + write_text(mpl, "%s has empty content\n", var->name); + for (memb = var->array->head; memb != NULL; memb = + memb->next) display_var(mpl, var, memb, DOT_NONE); + } + else if (entry->type == A_CONSTRAINT) + { /* model constraint */ + CONSTRAINT *con = entry->u.con; + MEMBER *memb; + xassert(mpl->flag_p); + /* display all members of the constraint array */ + if (con->array->head == NULL) + write_text(mpl, "%s has empty content\n", con->name); + for (memb = con->array->head; memb != NULL; memb = + memb->next) display_con(mpl, con, memb, DOT_NONE); + } + else if (entry->type == A_EXPRESSION) + { /* expression */ + CODE *code = entry->u.code; + if (code->op == O_MEMNUM || code->op == O_MEMSYM || + code->op == O_MEMSET || code->op == O_MEMVAR || + code->op == O_MEMCON) + display_memb(mpl, code); + else + display_code(mpl, code); + } + else + xassert(entry != entry); + } + return 0; +} + +void execute_display(MPL *mpl, DISPLAY *dpy) +{ loop_within_domain(mpl, dpy->domain, dpy, display_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_display - clean display statement. +-- +-- This routine cleans specified display statement that assumes deleting +-- all stuff dynamically allocated on generating/postsolving phase. */ + +void clean_display(MPL *mpl, DISPLAY *dpy) +{ DISPLAY1 *d; +#if 0 /* 15/V-2010 */ + ARG_LIST *e; +#endif + /* clean subscript domain */ + clean_domain(mpl, dpy->domain); + /* clean display list */ + for (d = dpy->list; d != NULL; d = d->next) + { /* clean pseudo-code for computing expression */ + if (d->type == A_EXPRESSION) + clean_code(mpl, d->u.code); +#if 0 /* 15/V-2010 */ + /* clean pseudo-code for computing subscripts */ + for (e = d->list; e != NULL; e = e->next) + clean_code(mpl, e->x); +#endif + } + return; +} + +/*---------------------------------------------------------------------- +-- execute_printf - execute printf statement. +-- +-- This routine executes specified printf statement. */ + +#if 1 /* 14/VII-2006 */ +static void print_char(MPL *mpl, int c) +{ if (mpl->prt_fp == NULL) + write_char(mpl, c); + else +#if 0 /* 04/VIII-2013 */ + xfputc(c, mpl->prt_fp); +#else + { unsigned char buf[1]; + buf[0] = (unsigned char)c; + glp_write(mpl->prt_fp, buf, 1); + } +#endif + return; +} + +static void print_text(MPL *mpl, char *fmt, ...) +{ va_list arg; + char buf[OUTBUF_SIZE], *c; + va_start(arg, fmt); + vsprintf(buf, fmt, arg); + xassert(strlen(buf) < sizeof(buf)); + va_end(arg); + for (c = buf; *c != '\0'; c++) print_char(mpl, *c); + return; +} +#endif + +static int printf_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + PRINTF *prt = (PRINTF *)info; + PRINTF1 *entry; + SYMBOL *sym; + char fmt[MAX_LENGTH+1], *c, *from, save; + /* evaluate format control string */ + sym = eval_symbolic(mpl, prt->fmt); + if (sym->str == NULL) + sprintf(fmt, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, fmt); + delete_symbol(mpl, sym); + /* scan format control string and perform formatting output */ + entry = prt->list; + for (c = fmt; *c != '\0'; c++) + { if (*c == '%') + { /* scan format specifier */ + from = c++; + if (*c == '%') + { print_char(mpl, '%'); + continue; + } + if (entry == NULL) break; + /* scan optional flags */ + while (*c == '-' || *c == '+' || *c == ' ' || *c == '#' || + *c == '0') c++; + /* scan optional minimum field width */ + while (isdigit((unsigned char)*c)) c++; + /* scan optional precision */ + if (*c == '.') + { c++; + while (isdigit((unsigned char)*c)) c++; + } + /* scan conversion specifier and perform formatting */ + save = *(c+1), *(c+1) = '\0'; + if (*c == 'd' || *c == 'i' || *c == 'e' || *c == 'E' || + *c == 'f' || *c == 'F' || *c == 'g' || *c == 'G') + { /* the specifier requires numeric value */ + double value; + xassert(entry != NULL); + switch (entry->code->type) + { case A_NUMERIC: + value = eval_numeric(mpl, entry->code); + break; + case A_SYMBOLIC: + sym = eval_symbolic(mpl, entry->code); + if (sym->str != NULL) + error(mpl, "cannot convert %s to floating-point" + " number", format_symbol(mpl, sym)); + value = sym->num; + delete_symbol(mpl, sym); + break; + case A_LOGICAL: + if (eval_logical(mpl, entry->code)) + value = 1.0; + else + value = 0.0; + break; + default: + xassert(entry != entry); + } + if (*c == 'd' || *c == 'i') + { double int_max = (double)INT_MAX; + if (!(-int_max <= value && value <= +int_max)) + error(mpl, "cannot convert %.*g to integer", + DBL_DIG, value); + print_text(mpl, from, (int)floor(value + 0.5)); + } + else + print_text(mpl, from, value); + } + else if (*c == 's') + { /* the specifier requires symbolic value */ + char value[MAX_LENGTH+1]; + switch (entry->code->type) + { case A_NUMERIC: + sprintf(value, "%.*g", DBL_DIG, eval_numeric(mpl, + entry->code)); + break; + case A_LOGICAL: + if (eval_logical(mpl, entry->code)) + strcpy(value, "T"); + else + strcpy(value, "F"); + break; + case A_SYMBOLIC: + sym = eval_symbolic(mpl, entry->code); + if (sym->str == NULL) + sprintf(value, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, value); + delete_symbol(mpl, sym); + break; + default: + xassert(entry != entry); + } + print_text(mpl, from, value); + } + else + error(mpl, "format specifier missing or invalid"); + *(c+1) = save; + entry = entry->next; + } + else if (*c == '\\') + { /* write some control character */ + c++; + if (*c == 't') + print_char(mpl, '\t'); + else if (*c == 'n') + print_char(mpl, '\n'); +#if 1 /* 28/X-2010 */ + else if (*c == '\0') + { /* format string ends with backslash */ + error(mpl, "invalid use of escape character \\ in format" + " control string"); + } +#endif + else + print_char(mpl, *c); + } + else + { /* write character without formatting */ + print_char(mpl, *c); + } + } + return 0; +} + +#if 0 /* 14/VII-2006 */ +void execute_printf(MPL *mpl, PRINTF *prt) +{ loop_within_domain(mpl, prt->domain, prt, printf_func); + return; +} +#else +void execute_printf(MPL *mpl, PRINTF *prt) +{ if (prt->fname == NULL) + { /* switch to the standard output */ + if (mpl->prt_fp != NULL) + { glp_close(mpl->prt_fp), mpl->prt_fp = NULL; + xfree(mpl->prt_file), mpl->prt_file = NULL; + } + } + else + { /* evaluate file name string */ + SYMBOL *sym; + char fname[MAX_LENGTH+1]; + sym = eval_symbolic(mpl, prt->fname); + if (sym->str == NULL) + sprintf(fname, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, fname); + delete_symbol(mpl, sym); + /* close the current print file, if necessary */ + if (mpl->prt_fp != NULL && + (!prt->app || strcmp(mpl->prt_file, fname) != 0)) + { glp_close(mpl->prt_fp), mpl->prt_fp = NULL; + xfree(mpl->prt_file), mpl->prt_file = NULL; + } + /* open the specified print file, if necessary */ + if (mpl->prt_fp == NULL) + { mpl->prt_fp = glp_open(fname, prt->app ? "a" : "w"); + if (mpl->prt_fp == NULL) + error(mpl, "unable to open `%s' for writing - %s", + fname, get_err_msg()); + mpl->prt_file = xmalloc(strlen(fname)+1); + strcpy(mpl->prt_file, fname); + } + } + loop_within_domain(mpl, prt->domain, prt, printf_func); + if (mpl->prt_fp != NULL) + { +#if 0 /* FIXME */ + xfflush(mpl->prt_fp); +#endif + if (glp_ioerr(mpl->prt_fp)) + error(mpl, "writing error to `%s' - %s", mpl->prt_file, + get_err_msg()); + } + return; +} +#endif + +/*---------------------------------------------------------------------- +-- clean_printf - clean printf statement. +-- +-- This routine cleans specified printf statement that assumes deleting +-- all stuff dynamically allocated on generating/postsolving phase. */ + +void clean_printf(MPL *mpl, PRINTF *prt) +{ PRINTF1 *p; + /* clean subscript domain */ + clean_domain(mpl, prt->domain); + /* clean pseudo-code for computing format string */ + clean_code(mpl, prt->fmt); + /* clean printf list */ + for (p = prt->list; p != NULL; p = p->next) + { /* clean pseudo-code for computing value to be printed */ + clean_code(mpl, p->code); + } +#if 1 /* 14/VII-2006 */ + /* clean pseudo-code for computing file name string */ + clean_code(mpl, prt->fname); +#endif + return; +} + +/*---------------------------------------------------------------------- +-- execute_for - execute for statement. +-- +-- This routine executes specified for statement. */ + +static int for_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + FOR *fur = (FOR *)info; + STATEMENT *stmt, *save; + save = mpl->stmt; + for (stmt = fur->list; stmt != NULL; stmt = stmt->next) + execute_statement(mpl, stmt); + mpl->stmt = save; + return 0; +} + +void execute_for(MPL *mpl, FOR *fur) +{ loop_within_domain(mpl, fur->domain, fur, for_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_for - clean for statement. +-- +-- This routine cleans specified for statement that assumes deleting all +-- stuff dynamically allocated on generating/postsolving phase. */ + +void clean_for(MPL *mpl, FOR *fur) +{ STATEMENT *stmt; + /* clean subscript domain */ + clean_domain(mpl, fur->domain); + /* clean all sub-statements */ + for (stmt = fur->list; stmt != NULL; stmt = stmt->next) + clean_statement(mpl, stmt); + return; +} + +/*---------------------------------------------------------------------- +-- execute_statement - execute specified model statement. +-- +-- This routine executes specified model statement. */ + +void execute_statement(MPL *mpl, STATEMENT *stmt) +{ mpl->stmt = stmt; + switch (stmt->type) + { case A_SET: + case A_PARAMETER: + case A_VARIABLE: + break; + case A_CONSTRAINT: + xprintf("Generating %s...\n", stmt->u.con->name); + eval_whole_con(mpl, stmt->u.con); + break; + case A_TABLE: + switch (stmt->u.tab->type) + { case A_INPUT: + xprintf("Reading %s...\n", stmt->u.tab->name); + break; + case A_OUTPUT: + xprintf("Writing %s...\n", stmt->u.tab->name); + break; + default: + xassert(stmt != stmt); + } + execute_table(mpl, stmt->u.tab); + break; + case A_SOLVE: + break; + case A_CHECK: + xprintf("Checking (line %d)...\n", stmt->line); + execute_check(mpl, stmt->u.chk); + break; + case A_DISPLAY: + write_text(mpl, "Display statement at line %d\n", + stmt->line); + execute_display(mpl, stmt->u.dpy); + break; + case A_PRINTF: + execute_printf(mpl, stmt->u.prt); + break; + case A_FOR: + execute_for(mpl, stmt->u.fur); + break; + default: + xassert(stmt != stmt); + } + return; +} + +/*---------------------------------------------------------------------- +-- clean_statement - clean specified model statement. +-- +-- This routine cleans specified model statement that assumes deleting +-- all stuff dynamically allocated on generating/postsolving phase. */ + +void clean_statement(MPL *mpl, STATEMENT *stmt) +{ switch(stmt->type) + { case A_SET: + clean_set(mpl, stmt->u.set); break; + case A_PARAMETER: + clean_parameter(mpl, stmt->u.par); break; + case A_VARIABLE: + clean_variable(mpl, stmt->u.var); break; + case A_CONSTRAINT: + clean_constraint(mpl, stmt->u.con); break; +#if 1 /* 11/II-2008 */ + case A_TABLE: + clean_table(mpl, stmt->u.tab); break; +#endif + case A_SOLVE: + break; + case A_CHECK: + clean_check(mpl, stmt->u.chk); break; + case A_DISPLAY: + clean_display(mpl, stmt->u.dpy); break; + case A_PRINTF: + clean_printf(mpl, stmt->u.prt); break; + case A_FOR: + clean_for(mpl, stmt->u.fur); break; + default: + xassert(stmt != stmt); + } + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl04.c b/resources/3rdparty/glpk-4.53/src/glpmpl04.c new file mode 100644 index 000000000..4ec2c19c2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpmpl04.c @@ -0,0 +1,1427 @@ +/* glpmpl04.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "glpmpl.h" + +#define xfault xerror +#define xfprintf glp_format +#define dmp_create_poolx(size) dmp_create_pool() + +/**********************************************************************/ +/* * * GENERATING AND POSTSOLVING MODEL * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- alloc_content - allocate content arrays for all model objects. +-- +-- This routine allocates content arrays for all existing model objects +-- and thereby finalizes creating model. +-- +-- This routine must be called immediately after reading model section, +-- i.e. before reading data section or generating model. */ + +void alloc_content(MPL *mpl) +{ STATEMENT *stmt; + /* walk through all model statements */ + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { switch (stmt->type) + { case A_SET: + /* model set */ + xassert(stmt->u.set->array == NULL); + stmt->u.set->array = create_array(mpl, A_ELEMSET, + stmt->u.set->dim); + break; + case A_PARAMETER: + /* model parameter */ + xassert(stmt->u.par->array == NULL); + switch (stmt->u.par->type) + { case A_NUMERIC: + case A_INTEGER: + case A_BINARY: + stmt->u.par->array = create_array(mpl, A_NUMERIC, + stmt->u.par->dim); + break; + case A_SYMBOLIC: + stmt->u.par->array = create_array(mpl, A_SYMBOLIC, + stmt->u.par->dim); + break; + default: + xassert(stmt != stmt); + } + break; + case A_VARIABLE: + /* model variable */ + xassert(stmt->u.var->array == NULL); + stmt->u.var->array = create_array(mpl, A_ELEMVAR, + stmt->u.var->dim); + break; + case A_CONSTRAINT: + /* model constraint/objective */ + xassert(stmt->u.con->array == NULL); + stmt->u.con->array = create_array(mpl, A_ELEMCON, + stmt->u.con->dim); + break; +#if 1 /* 11/II-2008 */ + case A_TABLE: +#endif + case A_SOLVE: + case A_CHECK: + case A_DISPLAY: + case A_PRINTF: + case A_FOR: + /* functional statements have no content array */ + break; + default: + xassert(stmt != stmt); + } + } + return; +} + +/*---------------------------------------------------------------------- +-- generate_model - generate model. +-- +-- This routine executes the model statements which precede the solve +-- statement. */ + +void generate_model(MPL *mpl) +{ STATEMENT *stmt; + xassert(!mpl->flag_p); + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { execute_statement(mpl, stmt); + if (mpl->stmt->type == A_SOLVE) break; + } + mpl->stmt = stmt; + return; +} + +/*---------------------------------------------------------------------- +-- build_problem - build problem instance. +-- +-- This routine builds lists of rows and columns for problem instance, +-- which corresponds to the generated model. */ + +void build_problem(MPL *mpl) +{ STATEMENT *stmt; + MEMBER *memb; + VARIABLE *v; + CONSTRAINT *c; + FORMULA *t; + int i, j; + xassert(mpl->m == 0); + xassert(mpl->n == 0); + xassert(mpl->row == NULL); + xassert(mpl->col == NULL); + /* check that all elemental variables has zero column numbers */ + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { if (stmt->type == A_VARIABLE) + { v = stmt->u.var; + for (memb = v->array->head; memb != NULL; memb = memb->next) + xassert(memb->value.var->j == 0); + } + } + /* assign row numbers to elemental constraints and objectives */ + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { if (stmt->type == A_CONSTRAINT) + { c = stmt->u.con; + for (memb = c->array->head; memb != NULL; memb = memb->next) + { xassert(memb->value.con->i == 0); + memb->value.con->i = ++mpl->m; + /* walk through linear form and mark elemental variables, + which are referenced at least once */ + for (t = memb->value.con->form; t != NULL; t = t->next) + { xassert(t->var != NULL); + t->var->memb->value.var->j = -1; + } + } + } + } + /* assign column numbers to marked elemental variables */ + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { if (stmt->type == A_VARIABLE) + { v = stmt->u.var; + for (memb = v->array->head; memb != NULL; memb = memb->next) + if (memb->value.var->j != 0) memb->value.var->j = + ++mpl->n; + } + } + /* build list of rows */ + mpl->row = xcalloc(1+mpl->m, sizeof(ELEMCON *)); + for (i = 1; i <= mpl->m; i++) mpl->row[i] = NULL; + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { if (stmt->type == A_CONSTRAINT) + { c = stmt->u.con; + for (memb = c->array->head; memb != NULL; memb = memb->next) + { i = memb->value.con->i; + xassert(1 <= i && i <= mpl->m); + xassert(mpl->row[i] == NULL); + mpl->row[i] = memb->value.con; + } + } + } + for (i = 1; i <= mpl->m; i++) xassert(mpl->row[i] != NULL); + /* build list of columns */ + mpl->col = xcalloc(1+mpl->n, sizeof(ELEMVAR *)); + for (j = 1; j <= mpl->n; j++) mpl->col[j] = NULL; + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { if (stmt->type == A_VARIABLE) + { v = stmt->u.var; + for (memb = v->array->head; memb != NULL; memb = memb->next) + { j = memb->value.var->j; + if (j == 0) continue; + xassert(1 <= j && j <= mpl->n); + xassert(mpl->col[j] == NULL); + mpl->col[j] = memb->value.var; + } + } + } + for (j = 1; j <= mpl->n; j++) xassert(mpl->col[j] != NULL); + return; +} + +/*---------------------------------------------------------------------- +-- postsolve_model - postsolve model. +-- +-- This routine executes the model statements which follow the solve +-- statement. */ + +void postsolve_model(MPL *mpl) +{ STATEMENT *stmt; + xassert(!mpl->flag_p); + mpl->flag_p = 1; + for (stmt = mpl->stmt; stmt != NULL; stmt = stmt->next) + execute_statement(mpl, stmt); + mpl->stmt = NULL; + return; +} + +/*---------------------------------------------------------------------- +-- clean_model - clean model content. +-- +-- This routine cleans the model content that assumes deleting all stuff +-- dynamically allocated on generating/postsolving phase. +-- +-- Actually cleaning model content is not needed. This function is used +-- mainly to be sure that there were no logical errors on using dynamic +-- memory pools during the generation phase. +-- +-- NOTE: This routine must not be called if any errors were detected on +-- the generation phase. */ + +void clean_model(MPL *mpl) +{ STATEMENT *stmt; + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + clean_statement(mpl, stmt); + /* check that all atoms have been returned to their pools */ + if (dmp_in_use(mpl->strings) != 0) + error(mpl, "internal logic error: %d string segment(s) were lo" + "st", dmp_in_use(mpl->strings)); + if (dmp_in_use(mpl->symbols) != 0) + error(mpl, "internal logic error: %d symbol(s) were lost", + dmp_in_use(mpl->symbols)); + if (dmp_in_use(mpl->tuples) != 0) + error(mpl, "internal logic error: %d n-tuple component(s) were" + " lost", dmp_in_use(mpl->tuples)); + if (dmp_in_use(mpl->arrays) != 0) + error(mpl, "internal logic error: %d array(s) were lost", + dmp_in_use(mpl->arrays)); + if (dmp_in_use(mpl->members) != 0) + error(mpl, "internal logic error: %d array member(s) were lost" + , dmp_in_use(mpl->members)); + if (dmp_in_use(mpl->elemvars) != 0) + error(mpl, "internal logic error: %d elemental variable(s) wer" + "e lost", dmp_in_use(mpl->elemvars)); + if (dmp_in_use(mpl->formulae) != 0) + error(mpl, "internal logic error: %d linear term(s) were lost", + dmp_in_use(mpl->formulae)); + if (dmp_in_use(mpl->elemcons) != 0) + error(mpl, "internal logic error: %d elemental constraint(s) w" + "ere lost", dmp_in_use(mpl->elemcons)); + return; +} + +/**********************************************************************/ +/* * * INPUT/OUTPUT * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- open_input - open input text file. +-- +-- This routine opens the input text file for scanning. */ + +void open_input(MPL *mpl, char *file) +{ mpl->line = 0; + mpl->c = '\n'; + mpl->token = 0; + mpl->imlen = 0; + mpl->image[0] = '\0'; + mpl->value = 0.0; + mpl->b_token = T_EOF; + mpl->b_imlen = 0; + mpl->b_image[0] = '\0'; + mpl->b_value = 0.0; + mpl->f_dots = 0; + mpl->f_scan = 0; + mpl->f_token = 0; + mpl->f_imlen = 0; + mpl->f_image[0] = '\0'; + mpl->f_value = 0.0; + memset(mpl->context, ' ', CONTEXT_SIZE); + mpl->c_ptr = 0; + xassert(mpl->in_fp == NULL); + mpl->in_fp = glp_open(file, "r"); + if (mpl->in_fp == NULL) + error(mpl, "unable to open %s - %s", file, get_err_msg()); + mpl->in_file = file; + /* scan the very first character */ + get_char(mpl); + /* scan the very first token */ + get_token(mpl); + return; +} + +/*---------------------------------------------------------------------- +-- read_char - read next character from input text file. +-- +-- This routine returns a next ASCII character read from the input text +-- file. If the end of file has been reached, EOF is returned. */ + +int read_char(MPL *mpl) +{ int c; + xassert(mpl->in_fp != NULL); + c = glp_getc(mpl->in_fp); + if (c < 0) + { if (glp_ioerr(mpl->in_fp)) + error(mpl, "read error on %s - %s", mpl->in_file, + get_err_msg()); + c = EOF; + } + return c; +} + +/*---------------------------------------------------------------------- +-- close_input - close input text file. +-- +-- This routine closes the input text file. */ + +void close_input(MPL *mpl) +{ xassert(mpl->in_fp != NULL); + glp_close(mpl->in_fp); + mpl->in_fp = NULL; + mpl->in_file = NULL; + return; +} + +/*---------------------------------------------------------------------- +-- open_output - open output text file. +-- +-- This routine opens the output text file for writing data produced by +-- display and printf statements. */ + +void open_output(MPL *mpl, char *file) +{ xassert(mpl->out_fp == NULL); + if (file == NULL) + { file = "<stdout>"; + mpl->out_fp = (void *)stdout; + } + else + { mpl->out_fp = glp_open(file, "w"); + if (mpl->out_fp == NULL) + error(mpl, "unable to create %s - %s", file, get_err_msg()); + } + mpl->out_file = xmalloc(strlen(file)+1); + strcpy(mpl->out_file, file); + return; +} + +/*---------------------------------------------------------------------- +-- write_char - write next character to output text file. +-- +-- This routine writes an ASCII character to the output text file. */ + +void write_char(MPL *mpl, int c) +{ xassert(mpl->out_fp != NULL); + if (mpl->out_fp == (void *)stdout) + xprintf("%c", c); + else + xfprintf(mpl->out_fp, "%c", c); + return; +} + +/*---------------------------------------------------------------------- +-- write_text - format and write text to output text file. +-- +-- This routine formats a text using the format control string and then +-- writes this text to the output text file. */ + +void write_text(MPL *mpl, char *fmt, ...) +{ va_list arg; + char buf[OUTBUF_SIZE], *c; + va_start(arg, fmt); + vsprintf(buf, fmt, arg); + xassert(strlen(buf) < sizeof(buf)); + va_end(arg); + for (c = buf; *c != '\0'; c++) write_char(mpl, *c); + return; +} + +/*---------------------------------------------------------------------- +-- flush_output - finalize writing data to output text file. +-- +-- This routine finalizes writing data to the output text file. */ + +void flush_output(MPL *mpl) +{ xassert(mpl->out_fp != NULL); + if (mpl->out_fp != (void *)stdout) + { +#if 0 /* FIXME */ + xfflush(mpl->out_fp); +#endif + if (glp_ioerr(mpl->out_fp)) + error(mpl, "write error on %s - %s", mpl->out_file, + get_err_msg()); + } + return; +} + +/**********************************************************************/ +/* * * SOLVER INTERFACE * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- error - print error message and terminate model processing. +-- +-- This routine formats and prints an error message and then terminates +-- model processing. */ + +void error(MPL *mpl, char *fmt, ...) +{ va_list arg; + char msg[4095+1]; + va_start(arg, fmt); + vsprintf(msg, fmt, arg); + xassert(strlen(msg) < sizeof(msg)); + va_end(arg); + switch (mpl->phase) + { case 1: + case 2: + /* translation phase */ + xprintf("%s:%d: %s\n", + mpl->in_file == NULL ? "(unknown)" : mpl->in_file, + mpl->line, msg); + print_context(mpl); + break; + case 3: + /* generation/postsolve phase */ + xprintf("%s:%d: %s\n", + mpl->mod_file == NULL ? "(unknown)" : mpl->mod_file, + mpl->stmt == NULL ? 0 : mpl->stmt->line, msg); + break; + default: + xassert(mpl != mpl); + } + mpl->phase = 4; + longjmp(mpl->jump, 1); + /* no return */ +} + +/*---------------------------------------------------------------------- +-- warning - print warning message and continue model processing. +-- +-- This routine formats and prints a warning message and returns to the +-- calling program. */ + +void warning(MPL *mpl, char *fmt, ...) +{ va_list arg; + char msg[4095+1]; + va_start(arg, fmt); + vsprintf(msg, fmt, arg); + xassert(strlen(msg) < sizeof(msg)); + va_end(arg); + switch (mpl->phase) + { case 1: + case 2: + /* translation phase */ + xprintf("%s:%d: warning: %s\n", + mpl->in_file == NULL ? "(unknown)" : mpl->in_file, + mpl->line, msg); + break; + case 3: + /* generation/postsolve phase */ + xprintf("%s:%d: warning: %s\n", + mpl->mod_file == NULL ? "(unknown)" : mpl->mod_file, + mpl->stmt == NULL ? 0 : mpl->stmt->line, msg); + break; + default: + xassert(mpl != mpl); + } + return; +} + +/*---------------------------------------------------------------------- +-- mpl_initialize - create and initialize translator database. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- MPL *mpl_initialize(void); +-- +-- *Description* +-- +-- The routine mpl_initialize creates and initializes the database used +-- by the GNU MathProg translator. +-- +-- *Returns* +-- +-- The routine returns a pointer to the database created. */ + +MPL *mpl_initialize(void) +{ MPL *mpl; + mpl = xmalloc(sizeof(MPL)); + /* scanning segment */ + mpl->line = 0; + mpl->c = 0; + mpl->token = 0; + mpl->imlen = 0; + mpl->image = xcalloc(MAX_LENGTH+1, sizeof(char)); + mpl->image[0] = '\0'; + mpl->value = 0.0; + mpl->b_token = 0; + mpl->b_imlen = 0; + mpl->b_image = xcalloc(MAX_LENGTH+1, sizeof(char)); + mpl->b_image[0] = '\0'; + mpl->b_value = 0.0; + mpl->f_dots = 0; + mpl->f_scan = 0; + mpl->f_token = 0; + mpl->f_imlen = 0; + mpl->f_image = xcalloc(MAX_LENGTH+1, sizeof(char)); + mpl->f_image[0] = '\0'; + mpl->f_value = 0.0; + mpl->context = xcalloc(CONTEXT_SIZE, sizeof(char)); + memset(mpl->context, ' ', CONTEXT_SIZE); + mpl->c_ptr = 0; + mpl->flag_d = 0; + /* translating segment */ + mpl->pool = dmp_create_poolx(0); + mpl->tree = avl_create_tree(avl_strcmp, NULL); + mpl->model = NULL; + mpl->flag_x = 0; + mpl->as_within = 0; + mpl->as_in = 0; + mpl->as_binary = 0; + mpl->flag_s = 0; + /* common segment */ + mpl->strings = dmp_create_poolx(sizeof(STRING)); + mpl->symbols = dmp_create_poolx(sizeof(SYMBOL)); + mpl->tuples = dmp_create_poolx(sizeof(TUPLE)); + mpl->arrays = dmp_create_poolx(sizeof(ARRAY)); + mpl->members = dmp_create_poolx(sizeof(MEMBER)); + mpl->elemvars = dmp_create_poolx(sizeof(ELEMVAR)); + mpl->formulae = dmp_create_poolx(sizeof(FORMULA)); + mpl->elemcons = dmp_create_poolx(sizeof(ELEMCON)); + mpl->a_list = NULL; + mpl->sym_buf = xcalloc(255+1, sizeof(char)); + mpl->sym_buf[0] = '\0'; + mpl->tup_buf = xcalloc(255+1, sizeof(char)); + mpl->tup_buf[0] = '\0'; + /* generating/postsolving segment */ + mpl->rand = rng_create_rand(); + mpl->flag_p = 0; + mpl->stmt = NULL; +#if 1 /* 11/II-2008 */ + mpl->dca = NULL; +#endif + mpl->m = 0; + mpl->n = 0; + mpl->row = NULL; + mpl->col = NULL; + /* input/output segment */ + mpl->in_fp = NULL; + mpl->in_file = NULL; + mpl->out_fp = NULL; + mpl->out_file = NULL; + mpl->prt_fp = NULL; + mpl->prt_file = NULL; + /* solver interface segment */ + if (setjmp(mpl->jump)) xassert(mpl != mpl); + mpl->phase = 0; + mpl->mod_file = NULL; + mpl->mpl_buf = xcalloc(255+1, sizeof(char)); + mpl->mpl_buf[0] = '\0'; + return mpl; +} + +/*---------------------------------------------------------------------- +-- mpl_read_model - read model section and optional data section. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_read_model(MPL *mpl, char *file, int skip_data); +-- +-- *Description* +-- +-- The routine mpl_read_model reads model section and optionally data +-- section, which may follow the model section, from the text file, +-- whose name is the character string file, performs translating model +-- statements and data blocks, and stores all the information in the +-- translator database. +-- +-- The parameter skip_data is a flag. If the input file contains the +-- data section and this flag is set, the data section is not read as +-- if there were no data section and a warning message is issued. This +-- allows reading the data section from another input file. +-- +-- This routine should be called once after the routine mpl_initialize +-- and before other API routines. +-- +-- *Returns* +-- +-- The routine mpl_read_model returns one the following codes: +-- +-- 1 - translation successful. The input text file contains only model +-- section. In this case the calling program may call the routine +-- mpl_read_data to read data section from another file. +-- 2 - translation successful. The input text file contains both model +-- and data section. +-- 4 - processing failed due to some errors. In this case the calling +-- program should call the routine mpl_terminate to terminate model +-- processing. */ + +int mpl_read_model(MPL *mpl, char *file, int skip_data) +{ if (mpl->phase != 0) + xfault("mpl_read_model: invalid call sequence\n"); + if (file == NULL) + xfault("mpl_read_model: no input filename specified\n"); + /* set up error handler */ + if (setjmp(mpl->jump)) goto done; + /* translate model section */ + mpl->phase = 1; + xprintf("Reading model section from %s...\n", file); + open_input(mpl, file); + model_section(mpl); + if (mpl->model == NULL) + error(mpl, "empty model section not allowed"); + /* save name of the input text file containing model section for + error diagnostics during the generation phase */ + mpl->mod_file = xcalloc(strlen(file)+1, sizeof(char)); + strcpy(mpl->mod_file, mpl->in_file); + /* allocate content arrays for all model objects */ + alloc_content(mpl); + /* optional data section may begin with the keyword 'data' */ + if (is_keyword(mpl, "data")) + { if (skip_data) + { warning(mpl, "data section ignored"); + goto skip; + } + mpl->flag_d = 1; + get_token(mpl /* data */); + if (mpl->token != T_SEMICOLON) + error(mpl, "semicolon missing where expected"); + get_token(mpl /* ; */); + /* translate data section */ + mpl->phase = 2; + xprintf("Reading data section from %s...\n", file); + data_section(mpl); + } + /* process end statement */ + end_statement(mpl); +skip: xprintf("%d line%s were read\n", + mpl->line, mpl->line == 1 ? "" : "s"); + close_input(mpl); +done: /* return to the calling program */ + return mpl->phase; +} + +/*---------------------------------------------------------------------- +-- mpl_read_data - read data section. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_read_data(MPL *mpl, char *file); +-- +-- *Description* +-- +-- The routine mpl_read_data reads data section from the text file, +-- whose name is the character string file, performs translating data +-- blocks, and stores the data read in the translator database. +-- +-- If this routine is used, it should be called once after the routine +-- mpl_read_model and if the latter returned the code 1. +-- +-- *Returns* +-- +-- The routine mpl_read_data returns one of the following codes: +-- +-- 2 - data section has been successfully processed. +-- 4 - processing failed due to some errors. In this case the calling +-- program should call the routine mpl_terminate to terminate model +-- processing. */ + +int mpl_read_data(MPL *mpl, char *file) +#if 0 /* 02/X-2008 */ +{ if (mpl->phase != 1) +#else +{ if (!(mpl->phase == 1 || mpl->phase == 2)) +#endif + xfault("mpl_read_data: invalid call sequence\n"); + if (file == NULL) + xfault("mpl_read_data: no input filename specified\n"); + /* set up error handler */ + if (setjmp(mpl->jump)) goto done; + /* process data section */ + mpl->phase = 2; + xprintf("Reading data section from %s...\n", file); + mpl->flag_d = 1; + open_input(mpl, file); + /* in this case the keyword 'data' is optional */ + if (is_literal(mpl, "data")) + { get_token(mpl /* data */); + if (mpl->token != T_SEMICOLON) + error(mpl, "semicolon missing where expected"); + get_token(mpl /* ; */); + } + data_section(mpl); + /* process end statement */ + end_statement(mpl); + xprintf("%d line%s were read\n", + mpl->line, mpl->line == 1 ? "" : "s"); + close_input(mpl); +done: /* return to the calling program */ + return mpl->phase; +} + +/*---------------------------------------------------------------------- +-- mpl_generate - generate model. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_generate(MPL *mpl, char *file); +-- +-- *Description* +-- +-- The routine mpl_generate generates the model using its description +-- stored in the translator database. This phase means generating all +-- variables, constraints, and objectives, executing check and display +-- statements, which precede the solve statement (if it is presented), +-- and building the problem instance. +-- +-- The character string file specifies the name of output text file, to +-- which output produced by display statements should be written. It is +-- allowed to specify NULL, in which case the output goes to stdout via +-- the routine print. +-- +-- This routine should be called once after the routine mpl_read_model +-- or mpl_read_data and if one of the latters returned the code 2. +-- +-- *Returns* +-- +-- The routine mpl_generate returns one of the following codes: +-- +-- 3 - model has been successfully generated. In this case the calling +-- program may call other api routines to obtain components of the +-- problem instance from the translator database. +-- 4 - processing failed due to some errors. In this case the calling +-- program should call the routine mpl_terminate to terminate model +-- processing. */ + +int mpl_generate(MPL *mpl, char *file) +{ if (!(mpl->phase == 1 || mpl->phase == 2)) + xfault("mpl_generate: invalid call sequence\n"); + /* set up error handler */ + if (setjmp(mpl->jump)) goto done; + /* generate model */ + mpl->phase = 3; + open_output(mpl, file); + generate_model(mpl); + flush_output(mpl); + /* build problem instance */ + build_problem(mpl); + /* generation phase has been finished */ + xprintf("Model has been successfully generated\n"); +done: /* return to the calling program */ + return mpl->phase; +} + +/*---------------------------------------------------------------------- +-- mpl_get_prob_name - obtain problem (model) name. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- char *mpl_get_prob_name(MPL *mpl); +-- +-- *Returns* +-- +-- The routine mpl_get_prob_name returns a pointer to internal buffer, +-- which contains symbolic name of the problem (model). +-- +-- *Note* +-- +-- Currently MathProg has no feature to assign a symbolic name to the +-- model. Therefore the routine mpl_get_prob_name tries to construct +-- such name using the name of input text file containing model section, +-- although this is not a good idea (due to portability problems). */ + +char *mpl_get_prob_name(MPL *mpl) +{ char *name = mpl->mpl_buf; + char *file = mpl->mod_file; + int k; + if (mpl->phase != 3) + xfault("mpl_get_prob_name: invalid call sequence\n"); + for (;;) + { if (strchr(file, '/') != NULL) + file = strchr(file, '/') + 1; + else if (strchr(file, '\\') != NULL) + file = strchr(file, '\\') + 1; + else if (strchr(file, ':') != NULL) + file = strchr(file, ':') + 1; + else + break; + } + for (k = 0; ; k++) + { if (k == 255) break; + if (!(isalnum((unsigned char)*file) || *file == '_')) break; + name[k] = *file++; + } + if (k == 0) + strcpy(name, "Unknown"); + else + name[k] = '\0'; + xassert(strlen(name) <= 255); + return name; +} + +/*---------------------------------------------------------------------- +-- mpl_get_num_rows - determine number of rows. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_num_rows(MPL *mpl); +-- +-- *Returns* +-- +-- The routine mpl_get_num_rows returns total number of rows in the +-- problem, where each row is an individual constraint or objective. */ + +int mpl_get_num_rows(MPL *mpl) +{ if (mpl->phase != 3) + xfault("mpl_get_num_rows: invalid call sequence\n"); + return mpl->m; +} + +/*---------------------------------------------------------------------- +-- mpl_get_num_cols - determine number of columns. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_num_cols(MPL *mpl); +-- +-- *Returns* +-- +-- The routine mpl_get_num_cols returns total number of columns in the +-- problem, where each column is an individual variable. */ + +int mpl_get_num_cols(MPL *mpl) +{ if (mpl->phase != 3) + xfault("mpl_get_num_cols: invalid call sequence\n"); + return mpl->n; +} + +/*---------------------------------------------------------------------- +-- mpl_get_row_name - obtain row name. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- char *mpl_get_row_name(MPL *mpl, int i); +-- +-- *Returns* +-- +-- The routine mpl_get_row_name returns a pointer to internal buffer, +-- which contains symbolic name of i-th row of the problem. */ + +char *mpl_get_row_name(MPL *mpl, int i) +{ char *name = mpl->mpl_buf, *t; + int len; + if (mpl->phase != 3) + xfault("mpl_get_row_name: invalid call sequence\n"); + if (!(1 <= i && i <= mpl->m)) + xfault("mpl_get_row_name: i = %d; row number out of range\n", + i); + strcpy(name, mpl->row[i]->con->name); + len = strlen(name); + xassert(len <= 255); + t = format_tuple(mpl, '[', mpl->row[i]->memb->tuple); + while (*t) + { if (len == 255) break; + name[len++] = *t++; + } + name[len] = '\0'; + if (len == 255) strcpy(name+252, "..."); + xassert(strlen(name) <= 255); + return name; +} + +/*---------------------------------------------------------------------- +-- mpl_get_row_kind - determine row kind. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_row_kind(MPL *mpl, int i); +-- +-- *Returns* +-- +-- The routine mpl_get_row_kind returns the kind of i-th row, which can +-- be one of the following: +-- +-- MPL_ST - non-free (constraint) row; +-- MPL_MIN - free (objective) row to be minimized; +-- MPL_MAX - free (objective) row to be maximized. */ + +int mpl_get_row_kind(MPL *mpl, int i) +{ int kind; + if (mpl->phase != 3) + xfault("mpl_get_row_kind: invalid call sequence\n"); + if (!(1 <= i && i <= mpl->m)) + xfault("mpl_get_row_kind: i = %d; row number out of range\n", + i); + switch (mpl->row[i]->con->type) + { case A_CONSTRAINT: + kind = MPL_ST; break; + case A_MINIMIZE: + kind = MPL_MIN; break; + case A_MAXIMIZE: + kind = MPL_MAX; break; + default: + xassert(mpl != mpl); + } + return kind; +} + +/*---------------------------------------------------------------------- +-- mpl_get_row_bnds - obtain row bounds. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_row_bnds(MPL *mpl, int i, double *lb, double *ub); +-- +-- *Description* +-- +-- The routine mpl_get_row_bnds stores lower and upper bounds of i-th +-- row of the problem to the locations, which the parameters lb and ub +-- point to, respectively. Besides the routine returns the type of the +-- i-th row. +-- +-- If some of the parameters lb and ub is NULL, the corresponding bound +-- value is not stored. +-- +-- Types and bounds have the following meaning: +-- +-- Type Bounds Note +-- ----------------------------------------------------------- +-- MPL_FR -inf < f(x) < +inf Free linear form +-- MPL_LO lb <= f(x) < +inf Inequality f(x) >= lb +-- MPL_UP -inf < f(x) <= ub Inequality f(x) <= ub +-- MPL_DB lb <= f(x) <= ub Inequality lb <= f(x) <= ub +-- MPL_FX f(x) = lb Equality f(x) = lb +-- +-- where f(x) is the corresponding linear form of the i-th row. +-- +-- If the row has no lower bound, *lb is set to zero; if the row has +-- no upper bound, *ub is set to zero; and if the row is of fixed type, +-- both *lb and *ub are set to the same value. +-- +-- *Returns* +-- +-- The routine returns the type of the i-th row as it is stated in the +-- table above. */ + +int mpl_get_row_bnds(MPL *mpl, int i, double *_lb, double *_ub) +{ ELEMCON *con; + int type; + double lb, ub; + if (mpl->phase != 3) + xfault("mpl_get_row_bnds: invalid call sequence\n"); + if (!(1 <= i && i <= mpl->m)) + xfault("mpl_get_row_bnds: i = %d; row number out of range\n", + i); + con = mpl->row[i]; +#if 0 /* 21/VII-2006 */ + if (con->con->lbnd == NULL && con->con->ubnd == NULL) + type = MPL_FR, lb = ub = 0.0; + else if (con->con->ubnd == NULL) + type = MPL_LO, lb = con->lbnd, ub = 0.0; + else if (con->con->lbnd == NULL) + type = MPL_UP, lb = 0.0, ub = con->ubnd; + else if (con->con->lbnd != con->con->ubnd) + type = MPL_DB, lb = con->lbnd, ub = con->ubnd; + else + type = MPL_FX, lb = ub = con->lbnd; +#else + lb = (con->con->lbnd == NULL ? -DBL_MAX : con->lbnd); + ub = (con->con->ubnd == NULL ? +DBL_MAX : con->ubnd); + if (lb == -DBL_MAX && ub == +DBL_MAX) + type = MPL_FR, lb = ub = 0.0; + else if (ub == +DBL_MAX) + type = MPL_LO, ub = 0.0; + else if (lb == -DBL_MAX) + type = MPL_UP, lb = 0.0; + else if (con->con->lbnd != con->con->ubnd) + type = MPL_DB; + else + type = MPL_FX; +#endif + if (_lb != NULL) *_lb = lb; + if (_ub != NULL) *_ub = ub; + return type; +} + +/*---------------------------------------------------------------------- +-- mpl_get_mat_row - obtain row of the constraint matrix. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[]); +-- +-- *Description* +-- +-- The routine mpl_get_mat_row stores column indices and numeric values +-- of constraint coefficients for the i-th row to locations ndx[1], ..., +-- ndx[len] and val[1], ..., val[len], respectively, where 0 <= len <= n +-- is number of (structural) non-zero constraint coefficients, and n is +-- number of columns in the problem. +-- +-- If the parameter ndx is NULL, column indices are not stored. If the +-- parameter val is NULL, numeric values are not stored. +-- +-- Note that free rows may have constant terms, which are not part of +-- the constraint matrix and therefore not reported by this routine. The +-- constant term of a particular row can be obtained, if necessary, via +-- the routine mpl_get_row_c0. +-- +-- *Returns* +-- +-- The routine mpl_get_mat_row returns len, which is length of i-th row +-- of the constraint matrix (i.e. number of non-zero coefficients). */ + +int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[]) +{ FORMULA *term; + int len = 0; + if (mpl->phase != 3) + xfault("mpl_get_mat_row: invalid call sequence\n"); + if (!(1 <= i && i <= mpl->m)) + xfault("mpl_get_mat_row: i = %d; row number out of range\n", + i); + for (term = mpl->row[i]->form; term != NULL; term = term->next) + { xassert(term->var != NULL); + len++; + xassert(len <= mpl->n); + if (ndx != NULL) ndx[len] = term->var->j; + if (val != NULL) val[len] = term->coef; + } + return len; +} + +/*---------------------------------------------------------------------- +-- mpl_get_row_c0 - obtain constant term of free row. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- double mpl_get_row_c0(MPL *mpl, int i); +-- +-- *Returns* +-- +-- The routine mpl_get_row_c0 returns numeric value of constant term of +-- i-th row. +-- +-- Note that only free rows may have non-zero constant terms. Therefore +-- if i-th row is not free, the routine returns zero. */ + +double mpl_get_row_c0(MPL *mpl, int i) +{ ELEMCON *con; + double c0; + if (mpl->phase != 3) + xfault("mpl_get_row_c0: invalid call sequence\n"); + if (!(1 <= i && i <= mpl->m)) + xfault("mpl_get_row_c0: i = %d; row number out of range\n", + i); + con = mpl->row[i]; + if (con->con->lbnd == NULL && con->con->ubnd == NULL) + c0 = - con->lbnd; + else + c0 = 0.0; + return c0; +} + +/*---------------------------------------------------------------------- +-- mpl_get_col_name - obtain column name. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- char *mpl_get_col_name(MPL *mpl, int j); +-- +-- *Returns* +-- +-- The routine mpl_get_col_name returns a pointer to internal buffer, +-- which contains symbolic name of j-th column of the problem. */ + +char *mpl_get_col_name(MPL *mpl, int j) +{ char *name = mpl->mpl_buf, *t; + int len; + if (mpl->phase != 3) + xfault("mpl_get_col_name: invalid call sequence\n"); + if (!(1 <= j && j <= mpl->n)) + xfault("mpl_get_col_name: j = %d; column number out of range\n" + , j); + strcpy(name, mpl->col[j]->var->name); + len = strlen(name); + xassert(len <= 255); + t = format_tuple(mpl, '[', mpl->col[j]->memb->tuple); + while (*t) + { if (len == 255) break; + name[len++] = *t++; + } + name[len] = '\0'; + if (len == 255) strcpy(name+252, "..."); + xassert(strlen(name) <= 255); + return name; +} + +/*---------------------------------------------------------------------- +-- mpl_get_col_kind - determine column kind. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_col_kind(MPL *mpl, int j); +-- +-- *Returns* +-- +-- The routine mpl_get_col_kind returns the kind of j-th column, which +-- can be one of the following: +-- +-- MPL_NUM - continuous variable; +-- MPL_INT - integer variable; +-- MPL_BIN - binary variable. +-- +-- Note that column kinds are defined independently on type and bounds +-- (reported by the routine mpl_get_col_bnds) of corresponding columns. +-- This means, in particular, that bounds of an integer column may be +-- fractional, or a binary column may have lower and upper bounds that +-- are not 0 and 1 (or it may have no lower/upper bound at all). */ + +int mpl_get_col_kind(MPL *mpl, int j) +{ int kind; + if (mpl->phase != 3) + xfault("mpl_get_col_kind: invalid call sequence\n"); + if (!(1 <= j && j <= mpl->n)) + xfault("mpl_get_col_kind: j = %d; column number out of range\n" + , j); + switch (mpl->col[j]->var->type) + { case A_NUMERIC: + kind = MPL_NUM; break; + case A_INTEGER: + kind = MPL_INT; break; + case A_BINARY: + kind = MPL_BIN; break; + default: + xassert(mpl != mpl); + } + return kind; +} + +/*---------------------------------------------------------------------- +-- mpl_get_col_bnds - obtain column bounds. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_col_bnds(MPL *mpl, int j, double *lb, double *ub); +-- +-- *Description* +-- +-- The routine mpl_get_col_bnds stores lower and upper bound of j-th +-- column of the problem to the locations, which the parameters lb and +-- ub point to, respectively. Besides the routine returns the type of +-- the j-th column. +-- +-- If some of the parameters lb and ub is NULL, the corresponding bound +-- value is not stored. +-- +-- Types and bounds have the following meaning: +-- +-- Type Bounds Note +-- ------------------------------------------------------ +-- MPL_FR -inf < x < +inf Free (unbounded) variable +-- MPL_LO lb <= x < +inf Variable with lower bound +-- MPL_UP -inf < x <= ub Variable with upper bound +-- MPL_DB lb <= x <= ub Double-bounded variable +-- MPL_FX x = lb Fixed variable +-- +-- where x is individual variable corresponding to the j-th column. +-- +-- If the column has no lower bound, *lb is set to zero; if the column +-- has no upper bound, *ub is set to zero; and if the column is of fixed +-- type, both *lb and *ub are set to the same value. +-- +-- *Returns* +-- +-- The routine returns the type of the j-th column as it is stated in +-- the table above. */ + +int mpl_get_col_bnds(MPL *mpl, int j, double *_lb, double *_ub) +{ ELEMVAR *var; + int type; + double lb, ub; + if (mpl->phase != 3) + xfault("mpl_get_col_bnds: invalid call sequence\n"); + if (!(1 <= j && j <= mpl->n)) + xfault("mpl_get_col_bnds: j = %d; column number out of range\n" + , j); + var = mpl->col[j]; +#if 0 /* 21/VII-2006 */ + if (var->var->lbnd == NULL && var->var->ubnd == NULL) + type = MPL_FR, lb = ub = 0.0; + else if (var->var->ubnd == NULL) + type = MPL_LO, lb = var->lbnd, ub = 0.0; + else if (var->var->lbnd == NULL) + type = MPL_UP, lb = 0.0, ub = var->ubnd; + else if (var->var->lbnd != var->var->ubnd) + type = MPL_DB, lb = var->lbnd, ub = var->ubnd; + else + type = MPL_FX, lb = ub = var->lbnd; +#else + lb = (var->var->lbnd == NULL ? -DBL_MAX : var->lbnd); + ub = (var->var->ubnd == NULL ? +DBL_MAX : var->ubnd); + if (lb == -DBL_MAX && ub == +DBL_MAX) + type = MPL_FR, lb = ub = 0.0; + else if (ub == +DBL_MAX) + type = MPL_LO, ub = 0.0; + else if (lb == -DBL_MAX) + type = MPL_UP, lb = 0.0; + else if (var->var->lbnd != var->var->ubnd) + type = MPL_DB; + else + type = MPL_FX; +#endif + if (_lb != NULL) *_lb = lb; + if (_ub != NULL) *_ub = ub; + return type; +} + +/*---------------------------------------------------------------------- +-- mpl_has_solve_stmt - check if model has solve statement. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_has_solve_stmt(MPL *mpl); +-- +-- *Returns* +-- +-- If the model has the solve statement, the routine returns non-zero, +-- otherwise zero is returned. */ + +int mpl_has_solve_stmt(MPL *mpl) +{ if (mpl->phase != 3) + xfault("mpl_has_solve_stmt: invalid call sequence\n"); + return mpl->flag_s; +} + +#if 1 /* 15/V-2010 */ +void mpl_put_row_soln(MPL *mpl, int i, int stat, double prim, + double dual) +{ /* store row (constraint/objective) solution components */ + xassert(mpl->phase == 3); + xassert(1 <= i && i <= mpl->m); + mpl->row[i]->stat = stat; + mpl->row[i]->prim = prim; + mpl->row[i]->dual = dual; + return; +} +#endif + +#if 1 /* 15/V-2010 */ +void mpl_put_col_soln(MPL *mpl, int j, int stat, double prim, + double dual) +{ /* store column (variable) solution components */ + xassert(mpl->phase == 3); + xassert(1 <= j && j <= mpl->n); + mpl->col[j]->stat = stat; + mpl->col[j]->prim = prim; + mpl->col[j]->dual = dual; + return; +} +#endif + +#if 0 /* 15/V-2010 */ +/*---------------------------------------------------------------------- +-- mpl_put_col_value - store column value. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- void mpl_put_col_value(MPL *mpl, int j, double val); +-- +-- *Description* +-- +-- The routine mpl_put_col_value stores numeric value of j-th column +-- into the translator database. It is assumed that the column value is +-- provided by the solver. */ + +void mpl_put_col_value(MPL *mpl, int j, double val) +{ if (mpl->phase != 3) + xfault("mpl_put_col_value: invalid call sequence\n"); + if (!(1 <= j && j <= mpl->n)) + xfault( + "mpl_put_col_value: j = %d; column number out of range\n", j); + mpl->col[j]->prim = val; + return; +} +#endif + +/*---------------------------------------------------------------------- +-- mpl_postsolve - postsolve model. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_postsolve(MPL *mpl); +-- +-- *Description* +-- +-- The routine mpl_postsolve performs postsolving of the model using +-- its description stored in the translator database. This phase means +-- executing statements, which follow the solve statement. +-- +-- If this routine is used, it should be called once after the routine +-- mpl_generate and if the latter returned the code 3. +-- +-- *Returns* +-- +-- The routine mpl_postsolve returns one of the following codes: +-- +-- 3 - model has been successfully postsolved. +-- 4 - processing failed due to some errors. In this case the calling +-- program should call the routine mpl_terminate to terminate model +-- processing. */ + +int mpl_postsolve(MPL *mpl) +{ if (!(mpl->phase == 3 && !mpl->flag_p)) + xfault("mpl_postsolve: invalid call sequence\n"); + /* set up error handler */ + if (setjmp(mpl->jump)) goto done; + /* perform postsolving */ + postsolve_model(mpl); + flush_output(mpl); + /* postsolving phase has been finished */ + xprintf("Model has been successfully processed\n"); +done: /* return to the calling program */ + return mpl->phase; +} + +/*---------------------------------------------------------------------- +-- mpl_terminate - free all resources used by translator. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- void mpl_terminate(MPL *mpl); +-- +-- *Description* +-- +-- The routine mpl_terminate frees all the resources used by the GNU +-- MathProg translator. */ + +void mpl_terminate(MPL *mpl) +{ if (setjmp(mpl->jump)) xassert(mpl != mpl); + switch (mpl->phase) + { case 0: + case 1: + case 2: + case 3: + /* there were no errors; clean the model content */ + clean_model(mpl); + xassert(mpl->a_list == NULL); +#if 1 /* 11/II-2008 */ + xassert(mpl->dca == NULL); +#endif + break; + case 4: + /* model processing has been finished due to error; delete + search trees, which may be created for some arrays */ + { ARRAY *a; + for (a = mpl->a_list; a != NULL; a = a->next) + if (a->tree != NULL) avl_delete_tree(a->tree); + } +#if 1 /* 11/II-2008 */ + free_dca(mpl); +#endif + break; + default: + xassert(mpl != mpl); + } + /* delete the translator database */ + xfree(mpl->image); + xfree(mpl->b_image); + xfree(mpl->f_image); + xfree(mpl->context); + dmp_delete_pool(mpl->pool); + avl_delete_tree(mpl->tree); + dmp_delete_pool(mpl->strings); + dmp_delete_pool(mpl->symbols); + dmp_delete_pool(mpl->tuples); + dmp_delete_pool(mpl->arrays); + dmp_delete_pool(mpl->members); + dmp_delete_pool(mpl->elemvars); + dmp_delete_pool(mpl->formulae); + dmp_delete_pool(mpl->elemcons); + xfree(mpl->sym_buf); + xfree(mpl->tup_buf); + rng_delete_rand(mpl->rand); + if (mpl->row != NULL) xfree(mpl->row); + if (mpl->col != NULL) xfree(mpl->col); + if (mpl->in_fp != NULL) glp_close(mpl->in_fp); + if (mpl->out_fp != NULL && mpl->out_fp != (void *)stdout) + glp_close(mpl->out_fp); + if (mpl->out_file != NULL) xfree(mpl->out_file); + if (mpl->prt_fp != NULL) glp_close(mpl->prt_fp); + if (mpl->prt_file != NULL) xfree(mpl->prt_file); + if (mpl->mod_file != NULL) xfree(mpl->mod_file); + xfree(mpl->mpl_buf); + xfree(mpl); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl05.c b/resources/3rdparty/glpk-4.53/src/glpmpl05.c new file mode 100644 index 000000000..2207572a7 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpmpl05.c @@ -0,0 +1,563 @@ +/* glpmpl05.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Authors: Andrew Makhorin <mao@gnu.org> +* Heinrich Schuchardt <xypron.glpk@gmx.de> +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "glpmpl.h" +#if 1 /* 11/VI-2013 */ +#include "jd.h" +#endif + +double fn_gmtime(MPL *mpl) +{ /* obtain the current calendar time (UTC) */ + time_t timer; + struct tm *tm; + int j; + time(&timer); + if (timer == (time_t)(-1)) +err: error(mpl, "gmtime(); unable to obtain current calendar time"); + tm = gmtime(&timer); + if (tm == NULL) goto err; + j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year); + if (j < 0) goto err; + return (((double)(j - jday(1, 1, 1970)) * 24.0 + + (double)tm->tm_hour) * 60.0 + (double)tm->tm_min) * 60.0 + + (double)tm->tm_sec; +} + +static char *week[] = { "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday" }; + +static char *moon[] = { "January", "February", "March", "April", "May", + "June", "July", "August", "September", "October", "November", + "December" }; + +static void error1(MPL *mpl, const char *str, const char *s, + const char *fmt, const char *f, const char *msg) +{ xprintf("Input string passed to str2time:\n"); + xprintf("%s\n", str); + xprintf("%*s\n", (s - str) + 1, "^"); + xprintf("Format string passed to str2time:\n"); + xprintf("%s\n", fmt); + xprintf("%*s\n", (f - fmt) + 1, "^"); + error(mpl, "%s", msg); + /* no return */ +} + +double fn_str2time(MPL *mpl, const char *str, const char *fmt) +{ /* convert character string to the calendar time */ + int j, year, month, day, hh, mm, ss, zone; + const char *s, *f; + year = month = day = hh = mm = ss = -1, zone = INT_MAX; + s = str; + for (f = fmt; *f != '\0'; f++) + { if (*f == '%') + { f++; + if (*f == 'b' || *f == 'h') + { /* the abbreviated month name */ + int k; + char *name; + if (month >= 0) + error1(mpl, str, s, fmt, f, "month multiply specified" + ); + while (*s == ' ') s++; + for (month = 1; month <= 12; month++) + { name = moon[month-1]; + for (k = 0; k <= 2; k++) + { if (toupper((unsigned char)s[k]) != + toupper((unsigned char)name[k])) goto next; + } + s += 3; + for (k = 3; name[k] != '\0'; k++) + { if (toupper((unsigned char)*s) != + toupper((unsigned char)name[k])) break; + s++; + } + break; +next: ; + } + if (month > 12) + error1(mpl, str, s, fmt, f, "abbreviated month name m" + "issing or invalid"); + } + else if (*f == 'd') + { /* the day of the month as a decimal number (01..31) */ + if (day >= 0) + error1(mpl, str, s, fmt, f, "day multiply specified"); + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "day missing or invalid"); + day = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + day = 10 * day + ((*s++) - '0'); + if (!(1 <= day && day <= 31)) + error1(mpl, str, s, fmt, f, "day out of range"); + } + else if (*f == 'H') + { /* the hour as a decimal number, using a 24-hour clock + (00..23) */ + if (hh >= 0) + error1(mpl, str, s, fmt, f, "hour multiply specified") + ; + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "hour missing or invalid") + ; + hh = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + hh = 10 * hh + ((*s++) - '0'); + if (!(0 <= hh && hh <= 23)) + error1(mpl, str, s, fmt, f, "hour out of range"); + } + else if (*f == 'm') + { /* the month as a decimal number (01..12) */ + if (month >= 0) + error1(mpl, str, s, fmt, f, "month multiply specified" + ); + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "month missing or invalid" + ); + month = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + month = 10 * month + ((*s++) - '0'); + if (!(1 <= month && month <= 12)) + error1(mpl, str, s, fmt, f, "month out of range"); + } + else if (*f == 'M') + { /* the minute as a decimal number (00..59) */ + if (mm >= 0) + error1(mpl, str, s, fmt, f, "minute multiply specifie" + "d"); + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "minute missing or invali" + "d"); + mm = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + mm = 10 * mm + ((*s++) - '0'); + if (!(0 <= mm && mm <= 59)) + error1(mpl, str, s, fmt, f, "minute out of range"); + } + else if (*f == 'S') + { /* the second as a decimal number (00..60) */ + if (ss >= 0) + error1(mpl, str, s, fmt, f, "second multiply specifie" + "d"); + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "second missing or invali" + "d"); + ss = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + ss = 10 * ss + ((*s++) - '0'); + if (!(0 <= ss && ss <= 60)) + error1(mpl, str, s, fmt, f, "second out of range"); + } + else if (*f == 'y') + { /* the year without a century as a decimal number + (00..99); the values 00 to 68 mean the years 2000 to + 2068 while the values 69 to 99 mean the years 1969 to + 1999 */ + if (year >= 0) + error1(mpl, str, s, fmt, f, "year multiply specified") + ; + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "year missing or invalid") + ; + year = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + year = 10 * year + ((*s++) - '0'); + year += (year >= 69 ? 1900 : 2000); + } + else if (*f == 'Y') + { /* the year as a decimal number, using the Gregorian + calendar */ + if (year >= 0) + error1(mpl, str, s, fmt, f, "year multiply specified") + ; + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "year missing or invalid") + ; + year = 0; + for (j = 1; j <= 4; j++) + { if (!('0' <= *s && *s <= '9')) break; + year = 10 * year + ((*s++) - '0'); + } + if (!(1 <= year && year <= 4000)) + error1(mpl, str, s, fmt, f, "year out of range"); + } + else if (*f == 'z') + { /* time zone offset in the form zhhmm */ + int z, hh, mm; + if (zone != INT_MAX) + error1(mpl, str, s, fmt, f, "time zone offset multipl" + "y specified"); + while (*s == ' ') s++; + if (*s == 'Z') + { z = hh = mm = 0, s++; + goto skip; + } + if (*s == '+') + z = +1, s++; + else if (*s == '-') + z = -1, s++; + else + error1(mpl, str, s, fmt, f, "time zone offset sign mi" + "ssing"); + hh = 0; + for (j = 1; j <= 2; j++) + { if (!('0' <= *s && *s <= '9')) +err1: error1(mpl, str, s, fmt, f, "time zone offset valu" + "e incomplete or invalid"); + hh = 10 * hh + ((*s++) - '0'); + } + if (hh > 23) +err2: error1(mpl, str, s, fmt, f, "time zone offset value o" + "ut of range"); + if (*s == ':') + { s++; + if (!('0' <= *s && *s <= '9')) goto err1; + } + mm = 0; + if (!('0' <= *s && *s <= '9')) goto skip; + for (j = 1; j <= 2; j++) + { if (!('0' <= *s && *s <= '9')) goto err1; + mm = 10 * mm + ((*s++) - '0'); + } + if (mm > 59) goto err2; +skip: zone = z * (60 * hh + mm); + } + else if (*f == '%') + { /* literal % character */ + goto test; + } + else + error1(mpl, str, s, fmt, f, "invalid conversion specifie" + "r"); + } + else if (*f == ' ') + ; + else +test: { /* check a matching character in the input string */ + if (*s != *f) + error1(mpl, str, s, fmt, f, "character mismatch"); + s++; + } + } + if (year < 0) year = 1970; + if (month < 0) month = 1; + if (day < 0) day = 1; + if (hh < 0) hh = 0; + if (mm < 0) mm = 0; + if (ss < 0) ss = 0; + if (zone == INT_MAX) zone = 0; + j = jday(day, month, year); + xassert(j >= 0); + return (((double)(j - jday(1, 1, 1970)) * 24.0 + (double)hh) * + 60.0 + (double)mm) * 60.0 + (double)ss - 60.0 * (double)zone; +} + +static void error2(MPL *mpl, const char *fmt, const char *f, + const char *msg) +{ xprintf("Format string passed to time2str:\n"); + xprintf("%s\n", fmt); + xprintf("%*s\n", (f - fmt) + 1, "^"); + error(mpl, "%s", msg); + /* no return */ +} + +static int weekday(int j) +{ /* determine weekday number (1 = Mon, ..., 7 = Sun) */ + return (j + jday(1, 1, 1970)) % 7 + 1; +} + +static int firstday(int year) +{ /* determine the first day of the first week for a specified year + according to ISO 8601 */ + int j; + /* if 1 January is Monday, Tuesday, Wednesday or Thursday, it is + in week 01; if 1 January is Friday, Saturday or Sunday, it is + in week 52 or 53 of the previous year */ + j = jday(1, 1, year) - jday(1, 1, 1970); + switch (weekday(j)) + { case 1: /* 1 Jan is Mon */ j += 0; break; + case 2: /* 1 Jan is Tue */ j -= 1; break; + case 3: /* 1 Jan is Wed */ j -= 2; break; + case 4: /* 1 Jan is Thu */ j -= 3; break; + case 5: /* 1 Jan is Fri */ j += 3; break; + case 6: /* 1 Jan is Sat */ j += 2; break; + case 7: /* 1 Jan is Sun */ j += 1; break; + default: xassert(j != j); + } + /* the first day of the week must be Monday */ + xassert(weekday(j) == 1); + return j; +} + +void fn_time2str(MPL *mpl, char *str, double t, const char *fmt) +{ /* convert the calendar time to character string */ + int j, year, month, day, hh, mm, ss, len; + double temp; + const char *f; + char buf[MAX_LENGTH+1]; + if (!(-62135596800.0 <= t && t <= 64092211199.0)) + error(mpl, "time2str(%.*g,...); argument out of range", + DBL_DIG, t); + t = floor(t + 0.5); + temp = fabs(t) / 86400.0; + j = (int)floor(temp); + if (t < 0.0) + { if (temp == floor(temp)) + j = - j; + else + j = - (j + 1); + } + xassert(jdate(j + jday(1, 1, 1970), &day, &month, &year) == 0); + ss = (int)(t - 86400.0 * (double)j); + xassert(0 <= ss && ss < 86400); + mm = ss / 60, ss %= 60; + hh = mm / 60, mm %= 60; + len = 0; + for (f = fmt; *f != '\0'; f++) + { if (*f == '%') + { f++; + if (*f == 'a') + { /* the abbreviated weekday name */ + memcpy(buf, week[weekday(j)-1], 3), buf[3] = '\0'; + } + else if (*f == 'A') + { /* the full weekday name */ + strcpy(buf, week[weekday(j)-1]); + } + else if (*f == 'b' || *f == 'h') + { /* the abbreviated month name */ + memcpy(buf, moon[month-1], 3), buf[3] = '\0'; + } + else if (*f == 'B') + { /* the full month name */ + strcpy(buf, moon[month-1]); + } + else if (*f == 'C') + { /* the century of the year */ + sprintf(buf, "%02d", year / 100); + } + else if (*f == 'd') + { /* the day of the month as a decimal number (01..31) */ + sprintf(buf, "%02d", day); + } + else if (*f == 'D') + { /* the date using the format %m/%d/%y */ + sprintf(buf, "%02d/%02d/%02d", month, day, year % 100); + } + else if (*f == 'e') + { /* the day of the month like with %d, but padded with + blank (1..31) */ + sprintf(buf, "%2d", day); + } + else if (*f == 'F') + { /* the date using the format %Y-%m-%d */ + sprintf(buf, "%04d-%02d-%02d", year, month, day); + } + else if (*f == 'g') + { /* the year corresponding to the ISO week number, but + without the century (range 00 through 99); this has + the same format and value as %y, except that if the + ISO week number (see %V) belongs to the previous or + next year, that year is used instead */ + int iso; + if (j < firstday(year)) + iso = year - 1; + else if (j < firstday(year + 1)) + iso = year; + else + iso = year + 1; + sprintf(buf, "%02d", iso % 100); + } + else if (*f == 'G') + { /* the year corresponding to the ISO week number; this + has the same format and value as %Y, excepth that if + the ISO week number (see %V) belongs to the previous + or next year, that year is used instead */ + int iso; + if (j < firstday(year)) + iso = year - 1; + else if (j < firstday(year + 1)) + iso = year; + else + iso = year + 1; + sprintf(buf, "%04d", iso); + } + else if (*f == 'H') + { /* the hour as a decimal number, using a 24-hour clock + (00..23) */ + sprintf(buf, "%02d", hh); + } + else if (*f == 'I') + { /* the hour as a decimal number, using a 12-hour clock + (01..12) */ + sprintf(buf, "%02d", + hh == 0 ? 12 : hh <= 12 ? hh : hh - 12); + } + else if (*f == 'j') + { /* the day of the year as a decimal number (001..366) */ + sprintf(buf, "%03d", + jday(day, month, year) - jday(1, 1, year) + 1); + } + else if (*f == 'k') + { /* the hour as a decimal number, using a 24-hour clock + like %H, but padded with blank (0..23) */ + sprintf(buf, "%2d", hh); + } + else if (*f == 'l') + { /* the hour as a decimal number, using a 12-hour clock + like %I, but padded with blank (1..12) */ + sprintf(buf, "%2d", + hh == 0 ? 12 : hh <= 12 ? hh : hh - 12); + } + else if (*f == 'm') + { /* the month as a decimal number (01..12) */ + sprintf(buf, "%02d", month); + } + else if (*f == 'M') + { /* the minute as a decimal number (00..59) */ + sprintf(buf, "%02d", mm); + } + else if (*f == 'p') + { /* either AM or PM, according to the given time value; + noon is treated as PM and midnight as AM */ + strcpy(buf, hh <= 11 ? "AM" : "PM"); + } + else if (*f == 'P') + { /* either am or pm, according to the given time value; + noon is treated as pm and midnight as am */ + strcpy(buf, hh <= 11 ? "am" : "pm"); + } + else if (*f == 'r') + { /* the calendar time using the format %I:%M:%S %p */ + sprintf(buf, "%02d:%02d:%02d %s", + hh == 0 ? 12 : hh <= 12 ? hh : hh - 12, + mm, ss, hh <= 11 ? "AM" : "PM"); + } + else if (*f == 'R') + { /* the hour and minute using the format %H:%M */ + sprintf(buf, "%02d:%02d", hh, mm); + } + else if (*f == 'S') + { /* the second as a decimal number (00..59) */ + sprintf(buf, "%02d", ss); + } + else if (*f == 'T') + { /* the time of day using the format %H:%M:%S */ + sprintf(buf, "%02d:%02d:%02d", hh, mm, ss); + } + else if (*f == 'u') + { /* the day of the week as a decimal number (1..7), + Monday being 1 */ + sprintf(buf, "%d", weekday(j)); + } + else if (*f == 'U') + { /* the week number of the current year as a decimal + number (range 00 through 53), starting with the first + Sunday as the first day of the first week; days + preceding the first Sunday in the year are considered + to be in week 00 */ +#if 1 /* 09/I-2009 */ +#undef sun +/* causes compilation error in SunOS */ +#endif + int sun; + /* sun = the first Sunday of the year */ + sun = jday(1, 1, year) - jday(1, 1, 1970); + sun += (7 - weekday(sun)); + sprintf(buf, "%02d", (j + 7 - sun) / 7); + } + else if (*f == 'V') + { /* the ISO week number as a decimal number (range 01 + through 53); ISO weeks start with Monday and end with + Sunday; week 01 of a year is the first week which has + the majority of its days in that year; week 01 of + a year can contain days from the previous year; the + week before week 01 of a year is the last week (52 or + 53) of the previous year even if it contains days + from the new year */ + int iso; + if (j < firstday(year)) + iso = j - firstday(year - 1); + else if (j < firstday(year + 1)) + iso = j - firstday(year); + else + iso = j - firstday(year + 1); + sprintf(buf, "%02d", iso / 7 + 1); + } + else if (*f == 'w') + { /* the day of the week as a decimal number (0..6), + Sunday being 0 */ + sprintf(buf, "%d", weekday(j) % 7); + } + else if (*f == 'W') + { /* the week number of the current year as a decimal + number (range 00 through 53), starting with the first + Monday as the first day of the first week; days + preceding the first Monday in the year are considered + to be in week 00 */ + int mon; + /* mon = the first Monday of the year */ + mon = jday(1, 1, year) - jday(1, 1, 1970); + mon += (8 - weekday(mon)) % 7; + sprintf(buf, "%02d", (j + 7 - mon) / 7); + } + else if (*f == 'y') + { /* the year without a century as a decimal number + (00..99) */ + sprintf(buf, "%02d", year % 100); + } + else if (*f == 'Y') + { /* the year as a decimal number, using the Gregorian + calendar */ + sprintf(buf, "%04d", year); + } + else if (*f == '%') + { /* a literal % character */ + buf[0] = '%', buf[1] = '\0'; + } + else + error2(mpl, fmt, f, "invalid conversion specifier"); + } + else + buf[0] = *f, buf[1] = '\0'; + if (len + strlen(buf) > MAX_LENGTH) + error(mpl, "time2str; output string length exceeds %d chara" + "cters", MAX_LENGTH); + memcpy(str+len, buf, strlen(buf)); + len += strlen(buf); + } + str[len] = '\0'; + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl06.c b/resources/3rdparty/glpk-4.53/src/glpmpl06.c new file mode 100644 index 000000000..8ab122a75 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpmpl06.c @@ -0,0 +1,1000 @@ +/* glpmpl06.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "glpmpl.h" +#include "glpsql.h" + +/**********************************************************************/ + +#define CSV_FIELD_MAX 50 +/* maximal number of fields in record */ + +#define CSV_FDLEN_MAX 100 +/* maximal field length */ + +struct csv +{ /* comma-separated values file */ + int mode; + /* 'R' = reading; 'W' = writing */ + char *fname; + /* name of csv file */ + FILE *fp; + /* stream assigned to csv file */ + jmp_buf jump; + /* address for non-local go to in case of error */ + int count; + /* record count */ + /*--------------------------------------------------------------*/ + /* used only for input csv file */ + int c; + /* current character or EOF */ + int what; + /* current marker: */ +#define CSV_EOF 0 /* end-of-file */ +#define CSV_EOR 1 /* end-of-record */ +#define CSV_NUM 2 /* floating-point number */ +#define CSV_STR 3 /* character string */ + char field[CSV_FDLEN_MAX+1]; + /* current field just read */ + int nf; + /* number of fields in the csv file */ + int ref[1+CSV_FIELD_MAX]; + /* ref[k] = k', if k-th field of the csv file corresponds to + k'-th field in the table statement; if ref[k] = 0, k-th field + of the csv file is ignored */ +#if 1 /* 01/VI-2010 */ + int nskip; + /* number of comment records preceding the header record */ +#endif +}; + +#undef read_char + +static void read_char(struct csv *csv) +{ /* read character from csv data file */ + int c; + xassert(csv->c != EOF); + if (csv->c == '\n') csv->count++; +loop: c = fgetc(csv->fp); + if (ferror(csv->fp)) + { xprintf("%s:%d: read error - %s\n", csv->fname, csv->count, + strerror(errno)); + longjmp(csv->jump, 0); + } + if (feof(csv->fp)) + { if (csv->c == '\n') + { csv->count--; + c = EOF; + } + else + { xprintf("%s:%d: warning: missing final end-of-line\n", + csv->fname, csv->count); + c = '\n'; + } + } + else if (c == '\r') + goto loop; + else if (c == '\n') + ; + else if (iscntrl(c)) + { xprintf("%s:%d: invalid control character 0x%02X\n", + csv->fname, csv->count, c); + longjmp(csv->jump, 0); + } + csv->c = c; + return; +} + +static void read_field(struct csv *csv) +{ /* read field from csv data file */ + /* check for end of file */ + if (csv->c == EOF) + { csv->what = CSV_EOF; + strcpy(csv->field, "EOF"); + goto done; + } + /* check for end of record */ + if (csv->c == '\n') + { csv->what = CSV_EOR; + strcpy(csv->field, "EOR"); + read_char(csv); + if (csv->c == ',') +err1: { xprintf("%s:%d: empty field not allowed\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } + if (csv->c == '\n') + { xprintf("%s:%d: empty record not allowed\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } +#if 1 /* 01/VI-2010 */ + /* skip comment records; may appear only before the very first + record containing field names */ + if (csv->c == '#' && csv->count == 1) + { while (csv->c == '#') + { while (csv->c != '\n') + read_char(csv); + read_char(csv); + csv->nskip++; + } + } +#endif + goto done; + } + /* skip comma before next field */ + if (csv->c == ',') + read_char(csv); + /* read field */ + if (csv->c == '\'' || csv->c == '"') + { /* read a field enclosed in quotes */ + int quote = csv->c, len = 0; + csv->what = CSV_STR; + /* skip opening quote */ + read_char(csv); + /* read field characters within quotes */ + for (;;) + { /* check for closing quote and read it */ + if (csv->c == quote) + { read_char(csv); + if (csv->c == quote) + ; + else if (csv->c == ',' || csv->c == '\n') + break; + else + { xprintf("%s:%d: invalid field\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } + } + /* check the current field length */ + if (len == CSV_FDLEN_MAX) +err2: { xprintf("%s:%d: field too long\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } + /* add the current character to the field */ + csv->field[len++] = (char)csv->c; + /* read the next character */ + read_char(csv); + } + /* the field has been read */ + if (len == 0) goto err1; + csv->field[len] = '\0'; + } + else + { /* read a field not enclosed in quotes */ + int len = 0; + double temp; + csv->what = CSV_NUM; + while (!(csv->c == ',' || csv->c == '\n')) + { /* quotes within the field are not allowed */ + if (csv->c == '\'' || csv->c == '"') + { xprintf("%s:%d: invalid use of single or double quote wi" + "thin field\n", csv->fname, csv->count); + longjmp(csv->jump, 0); + } + /* check the current field length */ + if (len == CSV_FDLEN_MAX) goto err2; + /* add the current character to the field */ + csv->field[len++] = (char)csv->c; + /* read the next character */ + read_char(csv); + } + /* the field has been read */ + if (len == 0) goto err1; + csv->field[len] = '\0'; + /* check the field type */ + if (str2num(csv->field, &temp)) csv->what = CSV_STR; + } +done: return; +} + +static struct csv *csv_open_file(TABDCA *dca, int mode) +{ /* open csv data file */ + struct csv *csv; + /* create control structure */ + csv = xmalloc(sizeof(struct csv)); + csv->mode = mode; + csv->fname = NULL; + csv->fp = NULL; + if (setjmp(csv->jump)) goto fail; + csv->count = 0; + csv->c = '\n'; + csv->what = 0; + csv->field[0] = '\0'; + csv->nf = 0; + /* try to open the csv data file */ + if (mpl_tab_num_args(dca) < 2) + { xprintf("csv_driver: file name not specified\n"); + longjmp(csv->jump, 0); + } + csv->fname = xmalloc(strlen(mpl_tab_get_arg(dca, 2))+1); + strcpy(csv->fname, mpl_tab_get_arg(dca, 2)); + if (mode == 'R') + { /* open the file for reading */ + int k; + csv->fp = fopen(csv->fname, "r"); + if (csv->fp == NULL) + { xprintf("csv_driver: unable to open %s - %s\n", + csv->fname, strerror(errno)); + longjmp(csv->jump, 0); + } +#if 1 /* 01/VI-2010 */ + csv->nskip = 0; +#endif + /* skip fake new-line */ + read_field(csv); + xassert(csv->what == CSV_EOR); + /* read field names */ + xassert(csv->nf == 0); + for (;;) + { read_field(csv); + if (csv->what == CSV_EOR) + break; + if (csv->what != CSV_STR) + { xprintf("%s:%d: invalid field name\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } + if (csv->nf == CSV_FIELD_MAX) + { xprintf("%s:%d: too many fields\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } + csv->nf++; + /* find corresponding field in the table statement */ + for (k = mpl_tab_num_flds(dca); k >= 1; k--) + { if (strcmp(mpl_tab_get_name(dca, k), csv->field) == 0) + break; + } + csv->ref[csv->nf] = k; + } + /* find dummy RECNO field in the table statement */ + for (k = mpl_tab_num_flds(dca); k >= 1; k--) + if (strcmp(mpl_tab_get_name(dca, k), "RECNO") == 0) break; + csv->ref[0] = k; + } + else if (mode == 'W') + { /* open the file for writing */ + int k, nf; + csv->fp = fopen(csv->fname, "w"); + if (csv->fp == NULL) + { xprintf("csv_driver: unable to create %s - %s\n", + csv->fname, strerror(errno)); + longjmp(csv->jump, 0); + } + /* write field names */ + nf = mpl_tab_num_flds(dca); + for (k = 1; k <= nf; k++) + fprintf(csv->fp, "%s%c", mpl_tab_get_name(dca, k), + k < nf ? ',' : '\n'); + csv->count++; + } + else + xassert(mode != mode); + /* the file has been open */ + return csv; +fail: /* the file cannot be open */ + if (csv->fname != NULL) xfree(csv->fname); + if (csv->fp != NULL) fclose(csv->fp); + xfree(csv); + return NULL; +} + +static int csv_read_record(TABDCA *dca, struct csv *csv) +{ /* read next record from csv data file */ + int k, ret = 0; + xassert(csv->mode == 'R'); + if (setjmp(csv->jump)) + { ret = 1; + goto done; + } + /* read dummy RECNO field */ + if (csv->ref[0] > 0) +#if 0 /* 01/VI-2010 */ + mpl_tab_set_num(dca, csv->ref[0], csv->count-1); +#else + mpl_tab_set_num(dca, csv->ref[0], csv->count-csv->nskip-1); +#endif + /* read fields */ + for (k = 1; k <= csv->nf; k++) + { read_field(csv); + if (csv->what == CSV_EOF) + { /* end-of-file reached */ + xassert(k == 1); + ret = -1; + goto done; + } + else if (csv->what == CSV_EOR) + { /* end-of-record reached */ + int lack = csv->nf - k + 1; + if (lack == 1) + xprintf("%s:%d: one field missing\n", csv->fname, + csv->count); + else + xprintf("%s:%d: %d fields missing\n", csv->fname, + csv->count, lack); + longjmp(csv->jump, 0); + } + else if (csv->what == CSV_NUM) + { /* floating-point number */ + if (csv->ref[k] > 0) + { double num; + xassert(str2num(csv->field, &num) == 0); + mpl_tab_set_num(dca, csv->ref[k], num); + } + } + else if (csv->what == CSV_STR) + { /* character string */ + if (csv->ref[k] > 0) + mpl_tab_set_str(dca, csv->ref[k], csv->field); + } + else + xassert(csv != csv); + } + /* now there must be NL */ + read_field(csv); + xassert(csv->what != CSV_EOF); + if (csv->what != CSV_EOR) + { xprintf("%s:%d: too many fields\n", csv->fname, csv->count); + longjmp(csv->jump, 0); + } +done: return ret; +} + +static int csv_write_record(TABDCA *dca, struct csv *csv) +{ /* write next record to csv data file */ + int k, nf, ret = 0; + const char *c; + xassert(csv->mode == 'W'); + nf = mpl_tab_num_flds(dca); + for (k = 1; k <= nf; k++) + { switch (mpl_tab_get_type(dca, k)) + { case 'N': + fprintf(csv->fp, "%.*g", DBL_DIG, + mpl_tab_get_num(dca, k)); + break; + case 'S': + fputc('"', csv->fp); + for (c = mpl_tab_get_str(dca, k); *c != '\0'; c++) + { if (*c == '"') + fputc('"', csv->fp), fputc('"', csv->fp); + else + fputc(*c, csv->fp); + } + fputc('"', csv->fp); + break; + default: + xassert(dca != dca); + } + fputc(k < nf ? ',' : '\n', csv->fp); + } + csv->count++; + if (ferror(csv->fp)) + { xprintf("%s:%d: write error - %s\n", csv->fname, csv->count, + strerror(errno)); + ret = 1; + } + return ret; +} + +static int csv_close_file(TABDCA *dca, struct csv *csv) +{ /* close csv data file */ + int ret = 0; + xassert(dca == dca); + if (csv->mode == 'W') + { fflush(csv->fp); + if (ferror(csv->fp)) + { xprintf("%s:%d: write error - %s\n", csv->fname, + csv->count, strerror(errno)); + ret = 1; + } + } + xfree(csv->fname); + fclose(csv->fp); + xfree(csv); + return ret; +} + +/**********************************************************************/ + +#define DBF_FIELD_MAX 50 +/* maximal number of fields in record */ + +#define DBF_FDLEN_MAX 100 +/* maximal field length */ + +struct dbf +{ /* xBASE data file */ + int mode; + /* 'R' = reading; 'W' = writing */ + char *fname; + /* name of xBASE file */ + FILE *fp; + /* stream assigned to xBASE file */ + jmp_buf jump; + /* address for non-local go to in case of error */ + int offset; + /* offset of a byte to be read next */ + int count; + /* record count */ + int nf; + /* number of fields */ + int ref[1+DBF_FIELD_MAX]; + /* ref[k] = k', if k-th field of the csv file corresponds to + k'-th field in the table statement; if ref[k] = 0, k-th field + of the csv file is ignored */ + int type[1+DBF_FIELD_MAX]; + /* type[k] is type of k-th field */ + int len[1+DBF_FIELD_MAX]; + /* len[k] is length of k-th field */ + int prec[1+DBF_FIELD_MAX]; + /* prec[k] is precision of k-th field */ +}; + +static int read_byte(struct dbf *dbf) +{ /* read byte from xBASE data file */ + int b; + b = fgetc(dbf->fp); + if (ferror(dbf->fp)) + { xprintf("%s:0x%X: read error - %s\n", dbf->fname, + dbf->offset, strerror(errno)); + longjmp(dbf->jump, 0); + } + if (feof(dbf->fp)) + { xprintf("%s:0x%X: unexpected end of file\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + xassert(0x00 <= b && b <= 0xFF); + dbf->offset++; + return b; +} + +static void read_header(TABDCA *dca, struct dbf *dbf) +{ /* read xBASE data file header */ + int b, j, k, recl; + char name[10+1]; + /* (ignored) */ + for (j = 1; j <= 10; j++) + read_byte(dbf); + /* length of each record, in bytes */ + recl = read_byte(dbf); + recl += read_byte(dbf) << 8; + /* (ignored) */ + for (j = 1; j <= 20; j++) + read_byte(dbf); + /* field descriptor array */ + xassert(dbf->nf == 0); + for (;;) + { /* check for end of array */ + b = read_byte(dbf); + if (b == 0x0D) break; + if (dbf->nf == DBF_FIELD_MAX) + { xprintf("%s:0x%X: too many fields\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + dbf->nf++; + /* field name */ + name[0] = (char)b; + for (j = 1; j < 10; j++) + { b = read_byte(dbf); + name[j] = (char)b; + } + name[10] = '\0'; + b = read_byte(dbf); + if (b != 0x00) + { xprintf("%s:0x%X: invalid field name\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + /* find corresponding field in the table statement */ + for (k = mpl_tab_num_flds(dca); k >= 1; k--) + if (strcmp(mpl_tab_get_name(dca, k), name) == 0) break; + dbf->ref[dbf->nf] = k; + /* field type */ + b = read_byte(dbf); + if (!(b == 'C' || b == 'N')) + { xprintf("%s:0x%X: invalid field type\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + dbf->type[dbf->nf] = b; + /* (ignored) */ + for (j = 1; j <= 4; j++) + read_byte(dbf); + /* field length */ + b = read_byte(dbf); + if (b == 0) + { xprintf("%s:0x%X: invalid field length\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + if (b > DBF_FDLEN_MAX) + { xprintf("%s:0x%X: field too long\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + dbf->len[dbf->nf] = b; + recl -= b; + /* (ignored) */ + for (j = 1; j <= 15; j++) + read_byte(dbf); + } + if (recl != 1) + { xprintf("%s:0x%X: invalid file header\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + /* find dummy RECNO field in the table statement */ + for (k = mpl_tab_num_flds(dca); k >= 1; k--) + if (strcmp(mpl_tab_get_name(dca, k), "RECNO") == 0) break; + dbf->ref[0] = k; + return; +} + +static void parse_third_arg(TABDCA *dca, struct dbf *dbf) +{ /* parse xBASE file format (third argument) */ + int j, k, temp; + const char *arg; + dbf->nf = mpl_tab_num_flds(dca); + arg = mpl_tab_get_arg(dca, 3), j = 0; + for (k = 1; k <= dbf->nf; k++) + { /* parse specification of k-th field */ + if (arg[j] == '\0') + { xprintf("xBASE driver: field %s: specification missing\n", + mpl_tab_get_name(dca, k)); + longjmp(dbf->jump, 0); + } + /* parse field type */ + if (arg[j] == 'C' || arg[j] == 'N') + dbf->type[k] = arg[j], j++; + else + { xprintf("xBASE driver: field %s: invalid field type\n", + mpl_tab_get_name(dca, k)); + longjmp(dbf->jump, 0); + } + /* check for left parenthesis */ + if (arg[j] == '(') + j++; + else +err: { xprintf("xBASE driver: field %s: invalid field format\n", + mpl_tab_get_name(dca, k)); + longjmp(dbf->jump, 0); + } + /* parse field length */ + temp = 0; + while (isdigit(arg[j])) + { if (temp > DBF_FDLEN_MAX) break; + temp = 10 * temp + (arg[j] - '0'), j++; + } + if (!(1 <= temp && temp <= DBF_FDLEN_MAX)) + { xprintf("xBASE driver: field %s: invalid field length\n", + mpl_tab_get_name(dca, k)); + longjmp(dbf->jump, 0); + } + dbf->len[k] = temp; + /* parse optional field precision */ + if (dbf->type[k] == 'N' && arg[j] == ',') + { j++; + temp = 0; + while (isdigit(arg[j])) + { if (temp > dbf->len[k]) break; + temp = 10 * temp + (arg[j] - '0'), j++; + } + if (temp > dbf->len[k]) + { xprintf("xBASE driver: field %s: invalid field precision" + "\n", mpl_tab_get_name(dca, k)); + longjmp(dbf->jump, 0); + } + dbf->prec[k] = temp; + } + else + dbf->prec[k] = 0; + /* check for right parenthesis */ + if (arg[j] == ')') + j++; + else + goto err; + } + /* ignore other specifications */ + return; +} + +static void write_byte(struct dbf *dbf, int b) +{ /* write byte to xBASE data file */ + fputc(b, dbf->fp); + dbf->offset++; + return; +} + +static void write_header(TABDCA *dca, struct dbf *dbf) +{ /* write xBASE data file header */ + int j, k, temp; + const char *name; + /* version number */ + write_byte(dbf, 0x03 /* file without DBT */); + /* date of last update (YYMMDD) */ + write_byte(dbf, 70 /* 1970 */); + write_byte(dbf, 1 /* January */); + write_byte(dbf, 1 /* 1st */); + /* number of records (unknown so far) */ + for (j = 1; j <= 4; j++) + write_byte(dbf, 0xFF); + /* length of the header, in bytes */ + temp = 32 + dbf->nf * 32 + 1; + write_byte(dbf, temp); + write_byte(dbf, temp >> 8); + /* length of each record, in bytes */ + temp = 1; + for (k = 1; k <= dbf->nf; k++) + temp += dbf->len[k]; + write_byte(dbf, temp); + write_byte(dbf, temp >> 8); + /* (reserved) */ + for (j = 1; j <= 20; j++) + write_byte(dbf, 0x00); + /* field descriptor array */ + for (k = 1; k <= dbf->nf; k++) + { /* field name (terminated by 0x00) */ + name = mpl_tab_get_name(dca, k); + for (j = 0; j < 10 && name[j] != '\0'; j++) + write_byte(dbf, name[j]); + for (j = j; j < 11; j++) + write_byte(dbf, 0x00); + /* field type */ + write_byte(dbf, dbf->type[k]); + /* (reserved) */ + for (j = 1; j <= 4; j++) + write_byte(dbf, 0x00); + /* field length */ + write_byte(dbf, dbf->len[k]); + /* field precision */ + write_byte(dbf, dbf->prec[k]); + /* (reserved) */ + for (j = 1; j <= 14; j++) + write_byte(dbf, 0x00); + } + /* end of header */ + write_byte(dbf, 0x0D); + return; +} + +static struct dbf *dbf_open_file(TABDCA *dca, int mode) +{ /* open xBASE data file */ + struct dbf *dbf; + /* create control structure */ + dbf = xmalloc(sizeof(struct dbf)); + dbf->mode = mode; + dbf->fname = NULL; + dbf->fp = NULL; + if (setjmp(dbf->jump)) goto fail; + dbf->offset = 0; + dbf->count = 0; + dbf->nf = 0; + /* try to open the xBASE data file */ + if (mpl_tab_num_args(dca) < 2) + { xprintf("xBASE driver: file name not specified\n"); + longjmp(dbf->jump, 0); + } + dbf->fname = xmalloc(strlen(mpl_tab_get_arg(dca, 2))+1); + strcpy(dbf->fname, mpl_tab_get_arg(dca, 2)); + if (mode == 'R') + { /* open the file for reading */ + dbf->fp = fopen(dbf->fname, "rb"); + if (dbf->fp == NULL) + { xprintf("xBASE driver: unable to open %s - %s\n", + dbf->fname, strerror(errno)); + longjmp(dbf->jump, 0); + } + read_header(dca, dbf); + } + else if (mode == 'W') + { /* open the file for writing */ + if (mpl_tab_num_args(dca) < 3) + { xprintf("xBASE driver: file format not specified\n"); + longjmp(dbf->jump, 0); + } + parse_third_arg(dca, dbf); + dbf->fp = fopen(dbf->fname, "wb"); + if (dbf->fp == NULL) + { xprintf("xBASE driver: unable to create %s - %s\n", + dbf->fname, strerror(errno)); + longjmp(dbf->jump, 0); + } + write_header(dca, dbf); + } + else + xassert(mode != mode); + /* the file has been open */ + return dbf; +fail: /* the file cannot be open */ + if (dbf->fname != NULL) xfree(dbf->fname); + if (dbf->fp != NULL) fclose(dbf->fp); + xfree(dbf); + return NULL; +} + +static int dbf_read_record(TABDCA *dca, struct dbf *dbf) +{ /* read next record from xBASE data file */ + int b, j, k, ret = 0; + char buf[DBF_FDLEN_MAX+1]; + xassert(dbf->mode == 'R'); + if (setjmp(dbf->jump)) + { ret = 1; + goto done; + } + /* check record flag */ + b = read_byte(dbf); + if (b == 0x1A) + { /* end of data */ + ret = -1; + goto done; + } + if (b != 0x20) + { xprintf("%s:0x%X: invalid record flag\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + /* read dummy RECNO field */ + if (dbf->ref[0] > 0) + mpl_tab_set_num(dca, dbf->ref[0], dbf->count+1); + /* read fields */ + for (k = 1; k <= dbf->nf; k++) + { /* read k-th field */ + for (j = 0; j < dbf->len[k]; j++) + buf[j] = (char)read_byte(dbf); + buf[dbf->len[k]] = '\0'; + /* set field value */ + if (dbf->type[k] == 'C') + { /* character field */ + if (dbf->ref[k] > 0) + mpl_tab_set_str(dca, dbf->ref[k], strtrim(buf)); + } + else if (dbf->type[k] == 'N') + { /* numeric field */ + if (dbf->ref[k] > 0) + { double num; + strspx(buf); + xassert(str2num(buf, &num) == 0); + mpl_tab_set_num(dca, dbf->ref[k], num); + } + } + else + xassert(dbf != dbf); + } + /* increase record count */ + dbf->count++; +done: return ret; +} + +static int dbf_write_record(TABDCA *dca, struct dbf *dbf) +{ /* write next record to xBASE data file */ + int j, k, ret = 0; + char buf[255+1]; + xassert(dbf->mode == 'W'); + if (setjmp(dbf->jump)) + { ret = 1; + goto done; + } + /* record flag */ + write_byte(dbf, 0x20); + xassert(dbf->nf == mpl_tab_num_flds(dca)); + for (k = 1; k <= dbf->nf; k++) + { if (dbf->type[k] == 'C') + { /* character field */ + const char *str; + if (mpl_tab_get_type(dca, k) == 'N') + { sprintf(buf, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); + str = buf; + } + else if (mpl_tab_get_type(dca, k) == 'S') + str = mpl_tab_get_str(dca, k); + else + xassert(dca != dca); + if ((int)strlen(str) > dbf->len[k]) + { xprintf("xBASE driver: field %s: cannot convert %.15s..." + " to field format\n", mpl_tab_get_name(dca, k), str); + longjmp(dbf->jump, 0); + } + for (j = 0; j < dbf->len[k] && str[j] != '\0'; j++) + write_byte(dbf, str[j]); + for (j = j; j < dbf->len[k]; j++) + write_byte(dbf, ' '); + } + else if (dbf->type[k] == 'N') + { /* numeric field */ + double num = mpl_tab_get_num(dca, k); + if (fabs(num) > 1e20) +err: { xprintf("xBASE driver: field %s: cannot convert %g to fi" + "eld format\n", mpl_tab_get_name(dca, k), num); + longjmp(dbf->jump, 0); + } + sprintf(buf, "%*.*f", dbf->len[k], dbf->prec[k], num); + xassert(strlen(buf) < sizeof(buf)); + if ((int)strlen(buf) != dbf->len[k]) goto err; + for (j = 0; j < dbf->len[k]; j++) + write_byte(dbf, buf[j]); + } + else + xassert(dbf != dbf); + } + /* increase record count */ + dbf->count++; +done: return ret; +} + +static int dbf_close_file(TABDCA *dca, struct dbf *dbf) +{ /* close xBASE data file */ + int ret = 0; + xassert(dca == dca); + if (dbf->mode == 'W') + { if (setjmp(dbf->jump)) + { ret = 1; + goto skip; + } + /* end-of-file flag */ + write_byte(dbf, 0x1A); + /* number of records */ + dbf->offset = 4; + if (fseek(dbf->fp, dbf->offset, SEEK_SET)) + { xprintf("%s:0x%X: seek error - %s\n", dbf->fname, + dbf->offset, strerror(errno)); + longjmp(dbf->jump, 0); + } + write_byte(dbf, dbf->count); + write_byte(dbf, dbf->count >> 8); + write_byte(dbf, dbf->count >> 16); + write_byte(dbf, dbf->count >> 24); + fflush(dbf->fp); + if (ferror(dbf->fp)) + { xprintf("%s:0x%X: write error - %s\n", dbf->fname, + dbf->offset, strerror(errno)); + longjmp(dbf->jump, 0); + } +skip: ; + } + xfree(dbf->fname); + fclose(dbf->fp); + xfree(dbf); + return ret; +} + +/**********************************************************************/ + +#define TAB_CSV 1 +#define TAB_XBASE 2 +#define TAB_ODBC 3 +#define TAB_MYSQL 4 + +void mpl_tab_drv_open(MPL *mpl, int mode) +{ TABDCA *dca = mpl->dca; + xassert(dca->id == 0); + xassert(dca->link == NULL); + xassert(dca->na >= 1); + if (strcmp(dca->arg[1], "CSV") == 0) + { dca->id = TAB_CSV; + dca->link = csv_open_file(dca, mode); + } + else if (strcmp(dca->arg[1], "xBASE") == 0) + { dca->id = TAB_XBASE; + dca->link = dbf_open_file(dca, mode); + } + else if (strcmp(dca->arg[1], "ODBC") == 0 || + strcmp(dca->arg[1], "iODBC") == 0) + { dca->id = TAB_ODBC; + dca->link = db_iodbc_open(dca, mode); + } + else if (strcmp(dca->arg[1], "MySQL") == 0) + { dca->id = TAB_MYSQL; + dca->link = db_mysql_open(dca, mode); + } + else + xprintf("Invalid table driver `%s'\n", dca->arg[1]); + if (dca->link == NULL) + error(mpl, "error on opening table %s", + mpl->stmt->u.tab->name); + return; +} + +int mpl_tab_drv_read(MPL *mpl) +{ TABDCA *dca = mpl->dca; + int ret; + switch (dca->id) + { case TAB_CSV: + ret = csv_read_record(dca, dca->link); + break; + case TAB_XBASE: + ret = dbf_read_record(dca, dca->link); + break; + case TAB_ODBC: + ret = db_iodbc_read(dca, dca->link); + break; + case TAB_MYSQL: + ret = db_mysql_read(dca, dca->link); + break; + default: + xassert(dca != dca); + } + if (ret > 0) + error(mpl, "error on reading data from table %s", + mpl->stmt->u.tab->name); + return ret; +} + +void mpl_tab_drv_write(MPL *mpl) +{ TABDCA *dca = mpl->dca; + int ret; + switch (dca->id) + { case TAB_CSV: + ret = csv_write_record(dca, dca->link); + break; + case TAB_XBASE: + ret = dbf_write_record(dca, dca->link); + break; + case TAB_ODBC: + ret = db_iodbc_write(dca, dca->link); + break; + case TAB_MYSQL: + ret = db_mysql_write(dca, dca->link); + break; + default: + xassert(dca != dca); + } + if (ret) + error(mpl, "error on writing data to table %s", + mpl->stmt->u.tab->name); + return; +} + +void mpl_tab_drv_close(MPL *mpl) +{ TABDCA *dca = mpl->dca; + int ret; + switch (dca->id) + { case TAB_CSV: + ret = csv_close_file(dca, dca->link); + break; + case TAB_XBASE: + ret = dbf_close_file(dca, dca->link); + break; + case TAB_ODBC: + ret = db_iodbc_close(dca, dca->link); + break; + case TAB_MYSQL: + ret = db_mysql_close(dca, dca->link); + break; + default: + xassert(dca != dca); + } + dca->id = 0; + dca->link = NULL; + if (ret) + error(mpl, "error on closing table %s", + mpl->stmt->u.tab->name); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpmps.c b/resources/3rdparty/glpk-4.53/src/glpmps.c new file mode 100644 index 000000000..7b45ff77f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpmps.c @@ -0,0 +1,1433 @@ +/* glpmps.c (MPS format routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "misc.h" +#include "prob.h" + +#define xfprintf glp_format + +/*********************************************************************** +* NAME +* +* glp_init_mpscp - initialize MPS format control parameters +* +* SYNOPSIS +* +* void glp_init_mpscp(glp_mpscp *parm); +* +* DESCRIPTION +* +* The routine glp_init_mpscp initializes control parameters, which are +* used by the MPS input/output routines glp_read_mps and glp_write_mps, +* with default values. +* +* Default values of the control parameters are stored in the glp_mpscp +* structure, which the parameter parm points to. */ + +void glp_init_mpscp(glp_mpscp *parm) +{ parm->blank = '\0'; + parm->obj_name = NULL; + parm->tol_mps = 1e-12; + return; +} + +static void check_parm(const char *func, const glp_mpscp *parm) +{ /* check control parameters */ + if (!(0x00 <= parm->blank && parm->blank <= 0xFF) || + !(parm->blank == '\0' || isprint(parm->blank))) + xerror("%s: blank = 0x%02X; invalid parameter\n", + func, parm->blank); + if (!(parm->obj_name == NULL || strlen(parm->obj_name) <= 255)) + xerror("%s: obj_name = \"%.12s...\"; parameter too long\n", + func, parm->obj_name); + if (!(0.0 <= parm->tol_mps && parm->tol_mps < 1.0)) + xerror("%s: tol_mps = %g; invalid parameter\n", + func, parm->tol_mps); + return; +} + +/*********************************************************************** +* NAME +* +* glp_read_mps - read problem data in MPS format +* +* SYNOPSIS +* +* int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_mps reads problem data in MPS format from a +* text file. +* +* The parameter fmt specifies the version of MPS format: +* +* GLP_MPS_DECK - fixed (ancient) MPS format; +* GLP_MPS_FILE - free (modern) MPS format. +* +* The parameter parm is a pointer to the structure glp_mpscp, which +* specifies control parameters used by the routine. If parm is NULL, +* the routine uses default settings. +* +* The character string fname specifies a name of the text file to be +* read. +* +* Note that before reading data the current content of the problem +* object is completely erased with the routine glp_erase_prob. +* +* RETURNS +* +* If the operation was successful, the routine glp_read_mps returns +* zero. Otherwise, it prints an error message and returns non-zero. */ + +struct csa +{ /* common storage area */ + glp_prob *P; + /* pointer to problem object */ + int deck; + /* MPS format (0 - free, 1 - fixed) */ + const glp_mpscp *parm; + /* pointer to control parameters */ + const char *fname; + /* name of input MPS file */ + glp_file *fp; + /* stream assigned to input MPS file */ + jmp_buf jump; + /* label for go to in case of error */ + int recno; + /* current record (card) number */ + int recpos; + /* current record (card) position */ + int c; + /* current character */ + int fldno; + /* current field number */ + char field[255+1]; + /* current field content */ + int w80; + /* warning 'record must not be longer than 80 chars' issued */ + int wef; + /* warning 'extra fields detected beyond field 6' issued */ + int obj_row; + /* objective row number */ + void *work1, *work2, *work3; + /* working arrays */ +}; + +static void error(struct csa *csa, const char *fmt, ...) +{ /* print error message and terminate processing */ + va_list arg; + xprintf("%s:%d: ", csa->fname, csa->recno); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + longjmp(csa->jump, 1); + /* no return */ +} + +static void warning(struct csa *csa, const char *fmt, ...) +{ /* print warning message and continue processing */ + va_list arg; + xprintf("%s:%d: warning: ", csa->fname, csa->recno); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + return; +} + +static void read_char(struct csa *csa) +{ /* read next character */ + int c; + if (csa->c == '\n') + csa->recno++, csa->recpos = 0; + csa->recpos++; +read: c = glp_getc(csa->fp); + if (c < 0) + { if (glp_ioerr(csa->fp)) + error(csa, "read error - %s\n", get_err_msg()); + else if (csa->c == '\n') + error(csa, "unexpected end of file\n"); + else + { warning(csa, "missing final end of line\n"); + c = '\n'; + } + } + else if (c == '\n') + ; + else if (csa->c == '\r') + { c = '\r'; + goto badc; + } + else if (csa->deck && c == '\r') + { csa->c = '\r'; + goto read; + } + else if (c == ' ') + ; + else if (isspace(c)) + { if (csa->deck) +badc: error(csa, "in fixed MPS format white-space character 0x%02" + "X is not allowed\n", c); + c = ' '; + } + else if (iscntrl(c)) + error(csa, "invalid control character 0x%02X\n", c); + if (csa->deck && csa->recpos == 81 && c != '\n' && csa->w80 < 1) + { warning(csa, "in fixed MPS format record must not be longer th" + "an 80 characters\n"); + csa->w80++; + } + csa->c = c; + return; +} + +static int indicator(struct csa *csa, int name) +{ /* skip comment records and read possible indicator record */ + int ret; + /* reset current field number */ + csa->fldno = 0; +loop: /* read the very first character of the next record */ + xassert(csa->c == '\n'); + read_char(csa); + if (csa->c == ' ' || csa->c == '\n') + { /* data record */ + ret = 0; + } + else if (csa->c == '*') + { /* comment record */ + while (csa->c != '\n') + read_char(csa); + goto loop; + } + else + { /* indicator record */ + int len = 0; + while (csa->c != ' ' && csa->c != '\n' && len < 12) + { csa->field[len++] = (char)csa->c; + read_char(csa); + } + csa->field[len] = '\0'; + if (!(strcmp(csa->field, "NAME") == 0 || + strcmp(csa->field, "ROWS") == 0 || + strcmp(csa->field, "COLUMNS") == 0 || + strcmp(csa->field, "RHS") == 0 || + strcmp(csa->field, "RANGES") == 0 || + strcmp(csa->field, "BOUNDS") == 0 || + strcmp(csa->field, "ENDATA") == 0)) + error(csa, "invalid indicator record\n"); + if (!name) + { while (csa->c != '\n') + read_char(csa); + } + ret = 1; + } + return ret; +} + +static void read_field(struct csa *csa) +{ /* read next field of the current data record */ + csa->fldno++; + if (csa->deck) + { /* fixed MPS format */ + int beg, end, pos; + /* determine predefined field positions */ + if (csa->fldno == 1) + beg = 2, end = 3; + else if (csa->fldno == 2) + beg = 5, end = 12; + else if (csa->fldno == 3) + beg = 15, end = 22; + else if (csa->fldno == 4) + beg = 25, end = 36; + else if (csa->fldno == 5) + beg = 40, end = 47; + else if (csa->fldno == 6) + beg = 50, end = 61; + else + xassert(csa != csa); + /* skip blanks preceding the current field */ + if (csa->c != '\n') + { pos = csa->recpos; + while (csa->recpos < beg) + { if (csa->c == ' ') + ; + else if (csa->c == '\n') + break; + else + error(csa, "in fixed MPS format positions %d-%d must " + "be blank\n", pos, beg-1); + read_char(csa); + } + } + /* skip possible comment beginning in the field 3 or 5 */ + if ((csa->fldno == 3 || csa->fldno == 5) && csa->c == '$') + { while (csa->c != '\n') + read_char(csa); + } + /* read the current field */ + for (pos = beg; pos <= end; pos++) + { if (csa->c == '\n') break; + csa->field[pos-beg] = (char)csa->c; + read_char(csa); + } + csa->field[pos-beg] = '\0'; + strtrim(csa->field); + /* skip blanks following the last field */ + if (csa->fldno == 6 && csa->c != '\n') + { while (csa->recpos <= 72) + { if (csa->c == ' ') + ; + else if (csa->c == '\n') + break; + else + error(csa, "in fixed MPS format positions 62-72 must " + "be blank\n"); + read_char(csa); + } + while (csa->c != '\n') + read_char(csa); + } + } + else + { /* free MPS format */ + int len; + /* skip blanks preceding the current field */ + while (csa->c == ' ') + read_char(csa); + /* skip possible comment */ + if (csa->c == '$') + { while (csa->c != '\n') + read_char(csa); + } + /* read the current field */ + len = 0; + while (!(csa->c == ' ' || csa->c == '\n')) + { if (len == 255) + error(csa, "length of field %d exceeds 255 characters\n", + csa->fldno++); + csa->field[len++] = (char)csa->c; + read_char(csa); + } + csa->field[len] = '\0'; + /* skip anything following the last field (any extra fields + are considered to be comments) */ + if (csa->fldno == 6) + { while (csa->c == ' ') + read_char(csa); + if (csa->c != '$' && csa->c != '\n' && csa->wef < 1) + { warning(csa, "some extra field(s) detected beyond field " + "6; field(s) ignored\n"); + csa->wef++; + } + while (csa->c != '\n') + read_char(csa); + } + } + return; +} + +static void patch_name(struct csa *csa, char *name) +{ /* process embedded blanks in symbolic name */ + int blank = csa->parm->blank; + if (blank == '\0') + { /* remove emedded blanks */ + strspx(name); + } + else + { /* replace embedded blanks by specified character */ + for (; *name != '\0'; name++) + if (*name == ' ') *name = (char)blank; + } + return; +} + +static double read_number(struct csa *csa) +{ /* read next field and convert it to floating-point number */ + double x; + char *s; + /* read next field */ + read_field(csa); + xassert(csa->fldno == 4 || csa->fldno == 6); + if (csa->field[0] == '\0') + error(csa, "missing numeric value in field %d\n", csa->fldno); + /* skip initial spaces of the field */ + for (s = csa->field; *s == ' '; s++); + /* perform conversion */ + if (str2num(s, &x) != 0) + error(csa, "cannot convert `%s' to floating-point number\n", + s); + return x; +} + +static void skip_field(struct csa *csa) +{ /* read and skip next field (assumed to be blank) */ + read_field(csa); + if (csa->field[0] != '\0') + error(csa, "field %d must be blank\n", csa->fldno); + return; +} + +static void read_name(struct csa *csa) +{ /* read NAME indicator record */ + if (!(indicator(csa, 1) && strcmp(csa->field, "NAME") == 0)) + error(csa, "missing NAME indicator record\n"); + /* this indicator record looks like a data record; simulate that + fields 1 and 2 were read */ + csa->fldno = 2; + /* field 3: model name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + warning(csa, "missing model name in field 3\n"); + else + glp_set_prob_name(csa->P, csa->field); + /* skip anything following field 3 */ + while (csa->c != '\n') + read_char(csa); + return; +} + +static void read_rows(struct csa *csa) +{ /* read ROWS section */ + int i, type; +loop: if (indicator(csa, 0)) goto done; + /* field 1: row type */ + read_field(csa), strspx(csa->field); + if (strcmp(csa->field, "N") == 0) + type = GLP_FR; + else if (strcmp(csa->field, "G") == 0) + type = GLP_LO; + else if (strcmp(csa->field, "L") == 0) + type = GLP_UP; + else if (strcmp(csa->field, "E") == 0) + type = GLP_FX; + else if (csa->field[0] == '\0') + error(csa, "missing row type in field 1\n"); + else + error(csa, "invalid row type in field 1\n"); + /* field 2: row name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + error(csa, "missing row name in field 2\n"); + if (glp_find_row(csa->P, csa->field) != 0) + error(csa, "row `%s' multiply specified\n", csa->field); + i = glp_add_rows(csa->P, 1); + glp_set_row_name(csa->P, i, csa->field); + glp_set_row_bnds(csa->P, i, type, 0.0, 0.0); + /* fields 3, 4, 5, and 6 must be blank */ + skip_field(csa); + skip_field(csa); + skip_field(csa); + skip_field(csa); + goto loop; +done: return; +} + +static void read_columns(struct csa *csa) +{ /* read COLUMNS section */ + int i, j, f, len, kind = GLP_CV, *ind; + double aij, *val; + char name[255+1], *flag; + /* allocate working arrays */ + csa->work1 = ind = xcalloc(1+csa->P->m, sizeof(int)); + csa->work2 = val = xcalloc(1+csa->P->m, sizeof(double)); + csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char)); + memset(&flag[1], 0, csa->P->m); + /* no current column exists */ + j = 0, len = 0; +loop: if (indicator(csa, 0)) goto done; + /* field 1 must be blank */ + if (csa->deck) + { read_field(csa); + if (csa->field[0] != '\0') + error(csa, "field 1 must be blank\n"); + } + else + csa->fldno++; + /* field 2: column or kind name */ + read_field(csa), patch_name(csa, csa->field); + strcpy(name, csa->field); + /* field 3: row name or keyword 'MARKER' */ + read_field(csa), patch_name(csa, csa->field); + if (strcmp(csa->field, "'MARKER'") == 0) + { /* process kind data record */ + /* field 4 must be blank */ + if (csa->deck) + { read_field(csa); + if (csa->field[0] != '\0') + error(csa, "field 4 must be blank\n"); + } + else + csa->fldno++; + /* field 5: keyword 'INTORG' or 'INTEND' */ + read_field(csa), patch_name(csa, csa->field); + if (strcmp(csa->field, "'INTORG'") == 0) + kind = GLP_IV; + else if (strcmp(csa->field, "'INTEND'") == 0) + kind = GLP_CV; + else if (csa->field[0] == '\0') + error(csa, "missing keyword in field 5\n"); + else + error(csa, "invalid keyword in field 5\n"); + /* field 6 must be blank */ + skip_field(csa); + goto loop; + } + /* process column name specified in field 2 */ + if (name[0] == '\0') + { /* the same column as in previous data record */ + if (j == 0) + error(csa, "missing column name in field 2\n"); + } + else if (j != 0 && strcmp(name, csa->P->col[j]->name) == 0) + { /* the same column as in previous data record */ + xassert(j != 0); + } + else + { /* store the current column */ + if (j != 0) + { glp_set_mat_col(csa->P, j, len, ind, val); + while (len > 0) flag[ind[len--]] = 0; + } + /* create new column */ + if (glp_find_col(csa->P, name) != 0) + error(csa, "column `%s' multiply specified\n", name); + j = glp_add_cols(csa->P, 1); + glp_set_col_name(csa->P, j, name); + glp_set_col_kind(csa->P, j, kind); + if (kind == GLP_CV) + glp_set_col_bnds(csa->P, j, GLP_LO, 0.0, 0.0); + else if (kind == GLP_IV) + glp_set_col_bnds(csa->P, j, GLP_DB, 0.0, 1.0); + else + xassert(kind != kind); + } + /* process fields 3-4 and 5-6 */ + for (f = 3; f <= 5; f += 2) + { /* field 3 or 5: row name */ + if (f == 3) + { if (csa->field[0] == '\0') + error(csa, "missing row name in field 3\n"); + } + else + { read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { /* if field 5 is blank, field 6 also must be blank */ + skip_field(csa); + continue; + } + } + i = glp_find_row(csa->P, csa->field); + if (i == 0) + error(csa, "row `%s' not found\n", csa->field); + if (flag[i]) + error(csa, "duplicate coefficient in row `%s'\n", + csa->field); + /* field 4 or 6: coefficient value */ + aij = read_number(csa); + if (fabs(aij) < csa->parm->tol_mps) aij = 0.0; + len++, ind[len] = i, val[len] = aij, flag[i] = 1; + } + goto loop; +done: /* store the last column */ + if (j != 0) + glp_set_mat_col(csa->P, j, len, ind, val); + /* free working arrays */ + xfree(ind); + xfree(val); + xfree(flag); + csa->work1 = csa->work2 = csa->work3 = NULL; + return; +} + +static void read_rhs(struct csa *csa) +{ /* read RHS section */ + int i, f, v, type; + double rhs; + char name[255+1], *flag; + /* allocate working array */ + csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char)); + memset(&flag[1], 0, csa->P->m); + /* no current RHS vector exists */ + v = 0; +loop: if (indicator(csa, 0)) goto done; + /* field 1 must be blank */ + if (csa->deck) + { read_field(csa); + if (csa->field[0] != '\0') + error(csa, "field 1 must be blank\n"); + } + else + csa->fldno++; + /* field 2: RHS vector name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { /* the same RHS vector as in previous data record */ + if (v == 0) + { warning(csa, "missing RHS vector name in field 2\n"); + goto blnk; + } + } + else if (v != 0 && strcmp(csa->field, name) == 0) + { /* the same RHS vector as in previous data record */ + xassert(v != 0); + } + else +blnk: { /* new RHS vector */ + if (v != 0) + error(csa, "multiple RHS vectors not supported\n"); + v++; + strcpy(name, csa->field); + } + /* process fields 3-4 and 5-6 */ + for (f = 3; f <= 5; f += 2) + { /* field 3 or 5: row name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { if (f == 3) + error(csa, "missing row name in field 3\n"); + else + { /* if field 5 is blank, field 6 also must be blank */ + skip_field(csa); + continue; + } + } + i = glp_find_row(csa->P, csa->field); + if (i == 0) + error(csa, "row `%s' not found\n", csa->field); + if (flag[i]) + error(csa, "duplicate right-hand side for row `%s'\n", + csa->field); + /* field 4 or 6: right-hand side value */ + rhs = read_number(csa); + if (fabs(rhs) < csa->parm->tol_mps) rhs = 0.0; + type = csa->P->row[i]->type; + if (type == GLP_FR) + { if (i == csa->obj_row) + glp_set_obj_coef(csa->P, 0, rhs); + else if (rhs != 0.0) + warning(csa, "non-zero right-hand side for free row `%s'" + " ignored\n", csa->P->row[i]->name); + } + else + glp_set_row_bnds(csa->P, i, type, rhs, rhs); + flag[i] = 1; + } + goto loop; +done: /* free working array */ + xfree(flag); + csa->work3 = NULL; + return; +} + +static void read_ranges(struct csa *csa) +{ /* read RANGES section */ + int i, f, v, type; + double rhs, rng; + char name[255+1], *flag; + /* allocate working array */ + csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char)); + memset(&flag[1], 0, csa->P->m); + /* no current RANGES vector exists */ + v = 0; +loop: if (indicator(csa, 0)) goto done; + /* field 1 must be blank */ + if (csa->deck) + { read_field(csa); + if (csa->field[0] != '\0') + error(csa, "field 1 must be blank\n"); + } + else + csa->fldno++; + /* field 2: RANGES vector name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { /* the same RANGES vector as in previous data record */ + if (v == 0) + { warning(csa, "missing RANGES vector name in field 2\n"); + goto blnk; + } + } + else if (v != 0 && strcmp(csa->field, name) == 0) + { /* the same RANGES vector as in previous data record */ + xassert(v != 0); + } + else +blnk: { /* new RANGES vector */ + if (v != 0) + error(csa, "multiple RANGES vectors not supported\n"); + v++; + strcpy(name, csa->field); + } + /* process fields 3-4 and 5-6 */ + for (f = 3; f <= 5; f += 2) + { /* field 3 or 5: row name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { if (f == 3) + error(csa, "missing row name in field 3\n"); + else + { /* if field 5 is blank, field 6 also must be blank */ + skip_field(csa); + continue; + } + } + i = glp_find_row(csa->P, csa->field); + if (i == 0) + error(csa, "row `%s' not found\n", csa->field); + if (flag[i]) + error(csa, "duplicate range for row `%s'\n", csa->field); + /* field 4 or 6: range value */ + rng = read_number(csa); + if (fabs(rng) < csa->parm->tol_mps) rng = 0.0; + type = csa->P->row[i]->type; + if (type == GLP_FR) + warning(csa, "range for free row `%s' ignored\n", + csa->P->row[i]->name); + else if (type == GLP_LO) + { rhs = csa->P->row[i]->lb; + glp_set_row_bnds(csa->P, i, rhs == 0.0 ? GLP_FX : GLP_DB, + rhs, rhs + fabs(rng)); + } + else if (type == GLP_UP) + { rhs = csa->P->row[i]->ub; + glp_set_row_bnds(csa->P, i, rhs == 0.0 ? GLP_FX : GLP_DB, + rhs - fabs(rng), rhs); + } + else if (type == GLP_FX) + { rhs = csa->P->row[i]->lb; + if (rng > 0.0) + glp_set_row_bnds(csa->P, i, GLP_DB, rhs, rhs + rng); + else if (rng < 0.0) + glp_set_row_bnds(csa->P, i, GLP_DB, rhs + rng, rhs); + } + else + xassert(type != type); + flag[i] = 1; + } + goto loop; +done: /* free working array */ + xfree(flag); + csa->work3 = NULL; + return; +} + +static void read_bounds(struct csa *csa) +{ /* read BOUNDS section */ + GLPCOL *col; + int j, v, mask, data; + double bnd, lb, ub; + char type[2+1], name[255+1], *flag; + /* allocate working array */ + csa->work3 = flag = xcalloc(1+csa->P->n, sizeof(char)); + memset(&flag[1], 0, csa->P->n); + /* no current BOUNDS vector exists */ + v = 0; +loop: if (indicator(csa, 0)) goto done; + /* field 1: bound type */ + read_field(csa); + if (strcmp(csa->field, "LO") == 0) + mask = 0x01, data = 1; + else if (strcmp(csa->field, "UP") == 0) + mask = 0x10, data = 1; + else if (strcmp(csa->field, "FX") == 0) + mask = 0x11, data = 1; + else if (strcmp(csa->field, "FR") == 0) + mask = 0x11, data = 0; + else if (strcmp(csa->field, "MI") == 0) + mask = 0x01, data = 0; + else if (strcmp(csa->field, "PL") == 0) + mask = 0x10, data = 0; + else if (strcmp(csa->field, "LI") == 0) + mask = 0x01, data = 1; + else if (strcmp(csa->field, "UI") == 0) + mask = 0x10, data = 1; + else if (strcmp(csa->field, "BV") == 0) + mask = 0x11, data = 0; + else if (csa->field[0] == '\0') + error(csa, "missing bound type in field 1\n"); + else + error(csa, "invalid bound type in field 1\n"); + strcpy(type, csa->field); + /* field 2: BOUNDS vector name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { /* the same BOUNDS vector as in previous data record */ + if (v == 0) + { warning(csa, "missing BOUNDS vector name in field 2\n"); + goto blnk; + } + } + else if (v != 0 && strcmp(csa->field, name) == 0) + { /* the same BOUNDS vector as in previous data record */ + xassert(v != 0); + } + else +blnk: { /* new BOUNDS vector */ + if (v != 0) + error(csa, "multiple BOUNDS vectors not supported\n"); + v++; + strcpy(name, csa->field); + } + /* field 3: column name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + error(csa, "missing column name in field 3\n"); + j = glp_find_col(csa->P, csa->field); + if (j == 0) + error(csa, "column `%s' not found\n", csa->field); + if ((flag[j] & mask) == 0x01) + error(csa, "duplicate lower bound for column `%s'\n", + csa->field); + if ((flag[j] & mask) == 0x10) + error(csa, "duplicate upper bound for column `%s'\n", + csa->field); + xassert((flag[j] & mask) == 0x00); + /* field 4: bound value */ + if (data) + { bnd = read_number(csa); + if (fabs(bnd) < csa->parm->tol_mps) bnd = 0.0; + } + else + read_field(csa), bnd = 0.0; + /* get current column bounds */ + col = csa->P->col[j]; + if (col->type == GLP_FR) + lb = -DBL_MAX, ub = +DBL_MAX; + else if (col->type == GLP_LO) + lb = col->lb, ub = +DBL_MAX; + else if (col->type == GLP_UP) + lb = -DBL_MAX, ub = col->ub; + else if (col->type == GLP_DB) + lb = col->lb, ub = col->ub; + else if (col->type == GLP_FX) + lb = ub = col->lb; + else + xassert(col != col); + /* change column bounds */ + if (strcmp(type, "LO") == 0) + lb = bnd; + else if (strcmp(type, "UP") == 0) + ub = bnd; + else if (strcmp(type, "FX") == 0) + lb = ub = bnd; + else if (strcmp(type, "FR") == 0) + lb = -DBL_MAX, ub = +DBL_MAX; + else if (strcmp(type, "MI") == 0) + lb = -DBL_MAX; + else if (strcmp(type, "PL") == 0) + ub = +DBL_MAX; + else if (strcmp(type, "LI") == 0) + { glp_set_col_kind(csa->P, j, GLP_IV); + lb = ceil(bnd); +#if 1 /* 16/VII-2013 */ + /* if column upper bound has not been explicitly specified, + take it as +inf */ + if (!(flag[j] & 0x10)) + ub = +DBL_MAX; +#endif + } + else if (strcmp(type, "UI") == 0) + { glp_set_col_kind(csa->P, j, GLP_IV); + ub = floor(bnd); + } + else if (strcmp(type, "BV") == 0) + { glp_set_col_kind(csa->P, j, GLP_IV); + lb = 0.0, ub = 1.0; + } + else + xassert(type != type); + /* set new column bounds */ + if (lb == -DBL_MAX && ub == +DBL_MAX) + glp_set_col_bnds(csa->P, j, GLP_FR, lb, ub); + else if (ub == +DBL_MAX) + glp_set_col_bnds(csa->P, j, GLP_LO, lb, ub); + else if (lb == -DBL_MAX) + glp_set_col_bnds(csa->P, j, GLP_UP, lb, ub); + else if (lb != ub) + glp_set_col_bnds(csa->P, j, GLP_DB, lb, ub); + else + glp_set_col_bnds(csa->P, j, GLP_FX, lb, ub); + flag[j] |= (char)mask; + /* fields 5 and 6 must be blank */ + skip_field(csa); + skip_field(csa); + goto loop; +done: /* free working array */ + xfree(flag); + csa->work3 = NULL; + return; +} + +int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname) +{ /* read problem data in MPS format */ + glp_mpscp _parm; + struct csa _csa, *csa = &_csa; + int ret; + xprintf("Reading problem data from `%s'...\n", fname); + if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE)) + xerror("glp_read_mps: fmt = %d; invalid parameter\n", fmt); + if (parm == NULL) + glp_init_mpscp(&_parm), parm = &_parm; + /* check control parameters */ + check_parm("glp_read_mps", parm); + /* initialize common storage area */ + csa->P = P; + csa->deck = (fmt == GLP_MPS_DECK); + csa->parm = parm; + csa->fname = fname; + csa->fp = NULL; + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->recno = csa->recpos = 0; + csa->c = '\n'; + csa->fldno = 0; + csa->field[0] = '\0'; + csa->w80 = csa->wef = 0; + csa->obj_row = 0; + csa->work1 = csa->work2 = csa->work3 = NULL; + /* erase problem object */ + glp_erase_prob(P); + glp_create_index(P); + /* open input MPS file */ + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* read NAME indicator record */ + read_name(csa); + if (P->name != NULL) + xprintf("Problem: %s\n", P->name); + /* read ROWS section */ + if (!(indicator(csa, 0) && strcmp(csa->field, "ROWS") == 0)) + error(csa, "missing ROWS indicator record\n"); + read_rows(csa); + /* determine objective row */ + if (parm->obj_name == NULL || parm->obj_name[0] == '\0') + { /* use the first row of N type */ + int i; + for (i = 1; i <= P->m; i++) + { if (P->row[i]->type == GLP_FR) + { csa->obj_row = i; + break; + } + } + if (csa->obj_row == 0) + warning(csa, "unable to determine objective row\n"); + } + else + { /* use a row with specified name */ + int i; + for (i = 1; i <= P->m; i++) + { xassert(P->row[i]->name != NULL); + if (strcmp(parm->obj_name, P->row[i]->name) == 0) + { csa->obj_row = i; + break; + } + } + if (csa->obj_row == 0) + error(csa, "objective row `%s' not found\n", + parm->obj_name); + } + if (csa->obj_row != 0) + { glp_set_obj_name(P, P->row[csa->obj_row]->name); + xprintf("Objective: %s\n", P->obj); + } + /* read COLUMNS section */ + if (strcmp(csa->field, "COLUMNS") != 0) + error(csa, "missing COLUMNS indicator record\n"); + read_columns(csa); + /* set objective coefficients */ + if (csa->obj_row != 0) + { GLPAIJ *aij; + for (aij = P->row[csa->obj_row]->ptr; aij != NULL; aij = + aij->r_next) glp_set_obj_coef(P, aij->col->j, aij->val); + } + /* read optional RHS section */ + if (strcmp(csa->field, "RHS") == 0) + read_rhs(csa); + /* read optional RANGES section */ + if (strcmp(csa->field, "RANGES") == 0) + read_ranges(csa); + /* read optional BOUNDS section */ + if (strcmp(csa->field, "BOUNDS") == 0) + read_bounds(csa); + /* read ENDATA indicator record */ + if (strcmp(csa->field, "ENDATA") != 0) + error(csa, "invalid use of %s indicator record\n", + csa->field); +#if 1 /* 08/VIII-2013 */ + /* remove free rows */ + { int i, nrs, *num; + num = talloc(1+P->m, int); + nrs = 0; + for (i = 1; i <= P->m; i++) + { if (P->row[i]->type == GLP_FR) + num[++nrs] = i; + } + if (nrs > 0) + { glp_del_rows(P, nrs, num); + if (nrs == 1) + xprintf("One free row was removed\n"); + else + xprintf("%d free rows were removed\n", nrs); + } + tfree(num); + } +#endif + /* print some statistics */ + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", + P->nnz, P->nnz == 1 ? "" : "s"); + if (glp_get_num_int(P) > 0) + { int ni = glp_get_num_int(P); + int nb = glp_get_num_bin(P); + if (ni == 1) + { if (nb == 0) + xprintf("One variable is integer\n"); + else + xprintf("One variable is binary\n"); + } + else + { xprintf("%d integer variables, ", ni); + if (nb == 0) + xprintf("none"); + else if (nb == 1) + xprintf("one"); + else if (nb == ni) + xprintf("all"); + else + xprintf("%d", nb); + xprintf(" of which %s binary\n", nb == 1 ? "is" : "are"); + } + } + xprintf("%d records were read\n", csa->recno); + /* problem data has been successfully read */ + glp_delete_index(P); + glp_sort_matrix(P); + ret = 0; +done: if (csa->fp != NULL) glp_close(csa->fp); + if (csa->work1 != NULL) xfree(csa->work1); + if (csa->work2 != NULL) xfree(csa->work2); + if (csa->work3 != NULL) xfree(csa->work3); + if (ret != 0) glp_erase_prob(P); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_mps - write problem data in MPS format +* +* SYNOPSIS +* +* int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_mps writes problem data in MPS format to a +* text file. +* +* The parameter fmt specifies the version of MPS format: +* +* GLP_MPS_DECK - fixed (ancient) MPS format; +* GLP_MPS_FILE - free (modern) MPS format. +* +* The parameter parm is a pointer to the structure glp_mpscp, which +* specifies control parameters used by the routine. If parm is NULL, +* the routine uses default settings. +* +* The character string fname specifies a name of the text file to be +* written. +* +* RETURNS +* +* If the operation was successful, the routine glp_read_mps returns +* zero. Otherwise, it prints an error message and returns non-zero. */ + +#define csa csa1 + +struct csa +{ /* common storage area */ + glp_prob *P; + /* pointer to problem object */ + int deck; + /* MPS format (0 - free, 1 - fixed) */ + const glp_mpscp *parm; + /* pointer to control parameters */ + char field[255+1]; + /* field buffer */ +}; + +static char *mps_name(struct csa *csa) +{ /* make problem name */ + char *f; + if (csa->P->name == NULL) + csa->field[0] = '\0'; + else if (csa->deck) + { strncpy(csa->field, csa->P->name, 8); + csa->field[8] = '\0'; + } + else + strcpy(csa->field, csa->P->name); + for (f = csa->field; *f != '\0'; f++) + if (*f == ' ') *f = '_'; + return csa->field; +} + +static char *row_name(struct csa *csa, int i) +{ /* make i-th row name */ + char *f; + xassert(0 <= i && i <= csa->P->m); + if (i == 0 || csa->P->row[i]->name == NULL || + csa->deck && strlen(csa->P->row[i]->name) > 8) + sprintf(csa->field, "R%07d", i); + else + { strcpy(csa->field, csa->P->row[i]->name); + for (f = csa->field; *f != '\0'; f++) + if (*f == ' ') *f = '_'; + } + return csa->field; +} + +static char *col_name(struct csa *csa, int j) +{ /* make j-th column name */ + char *f; + xassert(1 <= j && j <= csa->P->n); + if (csa->P->col[j]->name == NULL || + csa->deck && strlen(csa->P->col[j]->name) > 8) + sprintf(csa->field, "C%07d", j); + else + { strcpy(csa->field, csa->P->col[j]->name); + for (f = csa->field; *f != '\0'; f++) + if (*f == ' ') *f = '_'; + } + return csa->field; +} + +static char *mps_numb(struct csa *csa, double val) +{ /* format floating-point number */ + int dig; + char *exp; + for (dig = 12; dig >= 6; dig--) + { if (val != 0.0 && fabs(val) < 0.002) + sprintf(csa->field, "%.*E", dig-1, val); + else + sprintf(csa->field, "%.*G", dig, val); + exp = strchr(csa->field, 'E'); + if (exp != NULL) + sprintf(exp+1, "%d", atoi(exp+1)); + if (strlen(csa->field) <= 12) break; + } + xassert(strlen(csa->field) <= 12); + return csa->field; +} + +int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname) +{ /* write problem data in MPS format */ + glp_mpscp _parm; + struct csa _csa, *csa = &_csa; + glp_file *fp; + int out_obj, one_col = 0, empty = 0; + int i, j, recno, marker, count, gap, ret; + xprintf("Writing problem data to `%s'...\n", fname); + if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE)) + xerror("glp_write_mps: fmt = %d; invalid parameter\n", fmt); + if (parm == NULL) + glp_init_mpscp(&_parm), parm = &_parm; + /* check control parameters */ + check_parm("glp_write_mps", parm); + /* initialize common storage area */ + csa->P = P; + csa->deck = (fmt == GLP_MPS_DECK); + csa->parm = parm; + /* create output MPS file */ + fp = glp_open(fname, "w"), recno = 0; + if (fp == NULL) + { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* write comment records */ + xfprintf(fp, "* %-*s%s\n", P->name == NULL ? 1 : 12, "Problem:", + P->name == NULL ? "" : P->name), recno++; + xfprintf(fp, "* %-12s%s\n", "Class:", glp_get_num_int(P) == 0 ? + "LP" : "MIP"), recno++; + xfprintf(fp, "* %-12s%d\n", "Rows:", P->m), recno++; + if (glp_get_num_int(P) == 0) + xfprintf(fp, "* %-12s%d\n", "Columns:", P->n), recno++; + else + xfprintf(fp, "* %-12s%d (%d integer, %d binary)\n", + "Columns:", P->n, glp_get_num_int(P), glp_get_num_bin(P)), + recno++; + xfprintf(fp, "* %-12s%d\n", "Non-zeros:", P->nnz), recno++; + xfprintf(fp, "* %-12s%s\n", "Format:", csa->deck ? "Fixed MPS" : + "Free MPS"), recno++; + xfprintf(fp, "*\n", recno++); + /* write NAME indicator record */ + xfprintf(fp, "NAME%*s%s\n", + P->name == NULL ? 0 : csa->deck ? 10 : 1, "", mps_name(csa)), + recno++; +#if 1 + /* determine whether to write the objective row */ + out_obj = 1; + for (i = 1; i <= P->m; i++) + { if (P->row[i]->type == GLP_FR) + { out_obj = 0; + break; + } + } +#endif + /* write ROWS section */ + xfprintf(fp, "ROWS\n"), recno++; + for (i = (out_obj ? 0 : 1); i <= P->m; i++) + { int type; + type = (i == 0 ? GLP_FR : P->row[i]->type); + if (type == GLP_FR) + type = 'N'; + else if (type == GLP_LO) + type = 'G'; + else if (type == GLP_UP) + type = 'L'; + else if (type == GLP_DB || type == GLP_FX) + type = 'E'; + else + xassert(type != type); + xfprintf(fp, " %c%*s%s\n", type, csa->deck ? 2 : 1, "", + row_name(csa, i)), recno++; + } + /* write COLUMNS section */ + xfprintf(fp, "COLUMNS\n"), recno++; + marker = 0; + for (j = 1; j <= P->n; j++) + { GLPAIJ cj, *aij; + int kind; + kind = P->col[j]->kind; + if (kind == GLP_CV) + { if (marker % 2 == 1) + { /* close current integer block */ + marker++; + xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTEND'\n", + csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "", + csa->deck ? 17 : 1, ""), recno++; + } + } + else if (kind == GLP_IV) + { if (marker % 2 == 0) + { /* open new integer block */ + marker++; + xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTORG'\n", + csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "", + csa->deck ? 17 : 1, ""), recno++; + } + } + else + xassert(kind != kind); + if (out_obj && P->col[j]->coef != 0.0) + { /* make fake objective coefficient */ + aij = &cj; + aij->row = NULL; + aij->val = P->col[j]->coef; + aij->c_next = P->col[j]->ptr; + } + else + aij = P->col[j]->ptr; +#if 1 /* FIXME */ + if (aij == NULL) + { /* empty column */ + empty++; + xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", + csa->deck ? 8 : 1, col_name(csa, j)); + /* we need a row */ + xassert(P->m > 0); + xfprintf(fp, "%*s%-*s", + csa->deck ? 2 : 1, "", csa->deck ? 8 : 1, + row_name(csa, 1)); + xfprintf(fp, "%*s0%*s$ empty column\n", + csa->deck ? 13 : 1, "", csa->deck ? 3 : 1, ""), recno++; + } +#endif + count = 0; + for (aij = aij; aij != NULL; aij = aij->c_next) + { if (one_col || count % 2 == 0) + xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", + csa->deck ? 8 : 1, col_name(csa, j)); + gap = (one_col || count % 2 == 0 ? 2 : 3); + xfprintf(fp, "%*s%-*s", + csa->deck ? gap : 1, "", csa->deck ? 8 : 1, + row_name(csa, aij->row == NULL ? 0 : aij->row->i)); + xfprintf(fp, "%*s%*s", + csa->deck ? 2 : 1, "", csa->deck ? 12 : 1, + mps_numb(csa, aij->val)), count++; + if (one_col || count % 2 == 0) + xfprintf(fp, "\n"), recno++; + } + if (!(one_col || count % 2 == 0)) + xfprintf(fp, "\n"), recno++; + } + if (marker % 2 == 1) + { /* close last integer block */ + marker++; + xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTEND'\n", + csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "", + csa->deck ? 17 : 1, ""), recno++; + } +#if 1 + if (empty > 0) + xprintf("Warning: problem has %d empty column(s)\n", empty); +#endif + /* write RHS section */ + xfprintf(fp, "RHS\n"), recno++; + count = 0; + for (i = (out_obj ? 0 : 1); i <= P->m; i++) + { int type; + double rhs; + if (i == 0) + rhs = P->c0; + else + { type = P->row[i]->type; + if (type == GLP_FR) + rhs = 0.0; + else if (type == GLP_LO) + rhs = P->row[i]->lb; + else if (type == GLP_UP) + rhs = P->row[i]->ub; + else if (type == GLP_DB || type == GLP_FX) + rhs = P->row[i]->lb; + else + xassert(type != type); + } + if (rhs != 0.0) + { if (one_col || count % 2 == 0) + xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", + csa->deck ? 8 : 1, "RHS1"); + gap = (one_col || count % 2 == 0 ? 2 : 3); + xfprintf(fp, "%*s%-*s", + csa->deck ? gap : 1, "", csa->deck ? 8 : 1, + row_name(csa, i)); + xfprintf(fp, "%*s%*s", + csa->deck ? 2 : 1, "", csa->deck ? 12 : 1, + mps_numb(csa, rhs)), count++; + if (one_col || count % 2 == 0) + xfprintf(fp, "\n"), recno++; + } + } + if (!(one_col || count % 2 == 0)) + xfprintf(fp, "\n"), recno++; + /* write RANGES section */ + for (i = P->m; i >= 1; i--) + if (P->row[i]->type == GLP_DB) break; + if (i == 0) goto bnds; + xfprintf(fp, "RANGES\n"), recno++; + count = 0; + for (i = 1; i <= P->m; i++) + { if (P->row[i]->type == GLP_DB) + { if (one_col || count % 2 == 0) + xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", + csa->deck ? 8 : 1, "RNG1"); + gap = (one_col || count % 2 == 0 ? 2 : 3); + xfprintf(fp, "%*s%-*s", + csa->deck ? gap : 1, "", csa->deck ? 8 : 1, + row_name(csa, i)); + xfprintf(fp, "%*s%*s", + csa->deck ? 2 : 1, "", csa->deck ? 12 : 1, + mps_numb(csa, P->row[i]->ub - P->row[i]->lb)), count++; + if (one_col || count % 2 == 0) + xfprintf(fp, "\n"), recno++; + } + } + if (!(one_col || count % 2 == 0)) + xfprintf(fp, "\n"), recno++; +bnds: /* write BOUNDS section */ + for (j = P->n; j >= 1; j--) + if (!(P->col[j]->kind == GLP_CV && + P->col[j]->type == GLP_LO && P->col[j]->lb == 0.0)) + break; + if (j == 0) goto endt; + xfprintf(fp, "BOUNDS\n"), recno++; + for (j = 1; j <= P->n; j++) + { int type, data[2]; + double bnd[2]; + char *spec[2]; + spec[0] = spec[1] = NULL; + type = P->col[j]->type; + if (type == GLP_FR) + spec[0] = "FR", data[0] = 0; + else if (type == GLP_LO) + { if (P->col[j]->lb != 0.0) + spec[0] = "LO", data[0] = 1, bnd[0] = P->col[j]->lb; + if (P->col[j]->kind == GLP_IV) + spec[1] = "PL", data[1] = 0; + } + else if (type == GLP_UP) + { spec[0] = "MI", data[0] = 0; + spec[1] = "UP", data[1] = 1, bnd[1] = P->col[j]->ub; + } + else if (type == GLP_DB) + { if (P->col[j]->lb != 0.0) + spec[0] = "LO", data[0] = 1, bnd[0] = P->col[j]->lb; + spec[1] = "UP", data[1] = 1, bnd[1] = P->col[j]->ub; + } + else if (type == GLP_FX) + spec[0] = "FX", data[0] = 1, bnd[0] = P->col[j]->lb; + else + xassert(type != type); + for (i = 0; i <= 1; i++) + { if (spec[i] != NULL) + { xfprintf(fp, " %s %-*s%*s%-*s", spec[i], + csa->deck ? 8 : 1, "BND1", csa->deck ? 2 : 1, "", + csa->deck ? 8 : 1, col_name(csa, j)); + if (data[i]) + xfprintf(fp, "%*s%*s", csa->deck ? 2 : 1, "", + csa->deck ? 12 : 1, mps_numb(csa, bnd[i])); + xfprintf(fp, "\n"), recno++; + } + } + } +endt: /* write ENDATA indicator record */ + xfprintf(fp, "ENDATA\n"), recno++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* problem data has been successfully written */ + xprintf("%d records were written\n", recno); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpnet03.c b/resources/3rdparty/glpk-4.53/src/glpnet03.c new file mode 100644 index 000000000..9ddf1cb75 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpnet03.c @@ -0,0 +1,1020 @@ +/* glpnet03.c (Klingman's network problem generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is the result of translation of the Fortran program NETGEN +* developed by Dr. Darwin Klingman, which is publically available from +* NETLIB at <http://www.netlib.org/lp/generators>. +* +* The translation was made by Andrew Makhorin <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_netgen - Klingman's network problem generator +* +* SYNOPSIS +* +* int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, +* const int parm[1+15]); +* +* DESCRIPTION +* +* The routine glp_netgen is a network problem generator developed by +* Dr. Darwin Klingman. It can create capacitated and uncapacitated +* minimum cost flow (or transshipment), transportation, and assignment +* problems. +* +* The parameter G specifies the graph object, to which the generated +* problem data have to be stored. Note that on entry the graph object +* is erased with the routine glp_erase_graph. +* +* The parameter v_rhs specifies an offset of the field of type double +* in the vertex data block, to which the routine stores the supply or +* demand value. If v_rhs < 0, the value is not stored. +* +* The parameter a_cap specifies an offset of the field of type double +* in the arc data block, to which the routine stores the arc capacity. +* If a_cap < 0, the capacity is not stored. +* +* The parameter a_cost specifies an offset of the field of type double +* in the arc data block, to which the routine stores the per-unit cost +* if the arc flow. If a_cost < 0, the cost is not stored. +* +* The array parm contains description of the network to be generated: +* +* parm[0] not used +* parm[1] (iseed) 8-digit positive random number seed +* parm[2] (nprob) 8-digit problem id number +* parm[3] (nodes) total number of nodes +* parm[4] (nsorc) total number of source nodes (including +* transshipment nodes) +* parm[5] (nsink) total number of sink nodes (including +* transshipment nodes) +* parm[6] (iarcs) number of arcs +* parm[7] (mincst) minimum cost for arcs +* parm[8] (maxcst) maximum cost for arcs +* parm[9] (itsup) total supply +* parm[10] (ntsorc) number of transshipment source nodes +* parm[11] (ntsink) number of transshipment sink nodes +* parm[12] (iphic) percentage of skeleton arcs to be given +* the maximum cost +* parm[13] (ipcap) percentage of arcs to be capacitated +* parm[14] (mincap) minimum upper bound for capacitated arcs +* parm[15] (maxcap) maximum upper bound for capacitated arcs +* +* The routine generates a transportation problem if: +* +* nsorc + nsink = nodes, ntsorc = 0, and ntsink = 0. +* +* The routine generates an assignment problem if the requirements for +* a transportation problem are met and: +* +* nsorc = nsink and itsup = nsorc. +* +* RETURNS +* +* If the instance was successfully generated, the routine glp_netgen +* returns zero; otherwise, if specified parameters are inconsistent, +* the routine returns a non-zero error code. +* +* REFERENCES +* +* D.Klingman, A.Napier, and J.Stutz. NETGEN: A program for generating +* large scale capacitated assignment, transportation, and minimum cost +* flow networks. Management Science 20 (1974), 814-20. */ + +struct csa +{ /* common storage area */ + glp_graph *G; + int v_rhs, a_cap, a_cost; + int nodes, iarcs, mincst, maxcst, itsup, nsorc, nsink, nonsor, + nfsink, narcs, nsort, nftsor, ipcap, mincap, maxcap, ktl, + nodlft, *ipred, *ihead, *itail, *iflag, *isup, *lsinks, mult, + modul, i15, i16, jran; +}; + +#define G (csa->G) +#define v_rhs (csa->v_rhs) +#define a_cap (csa->a_cap) +#define a_cost (csa->a_cost) +#define nodes (csa->nodes) +#define iarcs (csa->iarcs) +#define mincst (csa->mincst) +#define maxcst (csa->maxcst) +#define itsup (csa->itsup) +#define nsorc (csa->nsorc) +#define nsink (csa->nsink) +#define nonsor (csa->nonsor) +#define nfsink (csa->nfsink) +#define narcs (csa->narcs) +#define nsort (csa->nsort) +#define nftsor (csa->nftsor) +#define ipcap (csa->ipcap) +#define mincap (csa->mincap) +#define maxcap (csa->maxcap) +#define ktl (csa->ktl) +#define nodlft (csa->nodlft) +#if 0 +/* spent a day to find out this bug */ +#define ist (csa->ist) +#else +#define ist (ipred[0]) +#endif +#define ipred (csa->ipred) +#define ihead (csa->ihead) +#define itail (csa->itail) +#define iflag (csa->iflag) +#define isup (csa->isup) +#define lsinks (csa->lsinks) +#define mult (csa->mult) +#define modul (csa->modul) +#define i15 (csa->i15) +#define i16 (csa->i16) +#define jran (csa->jran) + +static void cresup(struct csa *csa); +static void chain(struct csa *csa, int lpick, int lsorc); +static void chnarc(struct csa *csa, int lsorc); +static void sort(struct csa *csa); +static void pickj(struct csa *csa, int it); +static void assign(struct csa *csa); +static void setran(struct csa *csa, int iseed); +static int iran(struct csa *csa, int ilow, int ihigh); + +int glp_netgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost, + const int parm[1+15]) +{ struct csa _csa, *csa = &_csa; + int iseed, nprob, ntsorc, ntsink, iphic, i, nskel, nltr, ltsink, + ntrans, npsink, nftr, npsorc, ntravl, ntrrem, lsorc, lpick, + nsksr, nsrchn, j, item, l, ks, k, ksp, li, n, ii, it, ih, icap, + jcap, icost, jcost, ret; + G = G_; + v_rhs = _v_rhs; + a_cap = _a_cap; + a_cost = _a_cost; + if (G != NULL) + { if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_netgen: v_rhs = %d; invalid offset\n", v_rhs); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_netgen: a_cap = %d; invalid offset\n", a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_netgen: a_cost = %d; invalid offset\n", a_cost); + } + /* Input the user's random number seed and fix it if + non-positive. */ + iseed = parm[1]; + nprob = parm[2]; + if (iseed <= 0) iseed = 13502460; + setran(csa, iseed); + /* Input the user's problem characteristics. */ + nodes = parm[3]; + nsorc = parm[4]; + nsink = parm[5]; + iarcs = parm[6]; + mincst = parm[7]; + maxcst = parm[8]; + itsup = parm[9]; + ntsorc = parm[10]; + ntsink = parm[11]; + iphic = parm[12]; + ipcap = parm[13]; + mincap = parm[14]; + maxcap = parm[15]; + /* Check the size of the problem. */ + if (!(10 <= nodes && nodes <= 100000)) + { ret = 1; + goto done; + } + /* Check user supplied parameters for consistency. */ + if (!(nsorc >= 0 && nsink >= 0 && nsorc + nsink <= nodes)) + { ret = 2; + goto done; + } + if (iarcs < 0) + { ret = 3; + goto done; + } + if (mincst > maxcst) + { ret = 4; + goto done; + } + if (itsup < 0) + { ret = 5; + goto done; + } + if (!(0 <= ntsorc && ntsorc <= nsorc)) + { ret = 6; + goto done; + } + if (!(0 <= ntsink && ntsink <= nsink)) + { ret = 7; + goto done; + } + if (!(0 <= iphic && iphic <= 100)) + { ret = 8; + goto done; + } + if (!(0 <= ipcap && ipcap <= 100)) + { ret = 9; + goto done; + } + if (mincap > maxcap) + { ret = 10; + goto done; + } + /* Initailize the graph object. */ + if (G != NULL) + { glp_erase_graph(G, G->v_size, G->a_size); + glp_add_vertices(G, nodes); + if (v_rhs >= 0) + { double zero = 0.0; + for (i = 1; i <= nodes; i++) + { glp_vertex *v = G->v[i]; + memcpy((char *)v->data + v_rhs, &zero, sizeof(double)); + } + } + } + /* Allocate working arrays. */ + ipred = xcalloc(1+nodes, sizeof(int)); + ihead = xcalloc(1+nodes, sizeof(int)); + itail = xcalloc(1+nodes, sizeof(int)); + iflag = xcalloc(1+nodes, sizeof(int)); + isup = xcalloc(1+nodes, sizeof(int)); + lsinks = xcalloc(1+nodes, sizeof(int)); + /* Print the problem documentation records. */ + if (G == NULL) + { xprintf("BEGIN\n"); + xprintf("NETGEN PROBLEM%8d%10s%10d NODES AND%10d ARCS\n", + nprob, "", nodes, iarcs); + xprintf("USER:%11d%11d%11d%11d%11d%11d\nDATA:%11d%11d%11d%11d%" + "11d%11d\n", iseed, nsorc, nsink, mincst, + maxcst, itsup, ntsorc, ntsink, iphic, ipcap, + mincap, maxcap); + } + else + glp_set_graph_name(G, "NETGEN"); + /* Set various constants used in the program. */ + narcs = 0; + nskel = 0; + nltr = nodes - nsink; + ltsink = nltr + ntsink; + ntrans = nltr - nsorc; + nfsink = nltr + 1; + nonsor = nodes - nsorc + ntsorc; + npsink = nsink - ntsink; + nodlft = nodes - nsink + ntsink; + nftr = nsorc + 1; + nftsor = nsorc - ntsorc + 1; + npsorc = nsorc - ntsorc; + /* Randomly distribute the supply among the source nodes. */ + if (npsorc + npsink == nodes && npsorc == npsink && + itsup == nsorc) + { assign(csa); + nskel = nsorc; + goto L390; + } + cresup(csa); + /* Print the supply records. */ + if (G == NULL) + { xprintf("SUPPLY\n"); + for (i = 1; i <= nsorc; i++) + xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]); + xprintf("ARCS\n"); + } + else + { if (v_rhs >= 0) + { for (i = 1; i <= nsorc; i++) + { double temp = (double)isup[i]; + glp_vertex *v = G->v[i]; + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); + } + } + } + /* Make the sources point to themselves in ipred array. */ + for (i = 1; i <= nsorc; i++) + ipred[i] = i; + if (ntrans == 0) goto L170; + /* Chain the transshipment nodes together in the ipred array. */ + ist = nftr; + ipred[nltr] = 0; + for (i = nftr; i < nltr; i++) + ipred[i] = i+1; + /* Form even length chains for 60 percent of the transshipments.*/ + ntravl = 6 * ntrans / 10; + ntrrem = ntrans - ntravl; +L140: lsorc = 1; + while (ntravl != 0) + { lpick = iran(csa, 1, ntravl + ntrrem); + ntravl--; + chain(csa, lpick, lsorc); + if (lsorc == nsorc) goto L140; + lsorc++; + } + /* Add the remaining transshipments to the chains. */ + while (ntrrem != 0) + { + lpick = iran(csa, 1, ntrrem); + ntrrem--; + lsorc = iran(csa, 1, nsorc); + chain(csa, lpick, lsorc); + } +L170: /* Set all demands equal to zero. */ + for (i = nfsink; i <= nodes; i++) + ipred[i] = 0; + /* The following loop takes one chain at a time (through the use + of logic contained in the loop and calls to other routines) and + creates the remaining network arcs. */ + for (lsorc = 1; lsorc <= nsorc; lsorc++) + { chnarc(csa, lsorc); + for (i = nfsink; i <= nodes; i++) + iflag[i] = 0; + /* Choose the number of sinks to be hooked up to the current + chain. */ + if (ntrans != 0) + nsksr = (nsort * 2 * nsink) / ntrans; + else + nsksr = nsink / nsorc + 1; + if (nsksr < 2) nsksr = 2; + if (nsksr > nsink) nsksr = nsink; + nsrchn = nsort; + /* Randomly pick nsksr sinks and put their names in lsinks. */ + ktl = nsink; + for (j = 1; j <= nsksr; j++) + { item = iran(csa, 1, ktl); + ktl--; + for (l = nfsink; l <= nodes; l++) + { if (iflag[l] != 1) + { item--; + if (item == 0) goto L230; + } + } + break; +L230: lsinks[j] = l; + iflag[l] = 1; + } + /* If last source chain, add all sinks with zero demand to + lsinks list. */ + if (lsorc == nsorc) + { for (j = nfsink; j <= nodes; j++) + { if (ipred[j] == 0 && iflag[j] != 1) + { nsksr++; + lsinks[nsksr] = j; + iflag[j] = 1; + } + } + } + /* Create demands for group of sinks in lsinks. */ + ks = isup[lsorc] / nsksr; + k = ipred[lsorc]; + for (i = 1; i <= nsksr; i++) + { nsort++; + ksp = iran(csa, 1, ks); + j = iran(csa, 1, nsksr); + itail[nsort] = k; + li = lsinks[i]; + ihead[nsort] = li; + ipred[li] += ksp; + li = lsinks[j]; + ipred[li] += ks - ksp; + n = iran(csa, 1, nsrchn); + k = lsorc; + for (ii = 1; ii <= n; ii++) + k = ipred[k]; + } + li = lsinks[1]; + ipred[li] += isup[lsorc] - ks * nsksr; + nskel += nsort; + /* Sort the arcs in the chain from source lsorc using itail as + sort key. */ + sort(csa); + /* Print this part of skeleton and create the arcs for these + nodes. */ + i = 1; + itail[nsort+1] = 0; +L300: for (j = nftsor; j <= nodes; j++) + iflag[j] = 0; + ktl = nonsor - 1; + it = itail[i]; + iflag[it] = 1; +L320: ih = ihead[i]; + iflag[ih] = 1; + narcs++; + ktl--; + /* Determine if this skeleton arc should be capacitated. */ + icap = itsup; + jcap = iran(csa, 1, 100); + if (jcap <= ipcap) + { icap = isup[lsorc]; + if (mincap > icap) icap = mincap; + } + /* Determine if this skeleton arc should have the maximum + cost. */ + icost = maxcst; + jcost = iran(csa, 1, 100); + if (jcost > iphic) + icost = iran(csa, mincst, maxcst); + if (G == NULL) + xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ih, "", icost, + icap); + else + { glp_arc *a = glp_add_arc(G, it, ih); + if (a_cap >= 0) + { double temp = (double)icap; + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); + } + if (a_cost >= 0) + { double temp = (double)icost; + memcpy((char *)a->data + a_cost, &temp, sizeof(double)); + } + } + i++; + if (itail[i] == it) goto L320; + pickj(csa, it); + if (i <= nsort) goto L300; + } + /* Create arcs from the transshipment sinks. */ + if (ntsink != 0) + { for (i = nfsink; i <= ltsink; i++) + { for (j = nftsor; j <= nodes; j++) + iflag[j] = 0; + ktl = nonsor - 1; + iflag[i] = 1; + pickj(csa, i); + } + } +L390: /* Print the demand records and end record. */ + if (G == NULL) + { xprintf("DEMAND\n"); + for (i = nfsink; i <= nodes; i++) + xprintf("%6s%6d%18s%10d\n", "", i, "", ipred[i]); + xprintf("END\n"); + } + else + { if (v_rhs >= 0) + { for (i = nfsink; i <= nodes; i++) + { double temp = - (double)ipred[i]; + glp_vertex *v = G->v[i]; + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); + } + } + } + /* Free working arrays. */ + xfree(ipred); + xfree(ihead); + xfree(itail); + xfree(iflag); + xfree(isup); + xfree(lsinks); + /* The instance has been successfully generated. */ + ret = 0; +done: return ret; +} + +/*********************************************************************** +* The routine cresup randomly distributes the total supply among the +* source nodes. */ + +static void cresup(struct csa *csa) +{ int i, j, ks, ksp; + xassert(itsup > nsorc); + ks = itsup / nsorc; + for (i = 1; i <= nsorc; i++) + isup[i] = 0; + for (i = 1; i <= nsorc; i++) + { ksp = iran(csa, 1, ks); + j = iran(csa, 1, nsorc); + isup[i] += ksp; + isup[j] += ks - ksp; + } + j = iran(csa, 1, nsorc); + isup[j] += itsup - ks * nsorc; + return; +} + +/*********************************************************************** +* The routine chain adds node lpick to the end of the chain with source +* node lsorc. */ + +static void chain(struct csa *csa, int lpick, int lsorc) +{ int i, j, k, l, m; + k = 0; + m = ist; + for (i = 1; i <= lpick; i++) + { l = k; + k = m; + m = ipred[k]; + } + ipred[l] = m; + j = ipred[lsorc]; + ipred[k] = j; + ipred[lsorc] = k; + return; +} + +/*********************************************************************** +* The routine chnarc puts the arcs in the chain from source lsorc into +* the ihead and itail arrays for sorting. */ + +static void chnarc(struct csa *csa, int lsorc) +{ int ito, ifrom; + nsort = 0; + ito = ipred[lsorc]; +L10: if (ito == lsorc) return; + nsort++; + ifrom = ipred[ito]; + ihead[nsort] = ito; + itail[nsort] = ifrom; + ito = ifrom; + goto L10; +} + +/*********************************************************************** +* The routine sort sorts the nsort arcs in the ihead and itail arrays. +* ihead is used as the sort key (i.e. forward star sort order). */ + +static void sort(struct csa *csa) +{ int i, j, k, l, m, n, it; + n = nsort; + m = n; +L10: m /= 2; + if (m == 0) return; + k = n - m; + j = 1; +L20: i = j; +L30: l = i + m; + if (itail[i] <= itail[l]) goto L40; + it = itail[i]; + itail[i] = itail[l]; + itail[l] = it; + it = ihead[i]; + ihead[i] = ihead[l]; + ihead[l] = it; + i -= m; + if (i >= 1) goto L30; +L40: j++; + if (j <= k) goto L20; + goto L10; +} + +/*********************************************************************** +* The routine pickj creates a random number of arcs out of node 'it'. +* Various parameters are dynamically adjusted in an attempt to ensure +* that the generated network has the correct number of arcs. */ + +static void pickj(struct csa *csa, int it) +{ int j, k, l, nn, nupbnd, icap, jcap, icost; + if ((nodlft - 1) * 2 > iarcs - narcs - 1) + { nodlft--; + return; + } + if ((iarcs - narcs + nonsor - ktl - 1) / nodlft - nonsor + 1 >= 0) + k = nonsor; + else + { nupbnd = (iarcs - narcs - nodlft) / nodlft * 2; +L40: k = iran(csa, 1, nupbnd); + if (nodlft == 1) k = iarcs - narcs; + if ((nodlft - 1) * (nonsor - 1) < iarcs - narcs - k) goto L40; + } + nodlft--; + for (j = 1; j <= k; j++) + { nn = iran(csa, 1, ktl); + ktl--; + for (l = nftsor; l <= nodes; l++) + { if (iflag[l] != 1) + { nn--; + if (nn == 0) goto L70; + } + } + return; +L70: iflag[l] = 1; + icap = itsup; + jcap = iran(csa, 1, 100); + if (jcap <= ipcap) + icap = iran(csa, mincap, maxcap); + icost = iran(csa, mincst, maxcst); + if (G == NULL) + xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, l, "", icost, + icap); + else + { glp_arc *a = glp_add_arc(G, it, l); + if (a_cap >= 0) + { double temp = (double)icap; + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); + } + if (a_cost >= 0) + { double temp = (double)icost; + memcpy((char *)a->data + a_cost, &temp, sizeof(double)); + } + } + narcs++; + } + return; +} + +/*********************************************************************** +* The routine assign generate assignment problems. It defines the unit +* supplies, builds a skeleton, then calls pickj to create the arcs. */ + +static void assign(struct csa *csa) +{ int i, it, nn, l, ll, icost; + if (G == NULL) + xprintf("SUPPLY\n"); + for (i = 1; i <= nsorc; i++) + { isup[i] = 1; + iflag[i] = 0; + if (G == NULL) + xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]); + else + { if (v_rhs >= 0) + { double temp = (double)isup[i]; + glp_vertex *v = G->v[i]; + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); + } + } + } + if (G == NULL) + xprintf("ARCS\n"); + for (i = nfsink; i <= nodes; i++) + ipred[i] = 1; + for (it = 1; it <= nsorc; it++) + { for (i = nfsink; i <= nodes; i++) + iflag[i] = 0; + ktl = nsink - 1; + nn = iran(csa, 1, nsink - it + 1); + for (l = 1; l <= nsorc; l++) + { if (iflag[l] != 1) + { nn--; + if (nn == 0) break; + } + } + narcs++; + ll = nsorc + l; + icost = iran(csa, mincst, maxcst); + if (G == NULL) + xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ll, "", icost, + isup[1]); + else + { glp_arc *a = glp_add_arc(G, it, ll); + if (a_cap >= 0) + { double temp = (double)isup[1]; + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); + } + if (a_cost >= 0) + { double temp = (double)icost; + memcpy((char *)a->data + a_cost, &temp, sizeof(double)); + } + } + iflag[l] = 1; + iflag[ll] = 1; + pickj(csa, it); + } + return; +} + +/*********************************************************************** +* Portable congruential (uniform) random number generator: +* +* next_value = ((7**5) * previous_value) modulo ((2**31)-1) +* +* This generator consists of three routines: +* +* (1) setran - initializes constants and seed +* (2) iran - generates an integer random number +* (3) rran - generates a real random number +* +* The generator requires a machine with at least 32 bits of precision. +* The seed (iseed) must be in the range [1,(2**31)-1]. */ + +static void setran(struct csa *csa, int iseed) +{ xassert(iseed >= 1); + mult = 16807; + modul = 2147483647; + i15 = 1 << 15; + i16 = 1 << 16; + jran = iseed; + return; +} + +/*********************************************************************** +* The routine iran generates an integer random number between ilow and +* ihigh. If ilow > ihigh then iran returns ihigh. */ + +static int iran(struct csa *csa, int ilow, int ihigh) +{ int ixhi, ixlo, ixalo, leftlo, ixahi, ifulhi, irtlo, iover, + irthi, j; + ixhi = jran / i16; + ixlo = jran - ixhi * i16; + ixalo = ixlo * mult; + leftlo = ixalo / i16; + ixahi = ixhi * mult; + ifulhi = ixahi + leftlo; + irtlo = ixalo - leftlo * i16; + iover = ifulhi / i15; + irthi = ifulhi - iover * i15; + jran = ((irtlo - modul) + irthi * i16) + iover; + if (jran < 0) jran += modul; + j = ihigh - ilow + 1; + if (j > 0) + return jran % j + ilow; + else + return ihigh; +} + +/*********************************************************************** +* NAME +* +* glp_netgen_prob - Klingman's standard network problem instance +* +* SYNOPSIS +* +* void glp_netgen_prob(int nprob, int parm[1+15]); +* +* DESCRIPTION +* +* The routine glp_netgen_prob provides the set of parameters for +* Klingman's network problem generator (see the routine glp_netgen), +* which describe a standard network problem instance. +* +* The parameter nprob (101 <= nprob <= 150) specifies the problem +* instance number. +* +* The array parm contains description of the network, provided by the +* routine. (For detailed description of these parameters see comments +* to the routine glp_netgen.) +* +* PROBLEM CHARACTERISTICS +* +* The table below shows characteristics of Klingman's standard network +* problem instances. +* +* Problem Nodes Arcs Optimum +* ------- ----- ----- ---------- +* 101 5000 25336 6191726 +* 102 5000 25387 72337144 +* 103 5000 25355 218947553 +* 104 5000 25344 -19100371 +* 105 5000 25332 31192578 +* 106 5000 12870 4314276 +* 107 5000 37832 7393769 +* 108 5000 50309 8405738 +* 109 5000 75299 9190300 +* 110 5000 12825 8975048 +* 111 5000 37828 4747532 +* 112 5000 50325 4012671 +* 113 5000 75318 2979725 +* 114 5000 26514 5821181 +* 115 5000 25962 6353310 +* 116 5000 25304 5915426 +* 117 5000 12816 4420560 +* 118 5000 37797 7045842 +* 119 5000 50301 7724179 +* 120 5000 75330 8455200 +* 121 5000 25000 66366360 +* 122 5000 25000 30997529 +* 123 5000 25000 23388777 +* 124 5000 25000 17803443 +* 125 5000 25000 14119622 +* 126 5000 12500 18802218 +* 127 5000 37500 27674647 +* 128 5000 50000 30906194 +* 129 5000 75000 40905209 +* 130 5000 12500 38939608 +* 131 5000 37500 16752978 +* 132 5000 50000 13302951 +* 133 5000 75000 9830268 +* 134 1000 25000 3804874 +* 135 2500 25000 11729616 +* 136 7500 25000 33318101 +* 137 10000 25000 46426030 +* 138 5000 25000 60710879 +* 139 5000 25000 32729682 +* 140 5000 25000 27183831 +* 141 5000 25000 19963286 +* 142 5000 25000 20243457 +* 143 5000 25000 18586777 +* 144 5000 25000 2504591 +* 145 5000 25000 215956138 +* 146 5000 25000 2253113811 +* 147 5000 25000 -427908373 +* 148 5000 25000 -92965318 +* 149 5000 25000 86051224 +* 150 5000 25000 619314919 */ + +static const int data[50][1+15] = +{ { 0, 13502460, 101, 5000, 2500, 2500, 25000, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 4281922, 102, 5000, 2500, 2500, 25000, + 1, 100, 2500000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 44820113, 103, 5000, 2500, 2500, 25000, + 1, 100, 6250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 13450451, 104, 5000, 2500, 2500, 25000, + -100, -1, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 14719436, 105, 5000, 2500, 2500, 25000, + 101, 200, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 17365786, 106, 5000, 2500, 2500, 12500, + 1, 100, 125000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 19540113, 107, 5000, 2500, 2500, 37500, + 1, 100, 375000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 19560313, 108, 5000, 2500, 2500, 50000, + 1, 100, 500000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 2403509, 109, 5000, 2500, 2500, 75000, + 1, 100, 750000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 92480414, 110, 5000, 2500, 2500, 12500, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 4230140, 111, 5000, 2500, 2500, 37500, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 10032490, 112, 5000, 2500, 2500, 50000, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 17307474, 113, 5000, 2500, 2500, 75000, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 4925114, 114, 5000, 500, 4500, 25000, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 19842704, 115, 5000, 1500, 3500, 25000, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 88392060, 116, 5000, 2500, 2500, 25000, + 1, 100, 250000, 0, 0, 0, 0, 1, 1000 + }, + { 0, 12904407, 117, 5000, 2500, 2500, 12500, + 1, 100, 125000, 0, 0, 0, 0, 1, 1000 + }, + { 0, 11811811, 118, 5000, 2500, 2500, 37500, + 1, 100, 375000, 0, 0, 0, 0, 1, 1000 + }, + { 0, 90023593, 119, 5000, 2500, 2500, 50000, + 1, 100, 500000, 0, 0, 0, 0, 1, 1000 + }, + { 0, 93028922, 120, 5000, 2500, 2500, 75000, + 1, 100, 750000, 0, 0, 0, 0, 1, 1000 + }, + { 0, 72707401, 121, 5000, 50, 50, 25000, + 1, 100, 250000, 50, 50, 0, 100, 1, 1000 + }, + { 0, 93040771, 122, 5000, 250, 250, 25000, + 1, 100, 250000, 250, 250, 0, 100, 1, 1000 + }, + { 0, 70220611, 123, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 52774811, 124, 5000, 1000, 1000, 25000, + 1, 100, 250000, 1000, 1000, 0, 100, 1, 1000 + }, + { 0, 22492311, 125, 5000, 1500, 1500, 25000, + 1, 100, 250000, 1500, 1500, 0, 100, 1, 1000 + }, + { 0, 35269337, 126, 5000, 500, 500, 12500, + 1, 100, 125000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 30140502, 127, 5000, 500, 500, 37500, + 1, 100, 375000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 49205455, 128, 5000, 500, 500, 50000, + 1, 100, 500000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 42958341, 129, 5000, 500, 500, 75000, + 1, 100, 750000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 25440925, 130, 5000, 500, 500, 12500, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 75294924, 131, 5000, 500, 500, 37500, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 4463965, 132, 5000, 500, 500, 50000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 13390427, 133, 5000, 500, 500, 75000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 95250971, 134, 1000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 54830522, 135, 2500, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 520593, 136, 7500, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 52900925, 137, 10000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 22603395, 138, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 50 + }, + { 0, 55253099, 139, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 250 + }, + { 0, 75357001, 140, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 500 + }, + { 0, 10072459, 141, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 2500 + }, + { 0, 55728492, 142, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 5000 + }, + { 0, 593043, 143, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 0, 1, 1000 + }, + { 0, 94236572, 144, 5000, 500, 500, 25000, + 1, 10, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 94882955, 145, 5000, 500, 500, 25000, + 1, 1000, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 48489922, 146, 5000, 500, 500, 25000, + 1, 10000, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 75578374, 147, 5000, 500, 500, 25000, + -100, -1, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 44821152, 148, 5000, 500, 500, 25000, + -50, 49, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 45224103, 149, 5000, 500, 500, 25000, + 101, 200, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 63491741, 150, 5000, 500, 500, 25000, + 1001, 1100, 250000, 500, 500, 0, 100, 1, 1000 + }, +}; + +void glp_netgen_prob(int nprob, int parm[1+15]) +{ int k; + if (!(101 <= nprob && nprob <= 150)) + xerror("glp_netgen_prob: nprob = %d; invalid problem instance " + "number\n", nprob); + for (k = 1; k <= 15; k++) + parm[k] = data[nprob-101][k]; + return; +} + +/**********************************************************************/ + +#if 0 +static int scan(char card[80+1], int pos, int len) +{ char buf[10+1]; + memcpy(buf, &card[pos-1], len); + buf[len] = '\0'; + return atoi(buf); +} + +int main(void) +{ int parm[1+15]; + char card[80+1]; + xassert(fgets(card, sizeof(card), stdin) == card); + parm[1] = scan(card, 1, 8); + parm[2] = scan(card, 9, 8); + xassert(fgets(card, sizeof(card), stdin) == card); + parm[3] = scan(card, 1, 5); + parm[4] = scan(card, 6, 5); + parm[5] = scan(card, 11, 5); + parm[6] = scan(card, 16, 5); + parm[7] = scan(card, 21, 5); + parm[8] = scan(card, 26, 5); + parm[9] = scan(card, 31, 10); + parm[10] = scan(card, 41, 5); + parm[11] = scan(card, 46, 5); + parm[12] = scan(card, 51, 5); + parm[13] = scan(card, 56, 5); + parm[14] = scan(card, 61, 10); + parm[15] = scan(card, 71, 10); + glp_netgen(NULL, 0, 0, 0, parm); + return 0; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpnet04.c b/resources/3rdparty/glpk-4.53/src/glpnet04.c new file mode 100644 index 000000000..391392878 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpnet04.c @@ -0,0 +1,769 @@ +/* glpnet04.c (grid-like network problem generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is a modified version of the program GRIDGEN, a grid-like +* network problem generator developed by Yusin Lee and Jim Orlin. +* The original code is publically available on the DIMACS ftp site at: +* <ftp://dimacs.rutgers.edu/pub/netflow/generators/network/gridgen>. +* +* All changes concern only the program interface, so this modified +* version produces exactly the same instances as the original version. +* +* Changes were made by Andrew Makhorin <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_gridgen - grid-like network problem generator +* +* SYNOPSIS +* +* int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, +* const int parm[1+14]); +* +* DESCRIPTION +* +* The routine glp_gridgen is a grid-like network problem generator +* developed by Yusin Lee and Jim Orlin. +* +* The parameter G specifies the graph object, to which the generated +* problem data have to be stored. Note that on entry the graph object +* is erased with the routine glp_erase_graph. +* +* The parameter v_rhs specifies an offset of the field of type double +* in the vertex data block, to which the routine stores the supply or +* demand value. If v_rhs < 0, the value is not stored. +* +* The parameter a_cap specifies an offset of the field of type double +* in the arc data block, to which the routine stores the arc capacity. +* If a_cap < 0, the capacity is not stored. +* +* The parameter a_cost specifies an offset of the field of type double +* in the arc data block, to which the routine stores the per-unit cost +* if the arc flow. If a_cost < 0, the cost is not stored. +* +* The array parm contains description of the network to be generated: +* +* parm[0] not used +* parm[1] two-ways arcs indicator: +* 1 - if links in both direction should be generated +* 0 - otherwise +* parm[2] random number seed (a positive integer) +* parm[3] number of nodes (the number of nodes generated might be +* slightly different to make the network a grid) +* parm[4] grid width +* parm[5] number of sources +* parm[6] number of sinks +* parm[7] average degree +* parm[8] total flow +* parm[9] distribution of arc costs: +* 1 - uniform +* 2 - exponential +* parm[10] lower bound for arc cost (uniform) +* 100 * lambda (exponential) +* parm[11] upper bound for arc cost (uniform) +* not used (exponential) +* parm[12] distribution of arc capacities: +* 1 - uniform +* 2 - exponential +* parm[13] lower bound for arc capacity (uniform) +* 100 * lambda (exponential) +* parm[14] upper bound for arc capacity (uniform) +* not used (exponential) +* +* RETURNS +* +* If the instance was successfully generated, the routine glp_gridgen +* returns zero; otherwise, if specified parameters are inconsistent, +* the routine returns a non-zero error code. +* +* COMMENTS +* +* This network generator generates a grid-like network plus a super +* node. In additional to the arcs connecting the nodes in the grid, +* there is an arc from each supply node to the super node and from the +* super node to each demand node to guarantee feasiblity. These arcs +* have very high costs and very big capacities. +* +* The idea of this network generator is as follows: First, a grid of +* n1 * n2 is generated. For example, 5 * 3. The nodes are numbered as +* 1 to 15, and the supernode is numbered as n1*n2+1. Then arcs between +* adjacent nodes are generated. For these arcs, the user is allowed to +* specify either to generate two-way arcs or one-way arcs. If two-way +* arcs are to be generated, two arcs, one in each direction, will be +* generated between each adjacent node pairs. Otherwise, only one arc +* will be generated. If this is the case, the arcs will be generated +* in alterntive directions as shown below. +* +* 1 ---> 2 ---> 3 ---> 4 ---> 5 +* | ^ | ^ | +* | | | | | +* V | V | V +* 6 <--- 7 <--- 8 <--- 9 <--- 10 +* | ^ | ^ | +* | | | | | +* V | V | V +* 11 --->12 --->13 --->14 ---> 15 +* +* Then the arcs between the super node and the source/sink nodes are +* added as mentioned before. If the number of arcs still doesn't reach +* the requirement, additional arcs will be added by uniformly picking +* random node pairs. There is no checking to prevent multiple arcs +* between any pair of nodes. However, there will be no self-arcs (arcs +* that poins back to its tail node) in the network. +* +* The source and sink nodes are selected uniformly in the network, and +* the imbalances of each source/sink node are also assigned by uniform +* distribution. */ + +struct stat_para +{ /* structure for statistical distributions */ + int distribution; + /* the distribution: */ +#define UNIFORM 1 /* uniform distribution */ +#define EXPONENTIAL 2 /* exponential distribution */ + double parameter[5]; + /* the parameters of the distribution */ +}; + +struct arcs +{ int from; + /* the FROM node of that arc */ + int to; + /* the TO node of that arc */ + int cost; + /* original cost of that arc */ + int u; + /* capacity of the arc */ +}; + +struct imbalance +{ int node; + /* Node ID */ + int supply; + /* Supply of that node */ +}; + +struct csa +{ /* common storage area */ + glp_graph *G; + int v_rhs, a_cap, a_cost; + int seed; + /* random number seed */ + int seed_original; + /* the original seed from input */ + int two_way; + /* 0: generate arcs in both direction for the basic grid, except + for the arcs to/from the super node. 1: o/w */ + int n_node; + /* total number of nodes in the network, numbered 1 to n_node, + including the super node, which is the last one */ + int n_arc; + /* total number of arcs in the network, counting EVERY arc. */ + int n_grid_arc; + /* number of arcs in the basic grid, including the arcs to/from + the super node */ + int n_source, n_sink; + /* number of source and sink nodes */ + int avg_degree; + /* average degree, arcs to and from the super node are counted */ + int t_supply; + /* total supply in the network */ + int n1, n2; + /* the two edges of the network grid. n1 >= n2 */ + struct imbalance *source_list, *sink_list; + /* head of the array of source/sink nodes */ + struct stat_para arc_costs; + /* the distribution of arc costs */ + struct stat_para capacities; + /* distribution of the capacities of the arcs */ + struct arcs *arc_list; + /* head of the arc list array. Arcs in this array are in the + order of grid_arcs, arcs to/from super node, and other arcs */ +}; + +#define G (csa->G) +#define v_rhs (csa->v_rhs) +#define a_cap (csa->a_cap) +#define a_cost (csa->a_cost) +#define seed (csa->seed) +#define seed_original (csa->seed_original) +#define two_way (csa->two_way) +#define n_node (csa->n_node) +#define n_arc (csa->n_arc) +#define n_grid_arc (csa->n_grid_arc) +#define n_source (csa->n_source) +#define n_sink (csa->n_sink) +#define avg_degree (csa->avg_degree) +#define t_supply (csa->t_supply) +#define n1 (csa->n1) +#define n2 (csa->n2) +#define source_list (csa->source_list) +#define sink_list (csa->sink_list) +#define arc_costs (csa->arc_costs) +#define capacities (csa->capacities) +#define arc_list (csa->arc_list) + +static void assign_capacities(struct csa *csa); +static void assign_costs(struct csa *csa); +static void assign_imbalance(struct csa *csa); +static int exponential(struct csa *csa, double lambda[1]); +static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs + *arc_ptr); +static struct arcs *gen_basic_grid(struct csa *csa, struct arcs + *arc_ptr); +static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr); +static void generate(struct csa *csa); +static void output(struct csa *csa); +static double randy(struct csa *csa); +static void select_source_sinks(struct csa *csa); +static int uniform(struct csa *csa, double a[2]); + +int glp_gridgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost, + const int parm[1+14]) +{ struct csa _csa, *csa = &_csa; + int n, ret; + G = G_; + v_rhs = _v_rhs; + a_cap = _a_cap; + a_cost = _a_cost; + if (G != NULL) + { if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_gridgen: v_rhs = %d; invalid offset\n", v_rhs); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_gridgen: a_cap = %d; invalid offset\n", a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_gridgen: a_cost = %d; invalid offset\n", a_cost) + ; + } + /* Check the parameters for consistency. */ + if (!(parm[1] == 0 || parm[1] == 1)) + { ret = 1; + goto done; + } + if (parm[2] < 1) + { ret = 2; + goto done; + } + if (!(10 <= parm[3] && parm[3] <= 40000)) + { ret = 3; + goto done; + } + if (!(1 <= parm[4] && parm[4] <= 40000)) + { ret = 4; + goto done; + } + if (!(parm[5] >= 0 && parm[6] >= 0 && parm[5] + parm[6] <= + parm[3])) + { ret = 5; + goto done; + } + if (!(1 <= parm[7] && parm[7] <= parm[3])) + { ret = 6; + goto done; + } + if (parm[8] < 0) + { ret = 7; + goto done; + } + if (!(parm[9] == 1 || parm[9] == 2)) + { ret = 8; + goto done; + } + if (parm[9] == 1 && parm[10] > parm[11] || + parm[9] == 2 && parm[10] < 1) + { ret = 9; + goto done; + } + if (!(parm[12] == 1 || parm[12] == 2)) + { ret = 10; + goto done; + } + if (parm[12] == 1 && !(0 <= parm[13] && parm[13] <= parm[14]) || + parm[12] == 2 && parm[13] < 1) + { ret = 11; + goto done; + } + /* Initialize the graph object. */ + if (G != NULL) + { glp_erase_graph(G, G->v_size, G->a_size); + glp_set_graph_name(G, "GRIDGEN"); + } + /* Copy the generator parameters. */ + two_way = parm[1]; + seed_original = seed = parm[2]; + n_node = parm[3]; + n = parm[4]; + n_source = parm[5]; + n_sink = parm[6]; + avg_degree = parm[7]; + t_supply = parm[8]; + arc_costs.distribution = parm[9]; + if (parm[9] == 1) + { arc_costs.parameter[0] = parm[10]; + arc_costs.parameter[1] = parm[11]; + } + else + { arc_costs.parameter[0] = (double)parm[10] / 100.0; + arc_costs.parameter[1] = 0.0; + } + capacities.distribution = parm[12]; + if (parm[12] == 1) + { capacities.parameter[0] = parm[13]; + capacities.parameter[1] = parm[14]; + } + else + { capacities.parameter[0] = (double)parm[13] / 100.0; + capacities.parameter[1] = 0.0; + } + /* Calculate the edge lengths of the grid according to the + input. */ + if (n * n >= n_node) + { n1 = n; + n2 = (int)((double)n_node / (double)n + 0.5); + } + else + { n2 = n; + n1 = (int)((double)n_node / (double)n + 0.5); + } + /* Recalculate the total number of nodes and plus 1 for the super + node. */ + n_node = n1 * n2 + 1; + n_arc = n_node * avg_degree; + n_grid_arc = (two_way + 1) * ((n1 - 1) * n2 + (n2 - 1) * n1) + + n_source + n_sink; + if (n_grid_arc > n_arc) n_arc = n_grid_arc; + arc_list = xcalloc(n_arc, sizeof(struct arcs)); + source_list = xcalloc(n_source, sizeof(struct imbalance)); + sink_list = xcalloc(n_sink, sizeof(struct imbalance)); + /* Generate a random network. */ + generate(csa); + /* Output the network. */ + output(csa); + /* Free all allocated memory. */ + xfree(arc_list); + xfree(source_list); + xfree(sink_list); + /* The instance has been successfully generated. */ + ret = 0; +done: return ret; +} + +#undef random + +static void assign_capacities(struct csa *csa) +{ /* Assign a capacity to each arc. */ + struct arcs *arc_ptr = arc_list; + int (*random)(struct csa *csa, double *); + int i; + /* Determine the random number generator to use. */ + switch (arc_costs.distribution) + { case UNIFORM: + random = uniform; + break; + case EXPONENTIAL: + random = exponential; + break; + default: + xassert(csa != csa); + } + /* Assign capacities to grid arcs. */ + for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++) + arc_ptr->u = random(csa, capacities.parameter); + i = i - n_source - n_sink; + /* Assign capacities to arcs to/from supernode. */ + for (; i < n_grid_arc; i++, arc_ptr++) + arc_ptr->u = t_supply; + /* Assign capacities to all other arcs. */ + for (; i < n_arc; i++, arc_ptr++) + arc_ptr->u = random(csa, capacities.parameter); + return; +} + +static void assign_costs(struct csa *csa) +{ /* Assign a cost to each arc. */ + struct arcs *arc_ptr = arc_list; + int (*random)(struct csa *csa, double *); + int i; + /* A high cost assigned to arcs to/from the supernode. */ + int high_cost; + /* The maximum cost assigned to arcs in the base grid. */ + int max_cost = 0; + /* Determine the random number generator to use. */ + switch (arc_costs.distribution) + { case UNIFORM: + random = uniform; + break; + case EXPONENTIAL: + random = exponential; + break; + default: + xassert(csa != csa); + } + /* Assign costs to arcs in the base grid. */ + for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++) + { arc_ptr->cost = random(csa, arc_costs.parameter); + if (max_cost < arc_ptr->cost) max_cost = arc_ptr->cost; + } + i = i - n_source - n_sink; + /* Assign costs to arcs to/from the super node. */ + high_cost = max_cost * 2; + for (; i < n_grid_arc; i++, arc_ptr++) + arc_ptr->cost = high_cost; + /* Assign costs to all other arcs. */ + for (; i < n_arc; i++, arc_ptr++) + arc_ptr->cost = random(csa, arc_costs.parameter); + return; +} + +static void assign_imbalance(struct csa *csa) +{ /* Assign an imbalance to each node. */ + int total, i; + double avg; + struct imbalance *ptr; + /* assign the supply nodes */ + avg = 2.0 * t_supply / n_source; + do + { for (i = 1, total = t_supply, ptr = source_list + 1; + i < n_source; i++, ptr++) + { ptr->supply = (int)(randy(csa) * avg + 0.5); + total -= ptr->supply; + } + source_list->supply = total; + } + /* redo all if the assignment "overshooted" */ + while (total <= 0); + /* assign the demand nodes */ + avg = -2.0 * t_supply / n_sink; + do + { for (i = 1, total = t_supply, ptr = sink_list + 1; + i < n_sink; i++, ptr++) + { ptr->supply = (int)(randy(csa) * avg - 0.5); + total += ptr->supply; + } + sink_list->supply = - total; + } + while (total <= 0); + return; +} + +static int exponential(struct csa *csa, double lambda[1]) +{ /* Returns an "exponentially distributed" integer with parameter + lambda. */ + return ((int)(- lambda[0] * log((double)randy(csa)) + 0.5)); +} + +static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs + *arc_ptr) +{ /* Generate an arc from each source to the supernode and from + supernode to each sink. */ + int i; + for (i = 0; i < n_source; i++, arc_ptr++) + { arc_ptr->from = source_list[i].node; + arc_ptr->to = n_node; + } + for (i = 0; i < n_sink; i++, arc_ptr++) + { arc_ptr->to = sink_list[i].node; + arc_ptr->from = n_node; + } + return arc_ptr; +} + +static struct arcs *gen_basic_grid(struct csa *csa, struct arcs + *arc_ptr) +{ /* Generate the basic grid. */ + int direction = 1, i, j, k; + if (two_way) + { /* Generate an arc in each direction. */ + for (i = 1; i < n_node; i += n1) + { for (j = i, k = j + n1 - 1; j < k; j++) + { arc_ptr->from = j; + arc_ptr->to = j + 1; + arc_ptr++; + arc_ptr->from = j + 1; + arc_ptr->to = j; + arc_ptr++; + } + } + for (i = 1; i <= n1; i++) + { for (j = i + n1; j < n_node; j += n1) + { arc_ptr->from = j; + arc_ptr->to = j - n1; + arc_ptr++; + arc_ptr->from = j - n1; + arc_ptr->to = j; + arc_ptr++; + } + } + } + else + { /* Generate one arc in each direction. */ + for (i = 1; i < n_node; i += n1) + { if (direction == 1) + j = i; + else + j = i + 1; + for (k = j + n1 - 1; j < k; j++) + { arc_ptr->from = j; + arc_ptr->to = j + direction; + arc_ptr++; + } + direction = - direction; + } + for (i = 1; i <= n1; i++) + { j = i + n1; + if (direction == 1) + { for (; j < n_node; j += n1) + { arc_ptr->from = j - n1; + arc_ptr->to = j; + arc_ptr++; + } + } + else + { for (; j < n_node; j += n1) + { arc_ptr->from = j - n1; + arc_ptr->to = j; + arc_ptr++; + } + } + direction = - direction; + } + } + return arc_ptr; +} + +static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr) +{ /* Generate random arcs to meet the specified density. */ + int i; + double ab[2]; + ab[0] = 0.9; + ab[1] = n_node - 0.99; /* upper limit is n_node-1 because the + supernode cannot be selected */ + for (i = n_grid_arc; i < n_arc; i++, arc_ptr++) + { arc_ptr->from = uniform(csa, ab); + arc_ptr->to = uniform(csa, ab); + if (arc_ptr->from == arc_ptr->to) + { arc_ptr--; + i--; + } + } + return; +} + +static void generate(struct csa *csa) +{ /* Generate a random network. */ + struct arcs *arc_ptr = arc_list; + arc_ptr = gen_basic_grid(csa, arc_ptr); + select_source_sinks(csa); + arc_ptr = gen_additional_arcs(csa, arc_ptr); + gen_more_arcs(csa, arc_ptr); + assign_costs(csa); + assign_capacities(csa); + assign_imbalance(csa); + return; +} + +static void output(struct csa *csa) +{ /* Output the network in DIMACS format. */ + struct arcs *arc_ptr; + struct imbalance *imb_ptr; + int i; + if (G != NULL) goto skip; + /* Output "c", "p" records. */ + xprintf("c generated by GRIDGEN\n"); + xprintf("c seed %d\n", seed_original); + xprintf("c nodes %d\n", n_node); + xprintf("c grid size %d X %d\n", n1, n2); + xprintf("c sources %d sinks %d\n", n_source, n_sink); + xprintf("c avg. degree %d\n", avg_degree); + xprintf("c supply %d\n", t_supply); + switch (arc_costs.distribution) + { case UNIFORM: + xprintf("c arc costs: UNIFORM distr. min %d max %d\n", + (int)arc_costs.parameter[0], + (int)arc_costs.parameter[1]); + break; + case EXPONENTIAL: + xprintf("c arc costs: EXPONENTIAL distr. lambda %d\n", + (int)arc_costs.parameter[0]); + break; + default: + xassert(csa != csa); + } + switch (capacities.distribution) + { case UNIFORM: + xprintf("c arc caps : UNIFORM distr. min %d max %d\n", + (int)capacities.parameter[0], + (int)capacities.parameter[1]); + break; + case EXPONENTIAL: + xprintf("c arc caps : EXPONENTIAL distr. %d lambda %d\n", + (int)capacities.parameter[0]); + break; + default: + xassert(csa != csa); + } +skip: if (G == NULL) + xprintf("p min %d %d\n", n_node, n_arc); + else + { glp_add_vertices(G, n_node); + if (v_rhs >= 0) + { double zero = 0.0; + for (i = 1; i <= n_node; i++) + { glp_vertex *v = G->v[i]; + memcpy((char *)v->data + v_rhs, &zero, sizeof(double)); + } + } + } + /* Output "n node supply". */ + for (i = 0, imb_ptr = source_list; i < n_source; i++, imb_ptr++) + { if (G == NULL) + xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply); + else + { if (v_rhs >= 0) + { double temp = (double)imb_ptr->supply; + glp_vertex *v = G->v[imb_ptr->node]; + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); + } + } + } + for (i = 0, imb_ptr = sink_list; i < n_sink; i++, imb_ptr++) + { if (G == NULL) + xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply); + else + { if (v_rhs >= 0) + { double temp = (double)imb_ptr->supply; + glp_vertex *v = G->v[imb_ptr->node]; + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); + } + } + } + /* Output "a from to lowcap=0 hicap cost". */ + for (i = 0, arc_ptr = arc_list; i < n_arc; i++, arc_ptr++) + { if (G == NULL) + xprintf("a %d %d 0 %d %d\n", arc_ptr->from, arc_ptr->to, + arc_ptr->u, arc_ptr->cost); + else + { glp_arc *a = glp_add_arc(G, arc_ptr->from, arc_ptr->to); + if (a_cap >= 0) + { double temp = (double)arc_ptr->u; + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); + } + if (a_cost >= 0) + { double temp = (double)arc_ptr->cost; + memcpy((char *)a->data + a_cost, &temp, sizeof(double)); + } + } + } + return; +} + +static double randy(struct csa *csa) +{ /* Returns a random number between 0.0 and 1.0. + See Ward Cheney & David Kincaid, "Numerical Mathematics and + Computing," 2Ed, pp. 335. */ + seed = 16807 * seed % 2147483647; + if (seed < 0) seed = - seed; + return seed * 4.6566128752459e-10; +} + +static void select_source_sinks(struct csa *csa) +{ /* Randomly select the source nodes and sink nodes. */ + int i, *int_ptr; + int *temp_list; /* a temporary list of nodes */ + struct imbalance *ptr; + double ab[2]; /* parameter for random number generator */ + ab[0] = 0.9; + ab[1] = n_node - 0.99; /* upper limit is n_node-1 because the + supernode cannot be selected */ + temp_list = xcalloc(n_node, sizeof(int)); + for (i = 0, int_ptr = temp_list; i < n_node; i++, int_ptr++) + *int_ptr = 0; + /* Select the source nodes. */ + for (i = 0, ptr = source_list; i < n_source; i++, ptr++) + { ptr->node = uniform(csa, ab); + if (temp_list[ptr->node] == 1) /* check for duplicates */ + { ptr--; + i--; + } + else + temp_list[ptr->node] = 1; + } + /* Select the sink nodes. */ + for (i = 0, ptr = sink_list; i < n_sink; i++, ptr++) + { ptr->node = uniform(csa, ab); + if (temp_list[ptr->node] == 1) + { ptr--; + i--; + } + else + temp_list[ptr->node] = 1; + } + xfree(temp_list); + return; +} + +int uniform(struct csa *csa, double a[2]) +{ /* Generates an integer uniformly selected from [a[0],a[1]]. */ + return (int)((a[1] - a[0]) * randy(csa) + a[0] + 0.5); +} + +/**********************************************************************/ + +#if 0 +int main(void) +{ int parm[1+14]; + double temp; + scanf("%d", &parm[1]); + scanf("%d", &parm[2]); + scanf("%d", &parm[3]); + scanf("%d", &parm[4]); + scanf("%d", &parm[5]); + scanf("%d", &parm[6]); + scanf("%d", &parm[7]); + scanf("%d", &parm[8]); + scanf("%d", &parm[9]); + if (parm[9] == 1) + { scanf("%d", &parm[10]); + scanf("%d", &parm[11]); + } + else + { scanf("%le", &temp); + parm[10] = (int)(100.0 * temp + .5); + parm[11] = 0; + } + scanf("%d", &parm[12]); + if (parm[12] == 1) + { scanf("%d", &parm[13]); + scanf("%d", &parm[14]); + } + else + { scanf("%le", &temp); + parm[13] = (int)(100.0 * temp + .5); + parm[14] = 0; + } + glp_gridgen(NULL, 0, 0, 0, parm); + return 0; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpnet05.c b/resources/3rdparty/glpk-4.53/src/glpnet05.c new file mode 100644 index 000000000..ea7ca6300 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpnet05.c @@ -0,0 +1,368 @@ +/* glpnet05.c (Goldfarb's maximum flow problem generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is a modified version of the program RMFGEN, a maxflow +* problem generator developed by D.Goldfarb and M.Grigoriadis, and +* originally implemented by Tamas Badics <badics@rutcor.rutgers.edu>. +* The original code is publically available on the DIMACS ftp site at: +* <ftp://dimacs.rutgers.edu/pub/netflow/generators/network/genrmf>. +* +* All changes concern only the program interface, so this modified +* version produces exactly the same instances as the original version. +* +* Changes were made by Andrew Makhorin <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpk.h" +#include "rng.h" + +/*********************************************************************** +* NAME +* +* glp_rmfgen - Goldfarb's maximum flow problem generator +* +* SYNOPSIS +* +* int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap, +* const int parm[1+5]); +* +* DESCRIPTION +* +* The routine glp_rmfgen is a maximum flow problem generator developed +* by D.Goldfarb and M.Grigoriadis. +* +* The parameter G specifies the graph object, to which the generated +* problem data have to be stored. Note that on entry the graph object +* is erased with the routine glp_erase_graph. +* +* The pointer s specifies a location, to which the routine stores the +* source node number. If s is NULL, the node number is not stored. +* +* The pointer t specifies a location, to which the routine stores the +* sink node number. If t is NULL, the node number is not stored. +* +* The parameter a_cap specifies an offset of the field of type double +* in the arc data block, to which the routine stores the arc capacity. +* If a_cap < 0, the capacity is not stored. +* +* The array parm contains description of the network to be generated: +* +* parm[0] not used +* parm[1] (seed) random number seed (a positive integer) +* parm[2] (a) frame size +* parm[3] (b) depth +* parm[4] (c1) minimal arc capacity +* parm[5] (c2) maximal arc capacity +* +* RETURNS +* +* If the instance was successfully generated, the routine glp_netgen +* returns zero; otherwise, if specified parameters are inconsistent, +* the routine returns a non-zero error code. +* +* COMMENTS +* +* The generated network is as follows. It has b pieces of frames of +* size a * a. (So alltogether the number of vertices is a * a * b) +* +* In each frame all the vertices are connected with their neighbours +* (forth and back). In addition the vertices of a frame are connected +* one to one with the vertices of next frame using a random permutation +* of those vertices. +* +* The source is the lower left vertex of the first frame, the sink is +* the upper right vertex of the b'th frame. +* +* t +* +-------+ +* | .| +* | . | +* / | / | +* +-------+/ -+ b +* | | |/. +* a | -v- |/ +* | | |/ +* +-------+ 1 +* s a +* +* The capacities are randomly chosen integers from the range of [c1,c2] +* in the case of interconnecting edges, and c2 * a * a for the in-frame +* edges. +* +* REFERENCES +* +* D.Goldfarb and M.D.Grigoriadis, "A computational comparison of the +* Dinic and network simplex methods for maximum flow." Annals of Op. +* Res. 13 (1988), pp. 83-123. +* +* U.Derigs and W.Meier, "Implementing Goldberg's max-flow algorithm: +* A computational investigation." Zeitschrift fuer Operations Research +* 33 (1989), pp. 383-403. */ + +typedef struct VERTEX +{ struct EDGE **edgelist; + /* Pointer to the list of pointers to the adjacent edges. + (No matter that to or from edges) */ + struct EDGE **current; + /* Pointer to the current edge */ + int degree; + /* Number of adjacent edges (both direction) */ + int index; +} vertex; + +typedef struct EDGE +{ int from; + int to; + int cap; + /* Capacity */ +} edge; + +typedef struct NETWORK +{ struct NETWORK *next, *prev; + int vertnum; + int edgenum; + vertex *verts; + /* Vertex array[1..vertnum] */ + edge *edges; + /* Edge array[1..edgenum] */ + int source; + /* Pointer to the source */ + int sink; + /* Pointer to the sink */ +} network; + +struct csa +{ /* common storage area */ + glp_graph *G; + int *s, *t, a_cap; + RNG *rand; + network *N; + int *Parr; + int A, AA, C2AA, Ec; +}; + +#define G (csa->G) +#define s (csa->s) +#define t (csa->t) +#define a_cap (csa->a_cap) +#define N (csa->N) +#define Parr (csa->Parr) +#define A (csa->A) +#define AA (csa->AA) +#define C2AA (csa->C2AA) +#define Ec (csa->Ec) + +#undef random +#define random(A) (int)(rng_unif_01(csa->rand) * (double)(A)) +#define RANDOM(A, B) (int)(random((B) - (A) + 1) + (A)) +#define sgn(A) (((A) > 0) ? 1 : ((A) == 0) ? 0 : -1) + +static void make_edge(struct csa *csa, int from, int to, int c1, int c2) +{ Ec++; + N->edges[Ec].from = from; + N->edges[Ec].to = to; + N->edges[Ec].cap = RANDOM(c1, c2); + return; +} + +static void permute(struct csa *csa) +{ int i, j, tmp; + for (i = 1; i < AA; i++) + { j = RANDOM(i, AA); + tmp = Parr[i]; + Parr[i] = Parr[j]; + Parr[j] = tmp; + } + return; +} + +static void connect(struct csa *csa, int offset, int cv, int x1, int y1) +{ int cv1; + cv1 = offset + (x1 - 1) * A + y1; + Ec++; + N->edges[Ec].from = cv; + N->edges[Ec].to = cv1; + N->edges[Ec].cap = C2AA; + return; +} + +static network *gen_rmf(struct csa *csa, int a, int b, int c1, int c2) +{ /* generates a network with a*a*b nodes and 6a*a*b-4ab-2a*a edges + random_frame network: + Derigs & Meier, Methods & Models of OR (1989), 33:383-403 */ + int x, y, z, offset, cv; + A = a; + AA = a * a; + C2AA = c2 * AA; + Ec = 0; + N = (network *)xmalloc(sizeof(network)); + N->vertnum = AA * b; + N->edgenum = 5 * AA * b - 4 * A * b - AA; + N->edges = (edge *)xcalloc(N->edgenum + 1, sizeof(edge)); + N->source = 1; + N->sink = N->vertnum; + Parr = (int *)xcalloc(AA + 1, sizeof(int)); + for (x = 1; x <= AA; x++) + Parr[x] = x; + for (z = 1; z <= b; z++) + { offset = AA * (z - 1); + if (z != b) + permute(csa); + for (x = 1; x <= A; x++) + { for (y = 1; y <= A; y++) + { cv = offset + (x - 1) * A + y; + if (z != b) + make_edge(csa, cv, offset + AA + Parr[cv - offset], + c1, c2); /* the intermediate edges */ + if (y < A) + connect(csa, offset, cv, x, y + 1); + if (y > 1) + connect(csa, offset, cv, x, y - 1); + if (x < A) + connect(csa, offset, cv, x + 1, y); + if (x > 1) + connect(csa, offset, cv, x - 1, y); + } + } + } + xfree(Parr); + return N; +} + +static void print_max_format(struct csa *csa, network *n, char *comm[], + int dim) +{ /* prints a network heading with dim lines of comments (no \n + needs at the ends) */ + int i, vnum, e_num; + edge *e; + vnum = n->vertnum; + e_num = n->edgenum; + if (G == NULL) + { for (i = 0; i < dim; i++) + xprintf("c %s\n", comm[i]); + xprintf("p max %7d %10d\n", vnum, e_num); + xprintf("n %7d s\n", n->source); + xprintf("n %7d t\n", n->sink); + } + else + { glp_add_vertices(G, vnum); + if (s != NULL) *s = n->source; + if (t != NULL) *t = n->sink; + } + for (i = 1; i <= e_num; i++) + { e = &n->edges[i]; + if (G == NULL) + xprintf("a %7d %7d %10d\n", e->from, e->to, (int)e->cap); + else + { glp_arc *a = glp_add_arc(G, e->from, e->to); + if (a_cap >= 0) + { double temp = (double)e->cap; + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); + } + } + } + return; +} + +static void gen_free_net(network *n) +{ xfree(n->edges); + xfree(n); + return; +} + +int glp_rmfgen(glp_graph *G_, int *_s, int *_t, int _a_cap, + const int parm[1+5]) +{ struct csa _csa, *csa = &_csa; + network *n; + char comm[10][80], *com1[10]; + int seed, a, b, c1, c2, ret; + G = G_; + s = _s; + t = _t; + a_cap = _a_cap; + if (G != NULL) + { if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_rmfgen: a_cap = %d; invalid offset\n", a_cap); + } + seed = parm[1]; + a = parm[2]; + b = parm[3]; + c1 = parm[4]; + c2 = parm[5]; + if (!(seed > 0 && 1 <= a && a <= 1000 && 1 <= b && b <= 1000 && + 0 <= c1 && c1 <= c2 && c2 <= 1000)) + { ret = 1; + goto done; + } + if (G != NULL) + { glp_erase_graph(G, G->v_size, G->a_size); + glp_set_graph_name(G, "RMFGEN"); + } + csa->rand = rng_create_rand(); + rng_init_rand(csa->rand, seed); + n = gen_rmf(csa, a, b, c1, c2); + sprintf(comm[0], "This file was generated by genrmf."); + sprintf(comm[1], "The parameters are: a: %d b: %d c1: %d c2: %d", + a, b, c1, c2); + com1[0] = comm[0]; + com1[1] = comm[1]; + print_max_format(csa, n, com1, 2); + gen_free_net(n); + rng_delete_rand(csa->rand); + ret = 0; +done: return ret; +} + +/**********************************************************************/ + +#if 0 +int main(int argc, char *argv[]) +{ int seed, a, b, c1, c2, i, parm[1+5]; + seed = 123; + a = b = c1 = c2 = -1; + for (i = 1; i < argc; i++) + { if (strcmp(argv[i], "-seed") == 0) + seed = atoi(argv[++i]); + else if (strcmp(argv[i], "-a") == 0) + a = atoi(argv[++i]); + else if (strcmp(argv[i], "-b") == 0) + b = atoi(argv[++i]); + else if (strcmp(argv[i], "-c1") == 0) + c1 = atoi(argv[++i]); + else if (strcmp(argv[i], "-c2") == 0) + c2 = atoi(argv[++i]); + } + if (a < 0 || b < 0 || c1 < 0 || c2 < 0) + { xprintf("Usage:\n"); + xprintf("genrmf [-seed seed] -a frame_size -b depth\n"); + xprintf(" -c1 cap_range1 -c2 cap_range2\n"); + } + else + { parm[1] = seed; + parm[2] = a; + parm[3] = b; + parm[4] = c1; + parm[5] = c2; + glp_rmfgen(NULL, NULL, NULL, 0, parm); + } + return 0; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp.h b/resources/3rdparty/glpk-4.53/src/glpnpp.h new file mode 100644 index 000000000..6aaebe8d4 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpnpp.h @@ -0,0 +1,638 @@ +/* glpnpp.h (LP/MIP preprocessor) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPNPP_H +#define GLPNPP_H + +#include "prob.h" + +typedef struct NPP NPP; +typedef struct NPPROW NPPROW; +typedef struct NPPCOL NPPCOL; +typedef struct NPPAIJ NPPAIJ; +typedef struct NPPTSE NPPTSE; +typedef struct NPPLFE NPPLFE; + +struct NPP +{ /* LP/MIP preprocessor workspace */ + /*--------------------------------------------------------------*/ + /* original problem segment */ + int orig_dir; + /* optimization direction flag: + GLP_MIN - minimization + GLP_MAX - maximization */ + int orig_m; + /* number of rows */ + int orig_n; + /* number of columns */ + int orig_nnz; + /* number of non-zero constraint coefficients */ + /*--------------------------------------------------------------*/ + /* transformed problem segment (always minimization) */ + DMP *pool; + /* memory pool to store problem components */ + char *name; + /* problem name (1 to 255 chars); NULL means no name is assigned + to the problem */ + char *obj; + /* objective function name (1 to 255 chars); NULL means no name + is assigned to the objective function */ + double c0; + /* constant term of the objective function */ + int nrows; + /* number of rows introduced into the problem; this count + increases by one every time a new row is added and never + decreases; thus, actual number of rows may be less than nrows + due to row deletions */ + int ncols; + /* number of columns introduced into the problem; this count + increases by one every time a new column is added and never + decreases; thus, actual number of column may be less than + ncols due to column deletions */ + NPPROW *r_head; + /* pointer to the beginning of the row list */ + NPPROW *r_tail; + /* pointer to the end of the row list */ + NPPCOL *c_head; + /* pointer to the beginning of the column list */ + NPPCOL *c_tail; + /* pointer to the end of the column list */ + /*--------------------------------------------------------------*/ + /* transformation history */ + DMP *stack; + /* memory pool to store transformation entries */ + NPPTSE *top; + /* pointer to most recent transformation entry */ +#if 0 /* 16/XII-2009 */ + int count[1+25]; + /* transformation statistics */ +#endif + /*--------------------------------------------------------------*/ + /* resultant (preprocessed) problem segment */ + int m; + /* number of rows */ + int n; + /* number of columns */ + int nnz; + /* number of non-zero constraint coefficients */ + int *row_ref; /* int row_ref[1+m]; */ + /* row_ref[i], 1 <= i <= m, is the reference number assigned to + a row, which is i-th row of the resultant problem */ + int *col_ref; /* int col_ref[1+n]; */ + /* col_ref[j], 1 <= j <= n, is the reference number assigned to + a column, which is j-th column of the resultant problem */ + /*--------------------------------------------------------------*/ + /* recovered solution segment */ + int sol; + /* solution indicator: + GLP_SOL - basic solution + GLP_IPT - interior-point solution + GLP_MIP - mixed integer solution */ + int scaling; + /* scaling option: + GLP_OFF - scaling is disabled + GLP_ON - scaling is enabled */ + int p_stat; + /* status of primal basic solution: + GLP_UNDEF - primal solution is undefined + GLP_FEAS - primal solution is feasible + GLP_INFEAS - primal solution is infeasible + GLP_NOFEAS - no primal feasible solution exists */ + int d_stat; + /* status of dual basic solution: + GLP_UNDEF - dual solution is undefined + GLP_FEAS - dual solution is feasible + GLP_INFEAS - dual solution is infeasible + GLP_NOFEAS - no dual feasible solution exists */ + int t_stat; + /* status of interior-point solution: + GLP_UNDEF - interior solution is undefined + GLP_OPT - interior solution is optimal */ + int i_stat; + /* status of mixed integer solution: + GLP_UNDEF - integer solution is undefined + GLP_OPT - integer solution is optimal + GLP_FEAS - integer solution is feasible + GLP_NOFEAS - no integer solution exists */ + char *r_stat; /* char r_stat[1+nrows]; */ + /* r_stat[i], 1 <= i <= nrows, is status of i-th row: + GLP_BS - inactive constraint + GLP_NL - active constraint on lower bound + GLP_NU - active constraint on upper bound + GLP_NF - active free row + GLP_NS - active equality constraint */ + char *c_stat; /* char c_stat[1+nrows]; */ + /* c_stat[j], 1 <= j <= nrows, is status of j-th column: + GLP_BS - basic variable + GLP_NL - non-basic variable on lower bound + GLP_NU - non-basic variable on upper bound + GLP_NF - non-basic free variable + GLP_NS - non-basic fixed variable */ + double *r_pi; /* double r_pi[1+nrows]; */ + /* r_pi[i], 1 <= i <= nrows, is Lagrange multiplier (dual value) + for i-th row (constraint) */ + double *c_value; /* double c_value[1+ncols]; */ + /* c_value[j], 1 <= j <= ncols, is primal value of j-th column + (structural variable) */ +}; + +struct NPPROW +{ /* row (constraint) */ + int i; + /* reference number assigned to the row, 1 <= i <= nrows */ + char *name; + /* row name (1 to 255 chars); NULL means no name is assigned to + the row */ + double lb; + /* lower bound; -DBL_MAX means the row has no lower bound */ + double ub; + /* upper bound; +DBL_MAX means the row has no upper bound */ + NPPAIJ *ptr; + /* pointer to the linked list of constraint coefficients */ + int temp; + /* working field used by preprocessor routines */ + NPPROW *prev; + /* pointer to previous row in the row list */ + NPPROW *next; + /* pointer to next row in the row list */ +}; + +struct NPPCOL +{ /* column (variable) */ + int j; + /* reference number assigned to the column, 1 <= j <= ncols */ + char *name; + /* column name (1 to 255 chars); NULL means no name is assigned + to the column */ + char is_int; + /* 0 means continuous variable; 1 means integer variable */ + double lb; + /* lower bound; -DBL_MAX means the column has no lower bound */ + double ub; + /* upper bound; +DBL_MAX means the column has no upper bound */ + double coef; + /* objective coefficient */ + NPPAIJ *ptr; + /* pointer to the linked list of constraint coefficients */ + int temp; + /* working field used by preprocessor routines */ +#if 1 /* 28/XII-2009 */ + union + { double ll; + /* implied column lower bound */ + int pos; + /* vertex ordinal number corresponding to this binary column + in the conflict graph (0, if the vertex does not exist) */ + } ll; + union + { double uu; + /* implied column upper bound */ + int neg; + /* vertex ordinal number corresponding to complement of this + binary column in the conflict graph (0, if the vertex does + not exist) */ + } uu; +#endif + NPPCOL *prev; + /* pointer to previous column in the column list */ + NPPCOL *next; + /* pointer to next column in the column list */ +}; + +struct NPPAIJ +{ /* constraint coefficient */ + NPPROW *row; + /* pointer to corresponding row */ + NPPCOL *col; + /* pointer to corresponding column */ + double val; + /* (non-zero) coefficient value */ + NPPAIJ *r_prev; + /* pointer to previous coefficient in the same row */ + NPPAIJ *r_next; + /* pointer to next coefficient in the same row */ + NPPAIJ *c_prev; + /* pointer to previous coefficient in the same column */ + NPPAIJ *c_next; + /* pointer to next coefficient in the same column */ +}; + +struct NPPTSE +{ /* transformation stack entry */ + int (*func)(NPP *npp, void *info); + /* pointer to routine performing back transformation */ + void *info; + /* pointer to specific info (depends on the transformation) */ + NPPTSE *link; + /* pointer to another entry created *before* this entry */ +}; + +struct NPPLFE +{ /* linear form element */ + int ref; + /* row/column reference number */ + double val; + /* (non-zero) coefficient value */ + NPPLFE *next; + /* pointer to another element */ +}; + +#define npp_create_wksp _glp_npp_create_wksp +NPP *npp_create_wksp(void); +/* create LP/MIP preprocessor workspace */ + +#define npp_insert_row _glp_npp_insert_row +void npp_insert_row(NPP *npp, NPPROW *row, int where); +/* insert row to the row list */ + +#define npp_remove_row _glp_npp_remove_row +void npp_remove_row(NPP *npp, NPPROW *row); +/* remove row from the row list */ + +#define npp_activate_row _glp_npp_activate_row +void npp_activate_row(NPP *npp, NPPROW *row); +/* make row active */ + +#define npp_deactivate_row _glp_npp_deactivate_row +void npp_deactivate_row(NPP *npp, NPPROW *row); +/* make row inactive */ + +#define npp_insert_col _glp_npp_insert_col +void npp_insert_col(NPP *npp, NPPCOL *col, int where); +/* insert column to the column list */ + +#define npp_remove_col _glp_npp_remove_col +void npp_remove_col(NPP *npp, NPPCOL *col); +/* remove column from the column list */ + +#define npp_activate_col _glp_npp_activate_col +void npp_activate_col(NPP *npp, NPPCOL *col); +/* make column active */ + +#define npp_deactivate_col _glp_npp_deactivate_col +void npp_deactivate_col(NPP *npp, NPPCOL *col); +/* make column inactive */ + +#define npp_add_row _glp_npp_add_row +NPPROW *npp_add_row(NPP *npp); +/* add new row to the current problem */ + +#define npp_add_col _glp_npp_add_col +NPPCOL *npp_add_col(NPP *npp); +/* add new column to the current problem */ + +#define npp_add_aij _glp_npp_add_aij +NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val); +/* add new element to the constraint matrix */ + +#define npp_row_nnz _glp_npp_row_nnz +int npp_row_nnz(NPP *npp, NPPROW *row); +/* count number of non-zero coefficients in row */ + +#define npp_col_nnz _glp_npp_col_nnz +int npp_col_nnz(NPP *npp, NPPCOL *col); +/* count number of non-zero coefficients in column */ + +#define npp_push_tse _glp_npp_push_tse +void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info), + int size); +/* push new entry to the transformation stack */ + +#define npp_erase_row _glp_npp_erase_row +void npp_erase_row(NPP *npp, NPPROW *row); +/* erase row content to make it empty */ + +#define npp_del_row _glp_npp_del_row +void npp_del_row(NPP *npp, NPPROW *row); +/* remove row from the current problem */ + +#define npp_del_col _glp_npp_del_col +void npp_del_col(NPP *npp, NPPCOL *col); +/* remove column from the current problem */ + +#define npp_del_aij _glp_npp_del_aij +void npp_del_aij(NPP *npp, NPPAIJ *aij); +/* remove element from the constraint matrix */ + +#define npp_load_prob _glp_npp_load_prob +void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol, + int scaling); +/* load original problem into the preprocessor workspace */ + +#define npp_build_prob _glp_npp_build_prob +void npp_build_prob(NPP *npp, glp_prob *prob); +/* build resultant (preprocessed) problem */ + +#define npp_postprocess _glp_npp_postprocess +void npp_postprocess(NPP *npp, glp_prob *prob); +/* postprocess solution from the resultant problem */ + +#define npp_unload_sol _glp_npp_unload_sol +void npp_unload_sol(NPP *npp, glp_prob *orig); +/* store solution to the original problem */ + +#define npp_delete_wksp _glp_npp_delete_wksp +void npp_delete_wksp(NPP *npp); +/* delete LP/MIP preprocessor workspace */ + +#define npp_error() + +#define npp_free_row _glp_npp_free_row +void npp_free_row(NPP *npp, NPPROW *p); +/* process free (unbounded) row */ + +#define npp_geq_row _glp_npp_geq_row +void npp_geq_row(NPP *npp, NPPROW *p); +/* process row of 'not less than' type */ + +#define npp_leq_row _glp_npp_leq_row +void npp_leq_row(NPP *npp, NPPROW *p); +/* process row of 'not greater than' type */ + +#define npp_free_col _glp_npp_free_col +void npp_free_col(NPP *npp, NPPCOL *q); +/* process free (unbounded) column */ + +#define npp_lbnd_col _glp_npp_lbnd_col +void npp_lbnd_col(NPP *npp, NPPCOL *q); +/* process column with (non-zero) lower bound */ + +#define npp_ubnd_col _glp_npp_ubnd_col +void npp_ubnd_col(NPP *npp, NPPCOL *q); +/* process column with upper bound */ + +#define npp_dbnd_col _glp_npp_dbnd_col +void npp_dbnd_col(NPP *npp, NPPCOL *q); +/* process non-negative column with upper bound */ + +#define npp_fixed_col _glp_npp_fixed_col +void npp_fixed_col(NPP *npp, NPPCOL *q); +/* process fixed column */ + +#define npp_make_equality _glp_npp_make_equality +int npp_make_equality(NPP *npp, NPPROW *p); +/* process row with almost identical bounds */ + +#define npp_make_fixed _glp_npp_make_fixed +int npp_make_fixed(NPP *npp, NPPCOL *q); +/* process column with almost identical bounds */ + +#define npp_empty_row _glp_npp_empty_row +int npp_empty_row(NPP *npp, NPPROW *p); +/* process empty row */ + +#define npp_empty_col _glp_npp_empty_col +int npp_empty_col(NPP *npp, NPPCOL *q); +/* process empty column */ + +#define npp_implied_value _glp_npp_implied_value +int npp_implied_value(NPP *npp, NPPCOL *q, double s); +/* process implied column value */ + +#define npp_eq_singlet _glp_npp_eq_singlet +int npp_eq_singlet(NPP *npp, NPPROW *p); +/* process row singleton (equality constraint) */ + +#define npp_implied_lower _glp_npp_implied_lower +int npp_implied_lower(NPP *npp, NPPCOL *q, double l); +/* process implied column lower bound */ + +#define npp_implied_upper _glp_npp_implied_upper +int npp_implied_upper(NPP *npp, NPPCOL *q, double u); +/* process implied upper bound of column */ + +#define npp_ineq_singlet _glp_npp_ineq_singlet +int npp_ineq_singlet(NPP *npp, NPPROW *p); +/* process row singleton (inequality constraint) */ + +#define npp_implied_slack _glp_npp_implied_slack +void npp_implied_slack(NPP *npp, NPPCOL *q); +/* process column singleton (implied slack variable) */ + +#define npp_implied_free _glp_npp_implied_free +int npp_implied_free(NPP *npp, NPPCOL *q); +/* process column singleton (implied free variable) */ + +#define npp_eq_doublet _glp_npp_eq_doublet +NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p); +/* process row doubleton (equality constraint) */ + +#define npp_forcing_row _glp_npp_forcing_row +int npp_forcing_row(NPP *npp, NPPROW *p, int at); +/* process forcing row */ + +#define npp_analyze_row _glp_npp_analyze_row +int npp_analyze_row(NPP *npp, NPPROW *p); +/* perform general row analysis */ + +#define npp_inactive_bound _glp_npp_inactive_bound +void npp_inactive_bound(NPP *npp, NPPROW *p, int which); +/* remove row lower/upper inactive bound */ + +#define npp_implied_bounds _glp_npp_implied_bounds +void npp_implied_bounds(NPP *npp, NPPROW *p); +/* determine implied column bounds */ + +#define npp_binarize_prob _glp_npp_binarize_prob +int npp_binarize_prob(NPP *npp); +/* binarize MIP problem */ + +#define npp_is_packing _glp_npp_is_packing +int npp_is_packing(NPP *npp, NPPROW *row); +/* test if constraint is packing inequality */ + +#define npp_hidden_packing _glp_npp_hidden_packing +int npp_hidden_packing(NPP *npp, NPPROW *row); +/* identify hidden packing inequality */ + +#define npp_implied_packing _glp_npp_implied_packing +int npp_implied_packing(NPP *npp, NPPROW *row, int which, + NPPCOL *var[], char set[]); +/* identify implied packing inequality */ + +#define npp_is_covering _glp_npp_is_covering +int npp_is_covering(NPP *npp, NPPROW *row); +/* test if constraint is covering inequality */ + +#define npp_hidden_covering _glp_npp_hidden_covering +int npp_hidden_covering(NPP *npp, NPPROW *row); +/* identify hidden covering inequality */ + +#define npp_is_partitioning _glp_npp_is_partitioning +int npp_is_partitioning(NPP *npp, NPPROW *row); +/* test if constraint is partitioning equality */ + +#define npp_reduce_ineq_coef _glp_npp_reduce_ineq_coef +int npp_reduce_ineq_coef(NPP *npp, NPPROW *row); +/* reduce inequality constraint coefficients */ + +#define npp_clean_prob _glp_npp_clean_prob +void npp_clean_prob(NPP *npp); +/* perform initial LP/MIP processing */ + +#define npp_process_row _glp_npp_process_row +int npp_process_row(NPP *npp, NPPROW *row, int hard); +/* perform basic row processing */ + +#define npp_improve_bounds _glp_npp_improve_bounds +int npp_improve_bounds(NPP *npp, NPPROW *row, int flag); +/* improve current column bounds */ + +#define npp_process_col _glp_npp_process_col +int npp_process_col(NPP *npp, NPPCOL *col); +/* perform basic column processing */ + +#define npp_process_prob _glp_npp_process_prob +int npp_process_prob(NPP *npp, int hard); +/* perform basic LP/MIP processing */ + +#define npp_simplex _glp_npp_simplex +int npp_simplex(NPP *npp, const glp_smcp *parm); +/* process LP prior to applying primal/dual simplex method */ + +#define npp_integer _glp_npp_integer +int npp_integer(NPP *npp, const glp_iocp *parm); +/* process MIP prior to applying branch-and-bound method */ + +/**********************************************************************/ + +#define npp_sat_free_row _glp_npp_sat_free_row +void npp_sat_free_row(NPP *npp, NPPROW *p); +/* process free (unbounded) row */ + +#define npp_sat_fixed_col _glp_npp_sat_fixed_col +int npp_sat_fixed_col(NPP *npp, NPPCOL *q); +/* process fixed column */ + +#define npp_sat_is_bin_comb _glp_npp_sat_is_bin_comb +int npp_sat_is_bin_comb(NPP *npp, NPPROW *row); +/* test if row is binary combination */ + +#define npp_sat_num_pos_coef _glp_npp_sat_num_pos_coef +int npp_sat_num_pos_coef(NPP *npp, NPPROW *row); +/* determine number of positive coefficients */ + +#define npp_sat_num_neg_coef _glp_npp_sat_num_neg_coef +int npp_sat_num_neg_coef(NPP *npp, NPPROW *row); +/* determine number of negative coefficients */ + +#define npp_sat_is_cover_ineq _glp_npp_sat_is_cover_ineq +int npp_sat_is_cover_ineq(NPP *npp, NPPROW *row); +/* test if row is covering inequality */ + +#define npp_sat_is_pack_ineq _glp_npp_sat_is_pack_ineq +int npp_sat_is_pack_ineq(NPP *npp, NPPROW *row); +/* test if row is packing inequality */ + +#define npp_sat_is_partn_eq _glp_npp_sat_is_partn_eq +int npp_sat_is_partn_eq(NPP *npp, NPPROW *row); +/* test if row is partitioning equality */ + +#define npp_sat_reverse_row _glp_npp_sat_reverse_row +int npp_sat_reverse_row(NPP *npp, NPPROW *row); +/* multiply both sides of row by -1 */ + +#define npp_sat_split_pack _glp_npp_sat_split_pack +NPPROW *npp_sat_split_pack(NPP *npp, NPPROW *row, int nnn); +/* split packing inequality */ + +#define npp_sat_encode_pack _glp_npp_sat_encode_pack +void npp_sat_encode_pack(NPP *npp, NPPROW *row); +/* encode packing inequality */ + +typedef struct NPPLIT NPPLIT; +typedef struct NPPLSE NPPLSE; +typedef struct NPPSED NPPSED; + +struct NPPLIT +{ /* literal (binary variable or its negation) */ + NPPCOL *col; + /* pointer to binary variable; NULL means constant false */ + int neg; + /* negation flag: + 0 - literal is variable (or constant false) + 1 - literal is negation of variable (or constant true) */ +}; + +struct NPPLSE +{ /* literal set element */ + NPPLIT lit; + /* literal */ + NPPLSE *next; + /* pointer to another element */ +}; + +struct NPPSED +{ /* summation encoding descriptor */ + /* this struct describes the equality + x + y + z = s + 2 * c, + which was encoded as CNF and included into the transformed + problem; here x and y are literals, z is either a literal or + constant zero, s and c are binary variables modeling, resp., + the low and high (carry) sum bits */ + NPPLIT x, y, z; + /* literals; if z.col = NULL, z is constant zero */ + NPPCOL *s, *c; + /* binary variables modeling the sum bits */ +}; + +#define npp_sat_encode_sum2 _glp_npp_sat_encode_sum2 +void npp_sat_encode_sum2(NPP *npp, NPPLSE *set, NPPSED *sed); +/* encode 2-bit summation */ + +#define npp_sat_encode_sum3 _glp_npp_sat_encode_sum3 +void npp_sat_encode_sum3(NPP *npp, NPPLSE *set, NPPSED *sed); +/* encode 3-bit summation */ + +#define npp_sat_encode_sum_ax _glp_npp_sat_encode_sum_ax +int npp_sat_encode_sum_ax(NPP *npp, NPPROW *row, NPPLIT y[]); +/* encode linear combination of 0-1 variables */ + +#define npp_sat_normalize_clause _glp_npp_sat_normalize_clause +int npp_sat_normalize_clause(NPP *npp, int size, NPPLIT lit[]); +/* normalize clause */ + +#define npp_sat_encode_clause _glp_npp_sat_encode_clause +NPPROW *npp_sat_encode_clause(NPP *npp, int size, NPPLIT lit[]); +/* translate clause to cover inequality */ + +#define npp_sat_encode_geq _glp_npp_sat_encode_geq +int npp_sat_encode_geq(NPP *npp, int n, NPPLIT y[], int rhs); +/* encode "not less than" constraint */ + +#define npp_sat_encode_leq _glp_npp_sat_encode_leq +int npp_sat_encode_leq(NPP *npp, int n, NPPLIT y[], int rhs); +/* encode "not greater than" constraint */ + +#define npp_sat_encode_row _glp_npp_sat_encode_row +int npp_sat_encode_row(NPP *npp, NPPROW *row); +/* encode constraint (row) of general type */ + +#define npp_sat_encode_prob _glp_npp_sat_encode_prob +int npp_sat_encode_prob(NPP *npp); +/* encode 0-1 feasibility problem */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp01.c b/resources/3rdparty/glpk-4.53/src/glpnpp01.c new file mode 100644 index 000000000..9eb59f28e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpnpp01.c @@ -0,0 +1,938 @@ +/* glpnpp01.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpnpp.h" + +NPP *npp_create_wksp(void) +{ /* create LP/MIP preprocessor workspace */ + NPP *npp; + npp = xmalloc(sizeof(NPP)); + npp->orig_dir = 0; + npp->orig_m = npp->orig_n = npp->orig_nnz = 0; + npp->pool = dmp_create_pool(); + npp->name = npp->obj = NULL; + npp->c0 = 0.0; + npp->nrows = npp->ncols = 0; + npp->r_head = npp->r_tail = NULL; + npp->c_head = npp->c_tail = NULL; + npp->stack = dmp_create_pool(); + npp->top = NULL; +#if 0 /* 16/XII-2009 */ + memset(&npp->count, 0, sizeof(npp->count)); +#endif + npp->m = npp->n = npp->nnz = 0; + npp->row_ref = npp->col_ref = NULL; + npp->sol = npp->scaling = 0; + npp->p_stat = npp->d_stat = npp->t_stat = npp->i_stat = 0; + npp->r_stat = NULL; + /*npp->r_prim =*/ npp->r_pi = NULL; + npp->c_stat = NULL; + npp->c_value = /*npp->c_dual =*/ NULL; + return npp; +} + +void npp_insert_row(NPP *npp, NPPROW *row, int where) +{ /* insert row to the row list */ + if (where == 0) + { /* insert row to the beginning of the row list */ + row->prev = NULL; + row->next = npp->r_head; + if (row->next == NULL) + npp->r_tail = row; + else + row->next->prev = row; + npp->r_head = row; + } + else + { /* insert row to the end of the row list */ + row->prev = npp->r_tail; + row->next = NULL; + if (row->prev == NULL) + npp->r_head = row; + else + row->prev->next = row; + npp->r_tail = row; + } + return; +} + +void npp_remove_row(NPP *npp, NPPROW *row) +{ /* remove row from the row list */ + if (row->prev == NULL) + npp->r_head = row->next; + else + row->prev->next = row->next; + if (row->next == NULL) + npp->r_tail = row->prev; + else + row->next->prev = row->prev; + return; +} + +void npp_activate_row(NPP *npp, NPPROW *row) +{ /* make row active */ + if (!row->temp) + { row->temp = 1; + /* move the row to the beginning of the row list */ + npp_remove_row(npp, row); + npp_insert_row(npp, row, 0); + } + return; +} + +void npp_deactivate_row(NPP *npp, NPPROW *row) +{ /* make row inactive */ + if (row->temp) + { row->temp = 0; + /* move the row to the end of the row list */ + npp_remove_row(npp, row); + npp_insert_row(npp, row, 1); + } + return; +} + +void npp_insert_col(NPP *npp, NPPCOL *col, int where) +{ /* insert column to the column list */ + if (where == 0) + { /* insert column to the beginning of the column list */ + col->prev = NULL; + col->next = npp->c_head; + if (col->next == NULL) + npp->c_tail = col; + else + col->next->prev = col; + npp->c_head = col; + } + else + { /* insert column to the end of the column list */ + col->prev = npp->c_tail; + col->next = NULL; + if (col->prev == NULL) + npp->c_head = col; + else + col->prev->next = col; + npp->c_tail = col; + } + return; +} + +void npp_remove_col(NPP *npp, NPPCOL *col) +{ /* remove column from the column list */ + if (col->prev == NULL) + npp->c_head = col->next; + else + col->prev->next = col->next; + if (col->next == NULL) + npp->c_tail = col->prev; + else + col->next->prev = col->prev; + return; +} + +void npp_activate_col(NPP *npp, NPPCOL *col) +{ /* make column active */ + if (!col->temp) + { col->temp = 1; + /* move the column to the beginning of the column list */ + npp_remove_col(npp, col); + npp_insert_col(npp, col, 0); + } + return; +} + +void npp_deactivate_col(NPP *npp, NPPCOL *col) +{ /* make column inactive */ + if (col->temp) + { col->temp = 0; + /* move the column to the end of the column list */ + npp_remove_col(npp, col); + npp_insert_col(npp, col, 1); + } + return; +} + +NPPROW *npp_add_row(NPP *npp) +{ /* add new row to the current problem */ + NPPROW *row; + row = dmp_get_atom(npp->pool, sizeof(NPPROW)); + row->i = ++(npp->nrows); + row->name = NULL; + row->lb = -DBL_MAX, row->ub = +DBL_MAX; + row->ptr = NULL; + row->temp = 0; + npp_insert_row(npp, row, 1); + return row; +} + +NPPCOL *npp_add_col(NPP *npp) +{ /* add new column to the current problem */ + NPPCOL *col; + col = dmp_get_atom(npp->pool, sizeof(NPPCOL)); + col->j = ++(npp->ncols); + col->name = NULL; +#if 0 + col->kind = GLP_CV; +#else + col->is_int = 0; +#endif + col->lb = col->ub = col->coef = 0.0; + col->ptr = NULL; + col->temp = 0; + npp_insert_col(npp, col, 1); + return col; +} + +NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val) +{ /* add new element to the constraint matrix */ + NPPAIJ *aij; + aij = dmp_get_atom(npp->pool, sizeof(NPPAIJ)); + aij->row = row; + aij->col = col; + aij->val = val; + aij->r_prev = NULL; + aij->r_next = row->ptr; + aij->c_prev = NULL; + aij->c_next = col->ptr; + if (aij->r_next != NULL) + aij->r_next->r_prev = aij; + if (aij->c_next != NULL) + aij->c_next->c_prev = aij; + row->ptr = col->ptr = aij; + return aij; +} + +int npp_row_nnz(NPP *npp, NPPROW *row) +{ /* count number of non-zero coefficients in row */ + NPPAIJ *aij; + int nnz; + xassert(npp == npp); + nnz = 0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + nnz++; + return nnz; +} + +int npp_col_nnz(NPP *npp, NPPCOL *col) +{ /* count number of non-zero coefficients in column */ + NPPAIJ *aij; + int nnz; + xassert(npp == npp); + nnz = 0; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + nnz++; + return nnz; +} + +void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info), + int size) +{ /* push new entry to the transformation stack */ + NPPTSE *tse; + tse = dmp_get_atom(npp->stack, sizeof(NPPTSE)); + tse->func = func; + tse->info = dmp_get_atom(npp->stack, size); + tse->link = npp->top; + npp->top = tse; + return tse->info; +} + +#if 1 /* 23/XII-2009 */ +void npp_erase_row(NPP *npp, NPPROW *row) +{ /* erase row content to make it empty */ + NPPAIJ *aij; + while (row->ptr != NULL) + { aij = row->ptr; + row->ptr = aij->r_next; + if (aij->c_prev == NULL) + aij->col->ptr = aij->c_next; + else + aij->c_prev->c_next = aij->c_next; + if (aij->c_next == NULL) + ; + else + aij->c_next->c_prev = aij->c_prev; + dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); + } + return; +} +#endif + +void npp_del_row(NPP *npp, NPPROW *row) +{ /* remove row from the current problem */ +#if 0 /* 23/XII-2009 */ + NPPAIJ *aij; +#endif + if (row->name != NULL) + dmp_free_atom(npp->pool, row->name, strlen(row->name)+1); +#if 0 /* 23/XII-2009 */ + while (row->ptr != NULL) + { aij = row->ptr; + row->ptr = aij->r_next; + if (aij->c_prev == NULL) + aij->col->ptr = aij->c_next; + else + aij->c_prev->c_next = aij->c_next; + if (aij->c_next == NULL) + ; + else + aij->c_next->c_prev = aij->c_prev; + dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); + } +#else + npp_erase_row(npp, row); +#endif + npp_remove_row(npp, row); + dmp_free_atom(npp->pool, row, sizeof(NPPROW)); + return; +} + +void npp_del_col(NPP *npp, NPPCOL *col) +{ /* remove column from the current problem */ + NPPAIJ *aij; + if (col->name != NULL) + dmp_free_atom(npp->pool, col->name, strlen(col->name)+1); + while (col->ptr != NULL) + { aij = col->ptr; + col->ptr = aij->c_next; + if (aij->r_prev == NULL) + aij->row->ptr = aij->r_next; + else + aij->r_prev->r_next = aij->r_next; + if (aij->r_next == NULL) + ; + else + aij->r_next->r_prev = aij->r_prev; + dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); + } + npp_remove_col(npp, col); + dmp_free_atom(npp->pool, col, sizeof(NPPCOL)); + return; +} + +void npp_del_aij(NPP *npp, NPPAIJ *aij) +{ /* remove element from the constraint matrix */ + if (aij->r_prev == NULL) + aij->row->ptr = aij->r_next; + else + aij->r_prev->r_next = aij->r_next; + if (aij->r_next == NULL) + ; + else + aij->r_next->r_prev = aij->r_prev; + if (aij->c_prev == NULL) + aij->col->ptr = aij->c_next; + else + aij->c_prev->c_next = aij->c_next; + if (aij->c_next == NULL) + ; + else + aij->c_next->c_prev = aij->c_prev; + dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); + return; +} + +void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol, + int scaling) +{ /* load original problem into the preprocessor workspace */ + int m = orig->m; + int n = orig->n; + NPPROW **link; + int i, j; + double dir; + xassert(names == GLP_OFF || names == GLP_ON); + xassert(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP); + xassert(scaling == GLP_OFF || scaling == GLP_ON); + if (sol == GLP_MIP) xassert(!scaling); + npp->orig_dir = orig->dir; + if (npp->orig_dir == GLP_MIN) + dir = +1.0; + else if (npp->orig_dir == GLP_MAX) + dir = -1.0; + else + xassert(npp != npp); + npp->orig_m = m; + npp->orig_n = n; + npp->orig_nnz = orig->nnz; + if (names && orig->name != NULL) + { npp->name = dmp_get_atom(npp->pool, strlen(orig->name)+1); + strcpy(npp->name, orig->name); + } + if (names && orig->obj != NULL) + { npp->obj = dmp_get_atom(npp->pool, strlen(orig->obj)+1); + strcpy(npp->obj, orig->obj); + } + npp->c0 = dir * orig->c0; + /* load rows */ + link = xcalloc(1+m, sizeof(NPPROW *)); + for (i = 1; i <= m; i++) + { GLPROW *rrr = orig->row[i]; + NPPROW *row; + link[i] = row = npp_add_row(npp); + xassert(row->i == i); + if (names && rrr->name != NULL) + { row->name = dmp_get_atom(npp->pool, strlen(rrr->name)+1); + strcpy(row->name, rrr->name); + } + if (!scaling) + { if (rrr->type == GLP_FR) + row->lb = -DBL_MAX, row->ub = +DBL_MAX; + else if (rrr->type == GLP_LO) + row->lb = rrr->lb, row->ub = +DBL_MAX; + else if (rrr->type == GLP_UP) + row->lb = -DBL_MAX, row->ub = rrr->ub; + else if (rrr->type == GLP_DB) + row->lb = rrr->lb, row->ub = rrr->ub; + else if (rrr->type == GLP_FX) + row->lb = row->ub = rrr->lb; + else + xassert(rrr != rrr); + } + else + { double rii = rrr->rii; + if (rrr->type == GLP_FR) + row->lb = -DBL_MAX, row->ub = +DBL_MAX; + else if (rrr->type == GLP_LO) + row->lb = rrr->lb * rii, row->ub = +DBL_MAX; + else if (rrr->type == GLP_UP) + row->lb = -DBL_MAX, row->ub = rrr->ub * rii; + else if (rrr->type == GLP_DB) + row->lb = rrr->lb * rii, row->ub = rrr->ub * rii; + else if (rrr->type == GLP_FX) + row->lb = row->ub = rrr->lb * rii; + else + xassert(rrr != rrr); + } + } + /* load columns and constraint coefficients */ + for (j = 1; j <= n; j++) + { GLPCOL *ccc = orig->col[j]; + GLPAIJ *aaa; + NPPCOL *col; + col = npp_add_col(npp); + xassert(col->j == j); + if (names && ccc->name != NULL) + { col->name = dmp_get_atom(npp->pool, strlen(ccc->name)+1); + strcpy(col->name, ccc->name); + } + if (sol == GLP_MIP) +#if 0 + col->kind = ccc->kind; +#else + col->is_int = (char)(ccc->kind == GLP_IV); +#endif + if (!scaling) + { if (ccc->type == GLP_FR) + col->lb = -DBL_MAX, col->ub = +DBL_MAX; + else if (ccc->type == GLP_LO) + col->lb = ccc->lb, col->ub = +DBL_MAX; + else if (ccc->type == GLP_UP) + col->lb = -DBL_MAX, col->ub = ccc->ub; + else if (ccc->type == GLP_DB) + col->lb = ccc->lb, col->ub = ccc->ub; + else if (ccc->type == GLP_FX) + col->lb = col->ub = ccc->lb; + else + xassert(ccc != ccc); + col->coef = dir * ccc->coef; + for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next) + npp_add_aij(npp, link[aaa->row->i], col, aaa->val); + } + else + { double sjj = ccc->sjj; + if (ccc->type == GLP_FR) + col->lb = -DBL_MAX, col->ub = +DBL_MAX; + else if (ccc->type == GLP_LO) + col->lb = ccc->lb / sjj, col->ub = +DBL_MAX; + else if (ccc->type == GLP_UP) + col->lb = -DBL_MAX, col->ub = ccc->ub / sjj; + else if (ccc->type == GLP_DB) + col->lb = ccc->lb / sjj, col->ub = ccc->ub / sjj; + else if (ccc->type == GLP_FX) + col->lb = col->ub = ccc->lb / sjj; + else + xassert(ccc != ccc); + col->coef = dir * ccc->coef * sjj; + for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next) + npp_add_aij(npp, link[aaa->row->i], col, + aaa->row->rii * aaa->val * sjj); + } + } + xfree(link); + /* keep solution indicator and scaling option */ + npp->sol = sol; + npp->scaling = scaling; + return; +} + +void npp_build_prob(NPP *npp, glp_prob *prob) +{ /* build resultant (preprocessed) problem */ + NPPROW *row; + NPPCOL *col; + NPPAIJ *aij; + int i, j, type, len, *ind; + double dir, *val; + glp_erase_prob(prob); + glp_set_prob_name(prob, npp->name); + glp_set_obj_name(prob, npp->obj); + glp_set_obj_dir(prob, npp->orig_dir); + if (npp->orig_dir == GLP_MIN) + dir = +1.0; + else if (npp->orig_dir == GLP_MAX) + dir = -1.0; + else + xassert(npp != npp); + glp_set_obj_coef(prob, 0, dir * npp->c0); + /* build rows */ + for (row = npp->r_head; row != NULL; row = row->next) + { row->temp = i = glp_add_rows(prob, 1); + glp_set_row_name(prob, i, row->name); + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + type = GLP_FR; + else if (row->ub == +DBL_MAX) + type = GLP_LO; + else if (row->lb == -DBL_MAX) + type = GLP_UP; + else if (row->lb != row->ub) + type = GLP_DB; + else + type = GLP_FX; + glp_set_row_bnds(prob, i, type, row->lb, row->ub); + } + /* build columns and the constraint matrix */ + ind = xcalloc(1+prob->m, sizeof(int)); + val = xcalloc(1+prob->m, sizeof(double)); + for (col = npp->c_head; col != NULL; col = col->next) + { j = glp_add_cols(prob, 1); + glp_set_col_name(prob, j, col->name); +#if 0 + glp_set_col_kind(prob, j, col->kind); +#else + glp_set_col_kind(prob, j, col->is_int ? GLP_IV : GLP_CV); +#endif + if (col->lb == -DBL_MAX && col->ub == +DBL_MAX) + type = GLP_FR; + else if (col->ub == +DBL_MAX) + type = GLP_LO; + else if (col->lb == -DBL_MAX) + type = GLP_UP; + else if (col->lb != col->ub) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(prob, j, type, col->lb, col->ub); + glp_set_obj_coef(prob, j, dir * col->coef); + len = 0; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + { len++; + ind[len] = aij->row->temp; + val[len] = aij->val; + } + glp_set_mat_col(prob, j, len, ind, val); + } + xfree(ind); + xfree(val); + /* resultant problem has been built */ + npp->m = prob->m; + npp->n = prob->n; + npp->nnz = prob->nnz; + npp->row_ref = xcalloc(1+npp->m, sizeof(int)); + npp->col_ref = xcalloc(1+npp->n, sizeof(int)); + for (row = npp->r_head, i = 0; row != NULL; row = row->next) + npp->row_ref[++i] = row->i; + for (col = npp->c_head, j = 0; col != NULL; col = col->next) + npp->col_ref[++j] = col->j; + /* transformed problem segment is no longer needed */ + dmp_delete_pool(npp->pool), npp->pool = NULL; + npp->name = npp->obj = NULL; + npp->c0 = 0.0; + npp->r_head = npp->r_tail = NULL; + npp->c_head = npp->c_tail = NULL; + return; +} + +void npp_postprocess(NPP *npp, glp_prob *prob) +{ /* postprocess solution from the resultant problem */ + GLPROW *row; + GLPCOL *col; + NPPTSE *tse; + int i, j, k; + double dir; + xassert(npp->orig_dir == prob->dir); + if (npp->orig_dir == GLP_MIN) + dir = +1.0; + else if (npp->orig_dir == GLP_MAX) + dir = -1.0; + else + xassert(npp != npp); +#if 0 /* 11/VII-2013; due to call from ios_main */ + xassert(npp->m == prob->m); +#else + if (npp->sol != GLP_MIP) + xassert(npp->m == prob->m); +#endif + xassert(npp->n == prob->n); +#if 0 /* 11/VII-2013; due to call from ios_main */ + xassert(npp->nnz == prob->nnz); +#else + if (npp->sol != GLP_MIP) + xassert(npp->nnz == prob->nnz); +#endif + /* copy solution status */ + if (npp->sol == GLP_SOL) + { npp->p_stat = prob->pbs_stat; + npp->d_stat = prob->dbs_stat; + } + else if (npp->sol == GLP_IPT) + npp->t_stat = prob->ipt_stat; + else if (npp->sol == GLP_MIP) + npp->i_stat = prob->mip_stat; + else + xassert(npp != npp); + /* allocate solution arrays */ + if (npp->sol == GLP_SOL) + { if (npp->r_stat == NULL) + npp->r_stat = xcalloc(1+npp->nrows, sizeof(char)); + for (i = 1; i <= npp->nrows; i++) + npp->r_stat[i] = 0; + if (npp->c_stat == NULL) + npp->c_stat = xcalloc(1+npp->ncols, sizeof(char)); + for (j = 1; j <= npp->ncols; j++) + npp->c_stat[j] = 0; + } +#if 0 + if (npp->r_prim == NULL) + npp->r_prim = xcalloc(1+npp->nrows, sizeof(double)); + for (i = 1; i <= npp->nrows; i++) + npp->r_prim[i] = DBL_MAX; +#endif + if (npp->c_value == NULL) + npp->c_value = xcalloc(1+npp->ncols, sizeof(double)); + for (j = 1; j <= npp->ncols; j++) + npp->c_value[j] = DBL_MAX; + if (npp->sol != GLP_MIP) + { if (npp->r_pi == NULL) + npp->r_pi = xcalloc(1+npp->nrows, sizeof(double)); + for (i = 1; i <= npp->nrows; i++) + npp->r_pi[i] = DBL_MAX; +#if 0 + if (npp->c_dual == NULL) + npp->c_dual = xcalloc(1+npp->ncols, sizeof(double)); + for (j = 1; j <= npp->ncols; j++) + npp->c_dual[j] = DBL_MAX; +#endif + } + /* copy solution components from the resultant problem */ + if (npp->sol == GLP_SOL) + { for (i = 1; i <= npp->m; i++) + { row = prob->row[i]; + k = npp->row_ref[i]; + npp->r_stat[k] = (char)row->stat; + /*npp->r_prim[k] = row->prim;*/ + npp->r_pi[k] = dir * row->dual; + } + for (j = 1; j <= npp->n; j++) + { col = prob->col[j]; + k = npp->col_ref[j]; + npp->c_stat[k] = (char)col->stat; + npp->c_value[k] = col->prim; + /*npp->c_dual[k] = dir * col->dual;*/ + } + } + else if (npp->sol == GLP_IPT) + { for (i = 1; i <= npp->m; i++) + { row = prob->row[i]; + k = npp->row_ref[i]; + /*npp->r_prim[k] = row->pval;*/ + npp->r_pi[k] = dir * row->dval; + } + for (j = 1; j <= npp->n; j++) + { col = prob->col[j]; + k = npp->col_ref[j]; + npp->c_value[k] = col->pval; + /*npp->c_dual[k] = dir * col->dval;*/ + } + } + else if (npp->sol == GLP_MIP) + { +#if 0 + for (i = 1; i <= npp->m; i++) + { row = prob->row[i]; + k = npp->row_ref[i]; + /*npp->r_prim[k] = row->mipx;*/ + } +#endif + for (j = 1; j <= npp->n; j++) + { col = prob->col[j]; + k = npp->col_ref[j]; + npp->c_value[k] = col->mipx; + } + } + else + xassert(npp != npp); + /* perform postprocessing to construct solution to the original + problem */ + for (tse = npp->top; tse != NULL; tse = tse->link) + { xassert(tse->func != NULL); + xassert(tse->func(npp, tse->info) == 0); + } + return; +} + +void npp_unload_sol(NPP *npp, glp_prob *orig) +{ /* store solution to the original problem */ + GLPROW *row; + GLPCOL *col; + int i, j; + double dir; + xassert(npp->orig_dir == orig->dir); + if (npp->orig_dir == GLP_MIN) + dir = +1.0; + else if (npp->orig_dir == GLP_MAX) + dir = -1.0; + else + xassert(npp != npp); + xassert(npp->orig_m == orig->m); + xassert(npp->orig_n == orig->n); + xassert(npp->orig_nnz == orig->nnz); + if (npp->sol == GLP_SOL) + { /* store basic solution */ + orig->valid = 0; + orig->pbs_stat = npp->p_stat; + orig->dbs_stat = npp->d_stat; + orig->obj_val = orig->c0; + orig->some = 0; + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + row->stat = npp->r_stat[i]; + if (!npp->scaling) + { /*row->prim = npp->r_prim[i];*/ + row->dual = dir * npp->r_pi[i]; + } + else + { /*row->prim = npp->r_prim[i] / row->rii;*/ + row->dual = dir * npp->r_pi[i] * row->rii; + } + if (row->stat == GLP_BS) + row->dual = 0.0; + else if (row->stat == GLP_NL) + { xassert(row->type == GLP_LO || row->type == GLP_DB); + row->prim = row->lb; + } + else if (row->stat == GLP_NU) + { xassert(row->type == GLP_UP || row->type == GLP_DB); + row->prim = row->ub; + } + else if (row->stat == GLP_NF) + { xassert(row->type == GLP_FR); + row->prim = 0.0; + } + else if (row->stat == GLP_NS) + { xassert(row->type == GLP_FX); + row->prim = row->lb; + } + else + xassert(row != row); + } + for (j = 1; j <= orig->n; j++) + { col = orig->col[j]; + col->stat = npp->c_stat[j]; + if (!npp->scaling) + { col->prim = npp->c_value[j]; + /*col->dual = dir * npp->c_dual[j];*/ + } + else + { col->prim = npp->c_value[j] * col->sjj; + /*col->dual = dir * npp->c_dual[j] / col->sjj;*/ + } + if (col->stat == GLP_BS) + col->dual = 0.0; +#if 1 + else if (col->stat == GLP_NL) + { xassert(col->type == GLP_LO || col->type == GLP_DB); + col->prim = col->lb; + } + else if (col->stat == GLP_NU) + { xassert(col->type == GLP_UP || col->type == GLP_DB); + col->prim = col->ub; + } + else if (col->stat == GLP_NF) + { xassert(col->type == GLP_FR); + col->prim = 0.0; + } + else if (col->stat == GLP_NS) + { xassert(col->type == GLP_FX); + col->prim = col->lb; + } + else + xassert(col != col); +#endif + orig->obj_val += col->coef * col->prim; + } +#if 1 + /* compute primal values of inactive rows */ + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + if (row->stat == GLP_BS) + { GLPAIJ *aij; + double temp; + temp = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + temp += aij->val * aij->col->prim; + row->prim = temp; + } + } + /* compute reduced costs of active columns */ + for (j = 1; j <= orig->n; j++) + { col = orig->col[j]; + if (col->stat != GLP_BS) + { GLPAIJ *aij; + double temp; + temp = col->coef; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + temp -= aij->val * aij->row->dual; + col->dual = temp; + } + } +#endif + } + else if (npp->sol == GLP_IPT) + { /* store interior-point solution */ + orig->ipt_stat = npp->t_stat; + orig->ipt_obj = orig->c0; + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + if (!npp->scaling) + { /*row->pval = npp->r_prim[i];*/ + row->dval = dir * npp->r_pi[i]; + } + else + { /*row->pval = npp->r_prim[i] / row->rii;*/ + row->dval = dir * npp->r_pi[i] * row->rii; + } + } + for (j = 1; j <= orig->n; j++) + { col = orig->col[j]; + if (!npp->scaling) + { col->pval = npp->c_value[j]; + /*col->dval = dir * npp->c_dual[j];*/ + } + else + { col->pval = npp->c_value[j] * col->sjj; + /*col->dval = dir * npp->c_dual[j] / col->sjj;*/ + } + orig->ipt_obj += col->coef * col->pval; + } +#if 1 + /* compute row primal values */ + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + { GLPAIJ *aij; + double temp; + temp = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + temp += aij->val * aij->col->pval; + row->pval = temp; + } + } + /* compute column dual values */ + for (j = 1; j <= orig->n; j++) + { col = orig->col[j]; + { GLPAIJ *aij; + double temp; + temp = col->coef; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + temp -= aij->val * aij->row->dval; + col->dval = temp; + } + } +#endif + } + else if (npp->sol == GLP_MIP) + { /* store MIP solution */ + xassert(!npp->scaling); + orig->mip_stat = npp->i_stat; + orig->mip_obj = orig->c0; +#if 0 + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + /*row->mipx = npp->r_prim[i];*/ + } +#endif + for (j = 1; j <= orig->n; j++) + { col = orig->col[j]; + col->mipx = npp->c_value[j]; + if (col->kind == GLP_IV) + xassert(col->mipx == floor(col->mipx)); + orig->mip_obj += col->coef * col->mipx; + } +#if 1 + /* compute row primal values */ + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + { GLPAIJ *aij; + double temp; + temp = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + temp += aij->val * aij->col->mipx; + row->mipx = temp; + } + } +#endif + } + else + xassert(npp != npp); + return; +} + +void npp_delete_wksp(NPP *npp) +{ /* delete LP/MIP preprocessor workspace */ + if (npp->pool != NULL) + dmp_delete_pool(npp->pool); + if (npp->stack != NULL) + dmp_delete_pool(npp->stack); + if (npp->row_ref != NULL) + xfree(npp->row_ref); + if (npp->col_ref != NULL) + xfree(npp->col_ref); + if (npp->r_stat != NULL) + xfree(npp->r_stat); +#if 0 + if (npp->r_prim != NULL) + xfree(npp->r_prim); +#endif + if (npp->r_pi != NULL) + xfree(npp->r_pi); + if (npp->c_stat != NULL) + xfree(npp->c_stat); + if (npp->c_value != NULL) + xfree(npp->c_value); +#if 0 + if (npp->c_dual != NULL) + xfree(npp->c_dual); +#endif + xfree(npp); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp02.c b/resources/3rdparty/glpk-4.53/src/glpnpp02.c new file mode 100644 index 000000000..ec4a455b4 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpnpp02.c @@ -0,0 +1,1434 @@ +/* glpnpp02.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpnpp.h" + +/*********************************************************************** +* NAME +* +* npp_free_row - process free (unbounded) row +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_free_row(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_free_row processes row p, which is free (i.e. has +* no finite bounds): +* +* -inf < sum a[p,j] x[j] < +inf. (1) +* j +* +* PROBLEM TRANSFORMATION +* +* Constraint (1) cannot be active, so it is redundant and can be +* removed from the original problem. +* +* Removing row p leads to removing a column of multiplier pi[p] for +* this row in the dual system. Since row p has no bounds, pi[p] = 0, +* so removing the column does not affect the dual solution. +* +* RECOVERING BASIC SOLUTION +* +* In solution to the original problem row p is inactive constraint, +* so it is assigned status GLP_BS, and multiplier pi[p] is assigned +* zero value. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* In solution to the original problem row p is inactive constraint, +* so its multiplier pi[p] is assigned zero value. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct free_row +{ /* free (unbounded) row */ + int p; + /* row reference number */ +}; + +static int rcv_free_row(NPP *npp, void *info); + +void npp_free_row(NPP *npp, NPPROW *p) +{ /* process free (unbounded) row */ + struct free_row *info; + /* the row must be free */ + xassert(p->lb == -DBL_MAX && p->ub == +DBL_MAX); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_free_row, sizeof(struct free_row)); + info->p = p->i; + /* remove the row from the problem */ + npp_del_row(npp, p); + return; +} + +static int rcv_free_row(NPP *npp, void *_info) +{ /* recover free (unbounded) row */ + struct free_row *info = _info; + if (npp->sol == GLP_SOL) + npp->r_stat[info->p] = GLP_BS; + if (npp->sol != GLP_MIP) + npp->r_pi[info->p] = 0.0; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_geq_row - process row of 'not less than' type +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_geq_row(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_geq_row processes row p, which is 'not less than' +* inequality constraint: +* +* L[p] <= sum a[p,j] x[j] (<= U[p]), (1) +* j +* +* where L[p] < U[p], and upper bound may not exist (U[p] = +oo). +* +* PROBLEM TRANSFORMATION +* +* Constraint (1) can be replaced by equality constraint: +* +* sum a[p,j] x[j] - s = L[p], (2) +* j +* +* where +* +* 0 <= s (<= U[p] - L[p]) (3) +* +* is a non-negative surplus variable. +* +* Since in the primal system there appears column s having the only +* non-zero coefficient in row p, in the dual system there appears a +* new row: +* +* (-1) pi[p] + lambda = 0, (4) +* +* where (-1) is coefficient of column s in row p, pi[p] is multiplier +* of row p, lambda is multiplier of column q, 0 is coefficient of +* column s in the objective row. +* +* RECOVERING BASIC SOLUTION +* +* Status of row p in solution to the original problem is determined +* by its status and status of column q in solution to the transformed +* problem as follows: +* +* +--------------------------------------+------------------+ +* | Transformed problem | Original problem | +* +-----------------+--------------------+------------------+ +* | Status of row p | Status of column s | Status of row p | +* +-----------------+--------------------+------------------+ +* | GLP_BS | GLP_BS | N/A | +* | GLP_BS | GLP_NL | GLP_BS | +* | GLP_BS | GLP_NU | GLP_BS | +* | GLP_NS | GLP_BS | GLP_BS | +* | GLP_NS | GLP_NL | GLP_NL | +* | GLP_NS | GLP_NU | GLP_NU | +* +-----------------+--------------------+------------------+ +* +* Value of row multiplier pi[p] in solution to the original problem +* is the same as in solution to the transformed problem. +* +* 1. In solution to the transformed problem row p and column q cannot +* be basic at the same time; otherwise the basis matrix would have +* two linear dependent columns: unity column of auxiliary variable +* of row p and unity column of variable s. +* +* 2. Though in the transformed problem row p is equality constraint, +* it may be basic due to primal degenerate solution. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of row multiplier pi[p] in solution to the original problem +* is the same as in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct ineq_row +{ /* inequality constraint row */ + int p; + /* row reference number */ + int s; + /* column reference number for slack/surplus variable */ +}; + +static int rcv_geq_row(NPP *npp, void *info); + +void npp_geq_row(NPP *npp, NPPROW *p) +{ /* process row of 'not less than' type */ + struct ineq_row *info; + NPPCOL *s; + /* the row must have lower bound */ + xassert(p->lb != -DBL_MAX); + xassert(p->lb < p->ub); + /* create column for surplus variable */ + s = npp_add_col(npp); + s->lb = 0.0; + s->ub = (p->ub == +DBL_MAX ? +DBL_MAX : p->ub - p->lb); + /* and add it to the transformed problem */ + npp_add_aij(npp, p, s, -1.0); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_geq_row, sizeof(struct ineq_row)); + info->p = p->i; + info->s = s->j; + /* replace the row by equality constraint */ + p->ub = p->lb; + return; +} + +static int rcv_geq_row(NPP *npp, void *_info) +{ /* recover row of 'not less than' type */ + struct ineq_row *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] == GLP_BS) + { if (npp->c_stat[info->s] == GLP_BS) + { npp_error(); + return 1; + } + else if (npp->c_stat[info->s] == GLP_NL || + npp->c_stat[info->s] == GLP_NU) + npp->r_stat[info->p] = GLP_BS; + else + { npp_error(); + return 1; + } + } + else if (npp->r_stat[info->p] == GLP_NS) + { if (npp->c_stat[info->s] == GLP_BS) + npp->r_stat[info->p] = GLP_BS; + else if (npp->c_stat[info->s] == GLP_NL) + npp->r_stat[info->p] = GLP_NL; + else if (npp->c_stat[info->s] == GLP_NU) + npp->r_stat[info->p] = GLP_NU; + else + { npp_error(); + return 1; + } + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_leq_row - process row of 'not greater than' type +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_leq_row(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_leq_row processes row p, which is 'not greater than' +* inequality constraint: +* +* (L[p] <=) sum a[p,j] x[j] <= U[p], (1) +* j +* +* where L[p] < U[p], and lower bound may not exist (L[p] = +oo). +* +* PROBLEM TRANSFORMATION +* +* Constraint (1) can be replaced by equality constraint: +* +* sum a[p,j] x[j] + s = L[p], (2) +* j +* +* where +* +* 0 <= s (<= U[p] - L[p]) (3) +* +* is a non-negative slack variable. +* +* Since in the primal system there appears column s having the only +* non-zero coefficient in row p, in the dual system there appears a +* new row: +* +* (+1) pi[p] + lambda = 0, (4) +* +* where (+1) is coefficient of column s in row p, pi[p] is multiplier +* of row p, lambda is multiplier of column q, 0 is coefficient of +* column s in the objective row. +* +* RECOVERING BASIC SOLUTION +* +* Status of row p in solution to the original problem is determined +* by its status and status of column q in solution to the transformed +* problem as follows: +* +* +--------------------------------------+------------------+ +* | Transformed problem | Original problem | +* +-----------------+--------------------+------------------+ +* | Status of row p | Status of column s | Status of row p | +* +-----------------+--------------------+------------------+ +* | GLP_BS | GLP_BS | N/A | +* | GLP_BS | GLP_NL | GLP_BS | +* | GLP_BS | GLP_NU | GLP_BS | +* | GLP_NS | GLP_BS | GLP_BS | +* | GLP_NS | GLP_NL | GLP_NU | +* | GLP_NS | GLP_NU | GLP_NL | +* +-----------------+--------------------+------------------+ +* +* Value of row multiplier pi[p] in solution to the original problem +* is the same as in solution to the transformed problem. +* +* 1. In solution to the transformed problem row p and column q cannot +* be basic at the same time; otherwise the basis matrix would have +* two linear dependent columns: unity column of auxiliary variable +* of row p and unity column of variable s. +* +* 2. Though in the transformed problem row p is equality constraint, +* it may be basic due to primal degeneracy. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of row multiplier pi[p] in solution to the original problem +* is the same as in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +static int rcv_leq_row(NPP *npp, void *info); + +void npp_leq_row(NPP *npp, NPPROW *p) +{ /* process row of 'not greater than' type */ + struct ineq_row *info; + NPPCOL *s; + /* the row must have upper bound */ + xassert(p->ub != +DBL_MAX); + xassert(p->lb < p->ub); + /* create column for slack variable */ + s = npp_add_col(npp); + s->lb = 0.0; + s->ub = (p->lb == -DBL_MAX ? +DBL_MAX : p->ub - p->lb); + /* and add it to the transformed problem */ + npp_add_aij(npp, p, s, +1.0); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_leq_row, sizeof(struct ineq_row)); + info->p = p->i; + info->s = s->j; + /* replace the row by equality constraint */ + p->lb = p->ub; + return; +} + +static int rcv_leq_row(NPP *npp, void *_info) +{ /* recover row of 'not greater than' type */ + struct ineq_row *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] == GLP_BS) + { if (npp->c_stat[info->s] == GLP_BS) + { npp_error(); + return 1; + } + else if (npp->c_stat[info->s] == GLP_NL || + npp->c_stat[info->s] == GLP_NU) + npp->r_stat[info->p] = GLP_BS; + else + { npp_error(); + return 1; + } + } + else if (npp->r_stat[info->p] == GLP_NS) + { if (npp->c_stat[info->s] == GLP_BS) + npp->r_stat[info->p] = GLP_BS; + else if (npp->c_stat[info->s] == GLP_NL) + npp->r_stat[info->p] = GLP_NU; + else if (npp->c_stat[info->s] == GLP_NU) + npp->r_stat[info->p] = GLP_NL; + else + { npp_error(); + return 1; + } + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_free_col - process free (unbounded) column +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_free_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_free_col processes column q, which is free (i.e. has +* no finite bounds): +* +* -oo < x[q] < +oo. (1) +* +* PROBLEM TRANSFORMATION +* +* Free (unbounded) variable can be replaced by the difference of two +* non-negative variables: +* +* x[q] = s' - s'', s', s'' >= 0. (2) +* +* Assuming that in the transformed problem x[q] becomes s', +* transformation (2) causes new column s'' to appear, which differs +* from column s' only in the sign of coefficients in constraint and +* objective rows. Thus, if in the dual system the following row +* corresponds to column s': +* +* sum a[i,q] pi[i] + lambda' = c[q], (3) +* i +* +* the row which corresponds to column s'' is the following: +* +* sum (-a[i,q]) pi[i] + lambda'' = -c[q]. (4) +* i +* +* Then from (3) and (4) it follows that: +* +* lambda' + lambda'' = 0 => lambda' = lmabda'' = 0, (5) +* +* where lambda' and lambda'' are multipliers for columns s' and s'', +* resp. +* +* RECOVERING BASIC SOLUTION +* +* With respect to (5) status of column q in solution to the original +* problem is determined by statuses of columns s' and s'' in solution +* to the transformed problem as follows: +* +* +--------------------------------------+------------------+ +* | Transformed problem | Original problem | +* +------------------+-------------------+------------------+ +* | Status of col s' | Status of col s'' | Status of col q | +* +------------------+-------------------+------------------+ +* | GLP_BS | GLP_BS | N/A | +* | GLP_BS | GLP_NL | GLP_BS | +* | GLP_NL | GLP_BS | GLP_BS | +* | GLP_NL | GLP_NL | GLP_NF | +* +------------------+-------------------+------------------+ +* +* Value of column q is computed with formula (2). +* +* 1. In solution to the transformed problem columns s' and s'' cannot +* be basic at the same time, because they differ only in the sign, +* hence, are linear dependent. +* +* 2. Though column q is free, it can be non-basic due to dual +* degeneracy. +* +* 3. If column q is integral, columns s' and s'' are also integral. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q is computed with formula (2). +* +* RECOVERING MIP SOLUTION +* +* Value of column q is computed with formula (2). */ + +struct free_col +{ /* free (unbounded) column */ + int q; + /* column reference number for variables x[q] and s' */ + int s; + /* column reference number for variable s'' */ +}; + +static int rcv_free_col(NPP *npp, void *info); + +void npp_free_col(NPP *npp, NPPCOL *q) +{ /* process free (unbounded) column */ + struct free_col *info; + NPPCOL *s; + NPPAIJ *aij; + /* the column must be free */ + xassert(q->lb == -DBL_MAX && q->ub == +DBL_MAX); + /* variable x[q] becomes s' */ + q->lb = 0.0, q->ub = +DBL_MAX; + /* create variable s'' */ + s = npp_add_col(npp); + s->is_int = q->is_int; + s->lb = 0.0, s->ub = +DBL_MAX; + /* duplicate objective coefficient */ + s->coef = -q->coef; + /* duplicate column of the constraint matrix */ + for (aij = q->ptr; aij != NULL; aij = aij->c_next) + npp_add_aij(npp, aij->row, s, -aij->val); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_free_col, sizeof(struct free_col)); + info->q = q->j; + info->s = s->j; + return; +} + +static int rcv_free_col(NPP *npp, void *_info) +{ /* recover free (unbounded) column */ + struct free_col *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->c_stat[info->q] == GLP_BS) + { if (npp->c_stat[info->s] == GLP_BS) + { npp_error(); + return 1; + } + else if (npp->c_stat[info->s] == GLP_NL) + npp->c_stat[info->q] = GLP_BS; + else + { npp_error(); + return -1; + } + } + else if (npp->c_stat[info->q] == GLP_NL) + { if (npp->c_stat[info->s] == GLP_BS) + npp->c_stat[info->q] = GLP_BS; + else if (npp->c_stat[info->s] == GLP_NL) + npp->c_stat[info->q] = GLP_NF; + else + { npp_error(); + return -1; + } + } + else + { npp_error(); + return -1; + } + } + /* compute value of x[q] with formula (2) */ + npp->c_value[info->q] -= npp->c_value[info->s]; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_lbnd_col - process column with (non-zero) lower bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_lbnd_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_lbnd_col processes column q, which has (non-zero) +* lower bound: +* +* l[q] <= x[q] (<= u[q]), (1) +* +* where l[q] < u[q], and upper bound may not exist (u[q] = +oo). +* +* PROBLEM TRANSFORMATION +* +* Column q can be replaced as follows: +* +* x[q] = l[q] + s, (2) +* +* where +* +* 0 <= s (<= u[q] - l[q]) (3) +* +* is a non-negative variable. +* +* Substituting x[q] from (2) into the objective row, we have: +* +* z = sum c[j] x[j] + c0 = +* j +* +* = sum c[j] x[j] + c[q] x[q] + c0 = +* j!=q +* +* = sum c[j] x[j] + c[q] (l[q] + s) + c0 = +* j!=q +* +* = sum c[j] x[j] + c[q] s + c~0, +* +* where +* +* c~0 = c0 + c[q] l[q] (4) +* +* is the constant term of the objective in the transformed problem. +* Similarly, substituting x[q] into constraint row i, we have: +* +* L[i] <= sum a[i,j] x[j] <= U[i] ==> +* j +* +* L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> +* j!=q +* +* L[i] <= sum a[i,j] x[j] + a[i,q] (l[q] + s) <= U[i] ==> +* j!=q +* +* L~[i] <= sum a[i,j] x[j] + a[i,q] s <= U~[i], +* j!=q +* +* where +* +* L~[i] = L[i] - a[i,q] l[q], U~[i] = U[i] - a[i,q] l[q] (5) +* +* are lower and upper bounds of row i in the transformed problem, +* resp. +* +* Transformation (2) does not affect the dual system. +* +* RECOVERING BASIC SOLUTION +* +* Status of column q in solution to the original problem is the same +* as in solution to the transformed problem (GLP_BS, GLP_NL or GLP_NU). +* Value of column q is computed with formula (2). +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q is computed with formula (2). +* +* RECOVERING MIP SOLUTION +* +* Value of column q is computed with formula (2). */ + +struct bnd_col +{ /* bounded column */ + int q; + /* column reference number for variables x[q] and s */ + double bnd; + /* lower/upper bound l[q] or u[q] */ +}; + +static int rcv_lbnd_col(NPP *npp, void *info); + +void npp_lbnd_col(NPP *npp, NPPCOL *q) +{ /* process column with (non-zero) lower bound */ + struct bnd_col *info; + NPPROW *i; + NPPAIJ *aij; + /* the column must have non-zero lower bound */ + xassert(q->lb != 0.0); + xassert(q->lb != -DBL_MAX); + xassert(q->lb < q->ub); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_lbnd_col, sizeof(struct bnd_col)); + info->q = q->j; + info->bnd = q->lb; + /* substitute x[q] into objective row */ + npp->c0 += q->coef * q->lb; + /* substitute x[q] into constraint rows */ + for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row; + if (i->lb == i->ub) + i->ub = (i->lb -= aij->val * q->lb); + else + { if (i->lb != -DBL_MAX) + i->lb -= aij->val * q->lb; + if (i->ub != +DBL_MAX) + i->ub -= aij->val * q->lb; + } + } + /* column x[q] becomes column s */ + if (q->ub != +DBL_MAX) + q->ub -= q->lb; + q->lb = 0.0; + return; +} + +static int rcv_lbnd_col(NPP *npp, void *_info) +{ /* recover column with (non-zero) lower bound */ + struct bnd_col *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->c_stat[info->q] == GLP_BS || + npp->c_stat[info->q] == GLP_NL || + npp->c_stat[info->q] == GLP_NU) + npp->c_stat[info->q] = npp->c_stat[info->q]; + else + { npp_error(); + return 1; + } + } + /* compute value of x[q] with formula (2) */ + npp->c_value[info->q] = info->bnd + npp->c_value[info->q]; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_ubnd_col - process column with upper bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_ubnd_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_ubnd_col processes column q, which has upper bound: +* +* (l[q] <=) x[q] <= u[q], (1) +* +* where l[q] < u[q], and lower bound may not exist (l[q] = -oo). +* +* PROBLEM TRANSFORMATION +* +* Column q can be replaced as follows: +* +* x[q] = u[q] - s, (2) +* +* where +* +* 0 <= s (<= u[q] - l[q]) (3) +* +* is a non-negative variable. +* +* Substituting x[q] from (2) into the objective row, we have: +* +* z = sum c[j] x[j] + c0 = +* j +* +* = sum c[j] x[j] + c[q] x[q] + c0 = +* j!=q +* +* = sum c[j] x[j] + c[q] (u[q] - s) + c0 = +* j!=q +* +* = sum c[j] x[j] - c[q] s + c~0, +* +* where +* +* c~0 = c0 + c[q] u[q] (4) +* +* is the constant term of the objective in the transformed problem. +* Similarly, substituting x[q] into constraint row i, we have: +* +* L[i] <= sum a[i,j] x[j] <= U[i] ==> +* j +* +* L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> +* j!=q +* +* L[i] <= sum a[i,j] x[j] + a[i,q] (u[q] - s) <= U[i] ==> +* j!=q +* +* L~[i] <= sum a[i,j] x[j] - a[i,q] s <= U~[i], +* j!=q +* +* where +* +* L~[i] = L[i] - a[i,q] u[q], U~[i] = U[i] - a[i,q] u[q] (5) +* +* are lower and upper bounds of row i in the transformed problem, +* resp. +* +* Note that in the transformed problem coefficients c[q] and a[i,q] +* change their sign. Thus, the row of the dual system corresponding to +* column q: +* +* sum a[i,q] pi[i] + lambda[q] = c[q] (6) +* i +* +* in the transformed problem becomes the following: +* +* sum (-a[i,q]) pi[i] + lambda[s] = -c[q]. (7) +* i +* +* Therefore: +* +* lambda[q] = - lambda[s], (8) +* +* where lambda[q] is multiplier for column q, lambda[s] is multiplier +* for column s. +* +* RECOVERING BASIC SOLUTION +* +* With respect to (8) status of column q in solution to the original +* problem is determined by status of column s in solution to the +* transformed problem as follows: +* +* +-----------------------+--------------------+ +* | Status of column s | Status of column q | +* | (transformed problem) | (original problem) | +* +-----------------------+--------------------+ +* | GLP_BS | GLP_BS | +* | GLP_NL | GLP_NU | +* | GLP_NU | GLP_NL | +* +-----------------------+--------------------+ +* +* Value of column q is computed with formula (2). +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q is computed with formula (2). +* +* RECOVERING MIP SOLUTION +* +* Value of column q is computed with formula (2). */ + +static int rcv_ubnd_col(NPP *npp, void *info); + +void npp_ubnd_col(NPP *npp, NPPCOL *q) +{ /* process column with upper bound */ + struct bnd_col *info; + NPPROW *i; + NPPAIJ *aij; + /* the column must have upper bound */ + xassert(q->ub != +DBL_MAX); + xassert(q->lb < q->ub); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_ubnd_col, sizeof(struct bnd_col)); + info->q = q->j; + info->bnd = q->ub; + /* substitute x[q] into objective row */ + npp->c0 += q->coef * q->ub; + q->coef = -q->coef; + /* substitute x[q] into constraint rows */ + for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row; + if (i->lb == i->ub) + i->ub = (i->lb -= aij->val * q->ub); + else + { if (i->lb != -DBL_MAX) + i->lb -= aij->val * q->ub; + if (i->ub != +DBL_MAX) + i->ub -= aij->val * q->ub; + } + aij->val = -aij->val; + } + /* column x[q] becomes column s */ + if (q->lb != -DBL_MAX) + q->ub -= q->lb; + else + q->ub = +DBL_MAX; + q->lb = 0.0; + return; +} + +static int rcv_ubnd_col(NPP *npp, void *_info) +{ /* recover column with upper bound */ + struct bnd_col *info = _info; + if (npp->sol == GLP_BS) + { if (npp->c_stat[info->q] == GLP_BS) + npp->c_stat[info->q] = GLP_BS; + else if (npp->c_stat[info->q] == GLP_NL) + npp->c_stat[info->q] = GLP_NU; + else if (npp->c_stat[info->q] == GLP_NU) + npp->c_stat[info->q] = GLP_NL; + else + { npp_error(); + return 1; + } + } + /* compute value of x[q] with formula (2) */ + npp->c_value[info->q] = info->bnd - npp->c_value[info->q]; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_dbnd_col - process non-negative column with upper bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_dbnd_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_dbnd_col processes column q, which is non-negative +* and has upper bound: +* +* 0 <= x[q] <= u[q], (1) +* +* where u[q] > 0. +* +* PROBLEM TRANSFORMATION +* +* Upper bound of column q can be replaced by the following equality +* constraint: +* +* x[q] + s = u[q], (2) +* +* where s >= 0 is a non-negative complement variable. +* +* Since in the primal system along with new row (2) there appears a +* new column s having the only non-zero coefficient in this row, in +* the dual system there appears a new row: +* +* (+1)pi + lambda[s] = 0, (3) +* +* where (+1) is coefficient at column s in row (2), pi is multiplier +* for row (2), lambda[s] is multiplier for column s, 0 is coefficient +* at column s in the objective row. +* +* RECOVERING BASIC SOLUTION +* +* Status of column q in solution to the original problem is determined +* by its status and status of column s in solution to the transformed +* problem as follows: +* +* +-----------------------------------+------------------+ +* | Transformed problem | Original problem | +* +-----------------+-----------------+------------------+ +* | Status of col q | Status of col s | Status of col q | +* +-----------------+-----------------+------------------+ +* | GLP_BS | GLP_BS | GLP_BS | +* | GLP_BS | GLP_NL | GLP_NU | +* | GLP_NL | GLP_BS | GLP_NL | +* | GLP_NL | GLP_NL | GLP_NL (*) | +* +-----------------+-----------------+------------------+ +* +* Value of column q in solution to the original problem is the same as +* in solution to the transformed problem. +* +* 1. Formally, in solution to the transformed problem columns q and s +* cannot be non-basic at the same time, since the constraint (2) +* would be violated. However, if u[q] is close to zero, violation +* may be less than a working precision even if both columns q and s +* are non-basic. In this degenerate case row (2) can be only basic, +* i.e. non-active constraint (otherwise corresponding row of the +* basis matrix would be zero). This allows to pivot out auxiliary +* variable and pivot in column s, in which case the row becomes +* active while column s becomes basic. +* +* 2. If column q is integral, column s is also integral. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q in solution to the original problem is the same as +* in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* Value of column q in solution to the original problem is the same as +* in solution to the transformed problem. */ + +struct dbnd_col +{ /* double-bounded column */ + int q; + /* column reference number for variable x[q] */ + int s; + /* column reference number for complement variable s */ +}; + +static int rcv_dbnd_col(NPP *npp, void *info); + +void npp_dbnd_col(NPP *npp, NPPCOL *q) +{ /* process non-negative column with upper bound */ + struct dbnd_col *info; + NPPROW *p; + NPPCOL *s; + /* the column must be non-negative with upper bound */ + xassert(q->lb == 0.0); + xassert(q->ub > 0.0); + xassert(q->ub != +DBL_MAX); + /* create variable s */ + s = npp_add_col(npp); + s->is_int = q->is_int; + s->lb = 0.0, s->ub = +DBL_MAX; + /* create equality constraint (2) */ + p = npp_add_row(npp); + p->lb = p->ub = q->ub; + npp_add_aij(npp, p, q, +1.0); + npp_add_aij(npp, p, s, +1.0); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_dbnd_col, sizeof(struct dbnd_col)); + info->q = q->j; + info->s = s->j; + /* remove upper bound of x[q] */ + q->ub = +DBL_MAX; + return; +} + +static int rcv_dbnd_col(NPP *npp, void *_info) +{ /* recover non-negative column with upper bound */ + struct dbnd_col *info = _info; + if (npp->sol == GLP_BS) + { if (npp->c_stat[info->q] == GLP_BS) + { if (npp->c_stat[info->s] == GLP_BS) + npp->c_stat[info->q] = GLP_BS; + else if (npp->c_stat[info->s] == GLP_NL) + npp->c_stat[info->q] = GLP_NU; + else + { npp_error(); + return 1; + } + } + else if (npp->c_stat[info->q] == GLP_NL) + { if (npp->c_stat[info->s] == GLP_BS || + npp->c_stat[info->s] == GLP_NL) + npp->c_stat[info->q] = GLP_NL; + else + { npp_error(); + return 1; + } + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_fixed_col - process fixed column +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_fixed_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_fixed_col processes column q, which is fixed: +* +* x[q] = s[q], (1) +* +* where s[q] is a fixed column value. +* +* PROBLEM TRANSFORMATION +* +* The value of a fixed column can be substituted into the objective +* and constraint rows that allows removing the column from the problem. +* +* Substituting x[q] = s[q] into the objective row, we have: +* +* z = sum c[j] x[j] + c0 = +* j +* +* = sum c[j] x[j] + c[q] x[q] + c0 = +* j!=q +* +* = sum c[j] x[j] + c[q] s[q] + c0 = +* j!=q +* +* = sum c[j] x[j] + c~0, +* j!=q +* +* where +* +* c~0 = c0 + c[q] s[q] (2) +* +* is the constant term of the objective in the transformed problem. +* Similarly, substituting x[q] = s[q] into constraint row i, we have: +* +* L[i] <= sum a[i,j] x[j] <= U[i] ==> +* j +* +* L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> +* j!=q +* +* L[i] <= sum a[i,j] x[j] + a[i,q] s[q] <= U[i] ==> +* j!=q +* +* L~[i] <= sum a[i,j] x[j] + a[i,q] s <= U~[i], +* j!=q +* +* where +* +* L~[i] = L[i] - a[i,q] s[q], U~[i] = U[i] - a[i,q] s[q] (3) +* +* are lower and upper bounds of row i in the transformed problem, +* resp. +* +* RECOVERING BASIC SOLUTION +* +* Column q is assigned status GLP_NS and its value is assigned s[q]. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q is assigned s[q]. +* +* RECOVERING MIP SOLUTION +* +* Value of column q is assigned s[q]. */ + +struct fixed_col +{ /* fixed column */ + int q; + /* column reference number for variable x[q] */ + double s; + /* value, at which x[q] is fixed */ +}; + +static int rcv_fixed_col(NPP *npp, void *info); + +void npp_fixed_col(NPP *npp, NPPCOL *q) +{ /* process fixed column */ + struct fixed_col *info; + NPPROW *i; + NPPAIJ *aij; + /* the column must be fixed */ + xassert(q->lb == q->ub); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_fixed_col, sizeof(struct fixed_col)); + info->q = q->j; + info->s = q->lb; + /* substitute x[q] = s[q] into objective row */ + npp->c0 += q->coef * q->lb; + /* substitute x[q] = s[q] into constraint rows */ + for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row; + if (i->lb == i->ub) + i->ub = (i->lb -= aij->val * q->lb); + else + { if (i->lb != -DBL_MAX) + i->lb -= aij->val * q->lb; + if (i->ub != +DBL_MAX) + i->ub -= aij->val * q->lb; + } + } + /* remove the column from the problem */ + npp_del_col(npp, q); + return; +} + +static int rcv_fixed_col(NPP *npp, void *_info) +{ /* recover fixed column */ + struct fixed_col *info = _info; + if (npp->sol == GLP_SOL) + npp->c_stat[info->q] = GLP_NS; + npp->c_value[info->q] = info->s; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_make_equality - process row with almost identical bounds +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_make_equality(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_make_equality processes row p: +* +* L[p] <= sum a[p,j] x[j] <= U[p], (1) +* j +* +* where -oo < L[p] < U[p] < +oo, i.e. which is double-sided inequality +* constraint. +* +* RETURNS +* +* 0 - row bounds have not been changed; +* +* 1 - row has been replaced by equality constraint. +* +* PROBLEM TRANSFORMATION +* +* If bounds of row (1) are very close to each other: +* +* U[p] - L[p] <= eps, (2) +* +* where eps is an absolute tolerance for row value, the row can be +* replaced by the following almost equivalent equiality constraint: +* +* sum a[p,j] x[j] = b, (3) +* j +* +* where b = (L[p] + U[p]) / 2. If the right-hand side in (3) happens +* to be very close to its nearest integer: +* +* |b - floor(b + 0.5)| <= eps, (4) +* +* it is reasonable to use this nearest integer as the right-hand side. +* +* RECOVERING BASIC SOLUTION +* +* Status of row p in solution to the original problem is determined +* by its status and the sign of its multiplier pi[p] in solution to +* the transformed problem as follows: +* +* +-----------------------+---------+--------------------+ +* | Status of row p | Sign of | Status of row p | +* | (transformed problem) | pi[p] | (original problem) | +* +-----------------------+---------+--------------------+ +* | GLP_BS | + / - | GLP_BS | +* | GLP_NS | + | GLP_NL | +* | GLP_NS | - | GLP_NU | +* +-----------------------+---------+--------------------+ +* +* Value of row multiplier pi[p] in solution to the original problem is +* the same as in solution to the transformed problem. +* +* RECOVERING INTERIOR POINT SOLUTION +* +* Value of row multiplier pi[p] in solution to the original problem is +* the same as in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct make_equality +{ /* row with almost identical bounds */ + int p; + /* row reference number */ +}; + +static int rcv_make_equality(NPP *npp, void *info); + +int npp_make_equality(NPP *npp, NPPROW *p) +{ /* process row with almost identical bounds */ + struct make_equality *info; + double b, eps, nint; + /* the row must be double-sided inequality */ + xassert(p->lb != -DBL_MAX); + xassert(p->ub != +DBL_MAX); + xassert(p->lb < p->ub); + /* check row bounds */ + eps = 1e-9 + 1e-12 * fabs(p->lb); + if (p->ub - p->lb > eps) return 0; + /* row bounds are very close to each other */ + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_make_equality, sizeof(struct make_equality)); + info->p = p->i; + /* compute right-hand side */ + b = 0.5 * (p->ub + p->lb); + nint = floor(b + 0.5); + if (fabs(b - nint) <= eps) b = nint; + /* replace row p by almost equivalent equality constraint */ + p->lb = p->ub = b; + return 1; +} + +int rcv_make_equality(NPP *npp, void *_info) +{ /* recover row with almost identical bounds */ + struct make_equality *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] == GLP_BS) + npp->r_stat[info->p] = GLP_BS; + else if (npp->r_stat[info->p] == GLP_NS) + { if (npp->r_pi[info->p] >= 0.0) + npp->r_stat[info->p] = GLP_NL; + else + npp->r_stat[info->p] = GLP_NU; + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_make_fixed - process column with almost identical bounds +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_make_fixed(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_make_fixed processes column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where -oo < l[q] < u[q] < +oo, i.e. which has both lower and upper +* bounds. +* +* RETURNS +* +* 0 - column bounds have not been changed; +* +* 1 - column has been fixed. +* +* PROBLEM TRANSFORMATION +* +* If bounds of column (1) are very close to each other: +* +* u[q] - l[q] <= eps, (2) +* +* where eps is an absolute tolerance for column value, the column can +* be fixed: +* +* x[q] = s[q], (3) +* +* where s[q] = (l[q] + u[q]) / 2. And if the fixed column value s[q] +* happens to be very close to its nearest integer: +* +* |s[q] - floor(s[q] + 0.5)| <= eps, (4) +* +* it is reasonable to use this nearest integer as the fixed value. +* +* RECOVERING BASIC SOLUTION +* +* In the dual system of the original (as well as transformed) problem +* column q corresponds to the following row: +* +* sum a[i,q] pi[i] + lambda[q] = c[q]. (5) +* i +* +* Since multipliers pi[i] are known for all rows from solution to the +* transformed problem, formula (5) allows computing value of multiplier +* (reduced cost) for column q: +* +* lambda[q] = c[q] - sum a[i,q] pi[i]. (6) +* i +* +* Status of column q in solution to the original problem is determined +* by its status and the sign of its multiplier lambda[q] in solution to +* the transformed problem as follows: +* +* +-----------------------+-----------+--------------------+ +* | Status of column q | Sign of | Status of column q | +* | (transformed problem) | lambda[q] | (original problem) | +* +-----------------------+-----------+--------------------+ +* | GLP_BS | + / - | GLP_BS | +* | GLP_NS | + | GLP_NL | +* | GLP_NS | - | GLP_NU | +* +-----------------------+-----------+--------------------+ +* +* Value of column q in solution to the original problem is the same as +* in solution to the transformed problem. +* +* RECOVERING INTERIOR POINT SOLUTION +* +* Value of column q in solution to the original problem is the same as +* in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct make_fixed +{ /* column with almost identical bounds */ + int q; + /* column reference number */ + double c; + /* objective coefficient at x[q] */ + NPPLFE *ptr; + /* list of non-zero coefficients a[i,q] */ +}; + +static int rcv_make_fixed(NPP *npp, void *info); + +int npp_make_fixed(NPP *npp, NPPCOL *q) +{ /* process column with almost identical bounds */ + struct make_fixed *info; + NPPAIJ *aij; + NPPLFE *lfe; + double s, eps, nint; + /* the column must be double-bounded */ + xassert(q->lb != -DBL_MAX); + xassert(q->ub != +DBL_MAX); + xassert(q->lb < q->ub); + /* check column bounds */ + eps = 1e-9 + 1e-12 * fabs(q->lb); + if (q->ub - q->lb > eps) return 0; + /* column bounds are very close to each other */ + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_make_fixed, sizeof(struct make_fixed)); + info->q = q->j; + info->c = q->coef; + info->ptr = NULL; + /* save column coefficients a[i,q] (needed for basic solution + only) */ + if (npp->sol == GLP_SOL) + { for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = aij->row->i; + lfe->val = aij->val; + lfe->next = info->ptr; + info->ptr = lfe; + } + } + /* compute column fixed value */ + s = 0.5 * (q->ub + q->lb); + nint = floor(s + 0.5); + if (fabs(s - nint) <= eps) s = nint; + /* make column q fixed */ + q->lb = q->ub = s; + return 1; +} + +static int rcv_make_fixed(NPP *npp, void *_info) +{ /* recover column with almost identical bounds */ + struct make_fixed *info = _info; + NPPLFE *lfe; + double lambda; + if (npp->sol == GLP_SOL) + { if (npp->c_stat[info->q] == GLP_BS) + npp->c_stat[info->q] = GLP_BS; + else if (npp->c_stat[info->q] == GLP_NS) + { /* compute multiplier for column q with formula (6) */ + lambda = info->c; + for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) + lambda -= lfe->val * npp->r_pi[lfe->ref]; + /* assign status to non-basic column */ + if (lambda >= 0.0) + npp->c_stat[info->q] = GLP_NL; + else + npp->c_stat[info->q] = GLP_NU; + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp03.c b/resources/3rdparty/glpk-4.53/src/glpnpp03.c new file mode 100644 index 000000000..0c869ee39 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpnpp03.c @@ -0,0 +1,2862 @@ +/* glpnpp03.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpnpp.h" + +/*********************************************************************** +* NAME +* +* npp_empty_row - process empty row +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_empty_row(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_empty_row processes row p, which is empty, i.e. +* coefficients at all columns in this row are zero: +* +* L[p] <= sum 0 x[j] <= U[p], (1) +* +* where L[p] <= U[p]. +* +* RETURNS +* +* 0 - success; +* +* 1 - problem has no primal feasible solution. +* +* PROBLEM TRANSFORMATION +* +* If the following conditions hold: +* +* L[p] <= +eps, U[p] >= -eps, (2) +* +* where eps is an absolute tolerance for row value, the row p is +* redundant. In this case it can be replaced by equivalent redundant +* row, which is free (unbounded), and then removed from the problem. +* Otherwise, the row p is infeasible and, thus, the problem has no +* primal feasible solution. +* +* RECOVERING BASIC SOLUTION +* +* See the routine npp_free_row. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* See the routine npp_free_row. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +int npp_empty_row(NPP *npp, NPPROW *p) +{ /* process empty row */ + double eps = 1e-3; + /* the row must be empty */ + xassert(p->ptr == NULL); + /* check primal feasibility */ + if (p->lb > +eps || p->ub < -eps) + return 1; + /* replace the row by equivalent free (unbounded) row */ + p->lb = -DBL_MAX, p->ub = +DBL_MAX; + /* and process it */ + npp_free_row(npp, p); + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_empty_col - process empty column +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_empty_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_empty_col processes column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] <= u[q], which is empty, i.e. has zero coefficients in +* all constraint rows. +* +* RETURNS +* +* 0 - success; +* +* 1 - problem has no dual feasible solution. +* +* PROBLEM TRANSFORMATION +* +* The row of the dual system corresponding to the empty column is the +* following: +* +* sum 0 pi[i] + lambda[q] = c[q], (2) +* i +* +* from which it follows that: +* +* lambda[q] = c[q]. (3) +* +* If the following condition holds: +* +* c[q] < - eps, (4) +* +* where eps is an absolute tolerance for column multiplier, the lower +* column bound l[q] must be active to provide dual feasibility (note +* that being preprocessed the problem is always minimization). In this +* case the column can be fixed on its lower bound and removed from the +* problem (if the column is integral, its bounds are also assumed to +* be integral). And if the column has no lower bound (l[q] = -oo), the +* problem has no dual feasible solution. +* +* If the following condition holds: +* +* c[q] > + eps, (5) +* +* the upper column bound u[q] must be active to provide dual +* feasibility. In this case the column can be fixed on its upper bound +* and removed from the problem. And if the column has no upper bound +* (u[q] = +oo), the problem has no dual feasible solution. +* +* Finally, if the following condition holds: +* +* - eps <= c[q] <= +eps, (6) +* +* dual feasibility does not depend on a particular value of column q. +* In this case the column can be fixed either on its lower bound (if +* l[q] > -oo) or on its upper bound (if u[q] < +oo) or at zero (if the +* column is unbounded) and then removed from the problem. +* +* RECOVERING BASIC SOLUTION +* +* See the routine npp_fixed_col. Having been recovered the column +* is assigned status GLP_NS. However, if actually it is not fixed +* (l[q] < u[q]), its status should be changed to GLP_NL, GLP_NU, or +* GLP_NF depending on which bound it was fixed on transformation stage. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* See the routine npp_fixed_col. +* +* RECOVERING MIP SOLUTION +* +* See the routine npp_fixed_col. */ + +struct empty_col +{ /* empty column */ + int q; + /* column reference number */ + char stat; + /* status in basic solution */ +}; + +static int rcv_empty_col(NPP *npp, void *info); + +int npp_empty_col(NPP *npp, NPPCOL *q) +{ /* process empty column */ + struct empty_col *info; + double eps = 1e-3; + /* the column must be empty */ + xassert(q->ptr == NULL); + /* check dual feasibility */ + if (q->coef > +eps && q->lb == -DBL_MAX) + return 1; + if (q->coef < -eps && q->ub == +DBL_MAX) + return 1; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_empty_col, sizeof(struct empty_col)); + info->q = q->j; + /* fix the column */ + if (q->lb == -DBL_MAX && q->ub == +DBL_MAX) + { /* free column */ + info->stat = GLP_NF; + q->lb = q->ub = 0.0; + } + else if (q->ub == +DBL_MAX) +lo: { /* column with lower bound */ + info->stat = GLP_NL; + q->ub = q->lb; + } + else if (q->lb == -DBL_MAX) +up: { /* column with upper bound */ + info->stat = GLP_NU; + q->lb = q->ub; + } + else if (q->lb != q->ub) + { /* double-bounded column */ + if (q->coef >= +DBL_EPSILON) goto lo; + if (q->coef <= -DBL_EPSILON) goto up; + if (fabs(q->lb) <= fabs(q->ub)) goto lo; else goto up; + } + else + { /* fixed column */ + info->stat = GLP_NS; + } + /* process fixed column */ + npp_fixed_col(npp, q); + return 0; +} + +static int rcv_empty_col(NPP *npp, void *_info) +{ /* recover empty column */ + struct empty_col *info = _info; + if (npp->sol == GLP_SOL) + npp->c_stat[info->q] = info->stat; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_implied_value - process implied column value +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_implied_value(NPP *npp, NPPCOL *q, double s); +* +* DESCRIPTION +* +* For column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] < u[q], the routine npp_implied_value processes its +* implied value s[q]. If this implied value satisfies to the current +* column bounds and integrality condition, the routine fixes column q +* at the given point. Note that the column is kept in the problem in +* any case. +* +* RETURNS +* +* 0 - column has been fixed; +* +* 1 - implied value violates to current column bounds; +* +* 2 - implied value violates integrality condition. +* +* ALGORITHM +* +* Implied column value s[q] satisfies to the current column bounds if +* the following condition holds: +* +* l[q] - eps <= s[q] <= u[q] + eps, (2) +* +* where eps is an absolute tolerance for column value. If the column +* is integral, the following condition also must hold: +* +* |s[q] - floor(s[q]+0.5)| <= eps, (3) +* +* where floor(s[q]+0.5) is the nearest integer to s[q]. +* +* If both condition (2) and (3) are satisfied, the column can be fixed +* at the value s[q], or, if it is integral, at floor(s[q]+0.5). +* Otherwise, if s[q] violates (2) or (3), the problem has no feasible +* solution. +* +* Note: If s[q] is close to l[q] or u[q], it seems to be reasonable to +* fix the column at its lower or upper bound, resp. rather than at the +* implied value. */ + +int npp_implied_value(NPP *npp, NPPCOL *q, double s) +{ /* process implied column value */ + double eps, nint; + xassert(npp == npp); + /* column must not be fixed */ + xassert(q->lb < q->ub); + /* check integrality */ + if (q->is_int) + { nint = floor(s + 0.5); + if (fabs(s - nint) <= 1e-5) + s = nint; + else + return 2; + } + /* check current column lower bound */ + if (q->lb != -DBL_MAX) + { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->lb)); + if (s < q->lb - eps) return 1; + /* if s[q] is close to l[q], fix column at its lower bound + rather than at the implied value */ + if (s < q->lb + 1e-3 * eps) + { q->ub = q->lb; + return 0; + } + } + /* check current column upper bound */ + if (q->ub != +DBL_MAX) + { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->ub)); + if (s > q->ub + eps) return 1; + /* if s[q] is close to u[q], fix column at its upper bound + rather than at the implied value */ + if (s > q->ub - 1e-3 * eps) + { q->lb = q->ub; + return 0; + } + } + /* fix column at the implied value */ + q->lb = q->ub = s; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_eq_singlet - process row singleton (equality constraint) +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_eq_singlet(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_eq_singlet processes row p, which is equiality +* constraint having the only non-zero coefficient: +* +* a[p,q] x[q] = b. (1) +* +* RETURNS +* +* 0 - success; +* +* 1 - problem has no primal feasible solution; +* +* 2 - problem has no integer feasible solution. +* +* PROBLEM TRANSFORMATION +* +* The equality constraint defines implied value of column q: +* +* x[q] = s[q] = b / a[p,q]. (2) +* +* If the implied value s[q] satisfies to the column bounds (see the +* routine npp_implied_value), the column can be fixed at s[q] and +* removed from the problem. In this case row p becomes redundant, so +* it can be replaced by equivalent free row and also removed from the +* problem. +* +* Note that the routine removes from the problem only row p. Column q +* becomes fixed, however, it is kept in the problem. +* +* RECOVERING BASIC SOLUTION +* +* In solution to the original problem row p is assigned status GLP_NS +* (active equality constraint), and column q is assigned status GLP_BS +* (basic column). +* +* Multiplier for row p can be computed as follows. In the dual system +* of the original problem column q corresponds to the following row: +* +* sum a[i,q] pi[i] + lambda[q] = c[q] ==> +* i +* +* sum a[i,q] pi[i] + a[p,q] pi[p] + lambda[q] = c[q]. +* i!=p +* +* Therefore: +* +* 1 +* pi[p] = ------ (c[q] - lambda[q] - sum a[i,q] pi[i]), (3) +* a[p,q] i!=q +* +* where lambda[q] = 0 (since column[q] is basic), and pi[i] for all +* i != p are known in solution to the transformed problem. +* +* Value of column q in solution to the original problem is assigned +* its implied value s[q]. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Multiplier for row p is computed with formula (3). Value of column +* q is assigned its implied value s[q]. +* +* RECOVERING MIP SOLUTION +* +* Value of column q is assigned its implied value s[q]. */ + +struct eq_singlet +{ /* row singleton (equality constraint) */ + int p; + /* row reference number */ + int q; + /* column reference number */ + double apq; + /* constraint coefficient a[p,q] */ + double c; + /* objective coefficient at x[q] */ + NPPLFE *ptr; + /* list of non-zero coefficients a[i,q], i != p */ +}; + +static int rcv_eq_singlet(NPP *npp, void *info); + +int npp_eq_singlet(NPP *npp, NPPROW *p) +{ /* process row singleton (equality constraint) */ + struct eq_singlet *info; + NPPCOL *q; + NPPAIJ *aij; + NPPLFE *lfe; + int ret; + double s; + /* the row must be singleton equality constraint */ + xassert(p->lb == p->ub); + xassert(p->ptr != NULL && p->ptr->r_next == NULL); + /* compute and process implied column value */ + aij = p->ptr; + q = aij->col; + s = p->lb / aij->val; + ret = npp_implied_value(npp, q, s); + xassert(0 <= ret && ret <= 2); + if (ret != 0) return ret; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_eq_singlet, sizeof(struct eq_singlet)); + info->p = p->i; + info->q = q->j; + info->apq = aij->val; + info->c = q->coef; + info->ptr = NULL; + /* save column coefficients a[i,q], i != p (not needed for MIP + solution) */ + if (npp->sol != GLP_MIP) + { for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { if (aij->row == p) continue; /* skip a[p,q] */ + lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = aij->row->i; + lfe->val = aij->val; + lfe->next = info->ptr; + info->ptr = lfe; + } + } + /* remove the row from the problem */ + npp_del_row(npp, p); + return 0; +} + +static int rcv_eq_singlet(NPP *npp, void *_info) +{ /* recover row singleton (equality constraint) */ + struct eq_singlet *info = _info; + NPPLFE *lfe; + double temp; + if (npp->sol == GLP_SOL) + { /* column q must be already recovered as GLP_NS */ + if (npp->c_stat[info->q] != GLP_NS) + { npp_error(); + return 1; + } + npp->r_stat[info->p] = GLP_NS; + npp->c_stat[info->q] = GLP_BS; + } + if (npp->sol != GLP_MIP) + { /* compute multiplier for row p with formula (3) */ + temp = info->c; + for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) + temp -= lfe->val * npp->r_pi[lfe->ref]; + npp->r_pi[info->p] = temp / info->apq; + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_implied_lower - process implied column lower bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_implied_lower(NPP *npp, NPPCOL *q, double l); +* +* DESCRIPTION +* +* For column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] < u[q], the routine npp_implied_lower processes its +* implied lower bound l'[q]. As the result the current column lower +* bound may increase. Note that the column is kept in the problem in +* any case. +* +* RETURNS +* +* 0 - current column lower bound has not changed; +* +* 1 - current column lower bound has changed, but not significantly; +* +* 2 - current column lower bound has significantly changed; +* +* 3 - column has been fixed on its upper bound; +* +* 4 - implied lower bound violates current column upper bound. +* +* ALGORITHM +* +* If column q is integral, before processing its implied lower bound +* should be rounded up: +* +* ( floor(l'[q]+0.5), if |l'[q] - floor(l'[q]+0.5)| <= eps +* l'[q] := < (2) +* ( ceil(l'[q]), otherwise +* +* where floor(l'[q]+0.5) is the nearest integer to l'[q], ceil(l'[q]) +* is smallest integer not less than l'[q], and eps is an absolute +* tolerance for column value. +* +* Processing implied column lower bound l'[q] includes the following +* cases: +* +* 1) if l'[q] < l[q] + eps, implied lower bound is redundant; +* +* 2) if l[q] + eps <= l[q] <= u[q] + eps, current column lower bound +* l[q] can be strengthened by replacing it with l'[q]. If in this +* case new column lower bound becomes close to current column upper +* bound u[q], the column can be fixed on its upper bound; +* +* 3) if l'[q] > u[q] + eps, implied lower bound violates current +* column upper bound u[q], in which case the problem has no primal +* feasible solution. */ + +int npp_implied_lower(NPP *npp, NPPCOL *q, double l) +{ /* process implied column lower bound */ + int ret; + double eps, nint; + xassert(npp == npp); + /* column must not be fixed */ + xassert(q->lb < q->ub); + /* implied lower bound must be finite */ + xassert(l != -DBL_MAX); + /* if column is integral, round up l'[q] */ + if (q->is_int) + { nint = floor(l + 0.5); + if (fabs(l - nint) <= 1e-5) + l = nint; + else + l = ceil(l); + } + /* check current column lower bound */ + if (q->lb != -DBL_MAX) + { eps = (q->is_int ? 1e-3 : 1e-3 + 1e-6 * fabs(q->lb)); + if (l < q->lb + eps) + { ret = 0; /* redundant */ + goto done; + } + } + /* check current column upper bound */ + if (q->ub != +DBL_MAX) + { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->ub)); + if (l > q->ub + eps) + { ret = 4; /* infeasible */ + goto done; + } + /* if l'[q] is close to u[q], fix column at its upper bound */ + if (l > q->ub - 1e-3 * eps) + { q->lb = q->ub; + ret = 3; /* fixed */ + goto done; + } + } + /* check if column lower bound changes significantly */ + if (q->lb == -DBL_MAX) + ret = 2; /* significantly */ + else if (q->is_int && l > q->lb + 0.5) + ret = 2; /* significantly */ + else if (l > q->lb + 0.30 * (1.0 + fabs(q->lb))) + ret = 2; /* significantly */ + else + ret = 1; /* not significantly */ + /* set new column lower bound */ + q->lb = l; +done: return ret; +} + +/*********************************************************************** +* NAME +* +* npp_implied_upper - process implied column upper bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_implied_upper(NPP *npp, NPPCOL *q, double u); +* +* DESCRIPTION +* +* For column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] < u[q], the routine npp_implied_upper processes its +* implied upper bound u'[q]. As the result the current column upper +* bound may decrease. Note that the column is kept in the problem in +* any case. +* +* RETURNS +* +* 0 - current column upper bound has not changed; +* +* 1 - current column upper bound has changed, but not significantly; +* +* 2 - current column upper bound has significantly changed; +* +* 3 - column has been fixed on its lower bound; +* +* 4 - implied upper bound violates current column lower bound. +* +* ALGORITHM +* +* If column q is integral, before processing its implied upper bound +* should be rounded down: +* +* ( floor(u'[q]+0.5), if |u'[q] - floor(l'[q]+0.5)| <= eps +* u'[q] := < (2) +* ( floor(l'[q]), otherwise +* +* where floor(u'[q]+0.5) is the nearest integer to u'[q], +* floor(u'[q]) is largest integer not greater than u'[q], and eps is +* an absolute tolerance for column value. +* +* Processing implied column upper bound u'[q] includes the following +* cases: +* +* 1) if u'[q] > u[q] - eps, implied upper bound is redundant; +* +* 2) if l[q] - eps <= u[q] <= u[q] - eps, current column upper bound +* u[q] can be strengthened by replacing it with u'[q]. If in this +* case new column upper bound becomes close to current column lower +* bound, the column can be fixed on its lower bound; +* +* 3) if u'[q] < l[q] - eps, implied upper bound violates current +* column lower bound l[q], in which case the problem has no primal +* feasible solution. */ + +int npp_implied_upper(NPP *npp, NPPCOL *q, double u) +{ int ret; + double eps, nint; + xassert(npp == npp); + /* column must not be fixed */ + xassert(q->lb < q->ub); + /* implied upper bound must be finite */ + xassert(u != +DBL_MAX); + /* if column is integral, round down u'[q] */ + if (q->is_int) + { nint = floor(u + 0.5); + if (fabs(u - nint) <= 1e-5) + u = nint; + else + u = floor(u); + } + /* check current column upper bound */ + if (q->ub != +DBL_MAX) + { eps = (q->is_int ? 1e-3 : 1e-3 + 1e-6 * fabs(q->ub)); + if (u > q->ub - eps) + { ret = 0; /* redundant */ + goto done; + } + } + /* check current column lower bound */ + if (q->lb != -DBL_MAX) + { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->lb)); + if (u < q->lb - eps) + { ret = 4; /* infeasible */ + goto done; + } + /* if u'[q] is close to l[q], fix column at its lower bound */ + if (u < q->lb + 1e-3 * eps) + { q->ub = q->lb; + ret = 3; /* fixed */ + goto done; + } + } + /* check if column upper bound changes significantly */ + if (q->ub == +DBL_MAX) + ret = 2; /* significantly */ + else if (q->is_int && u < q->ub - 0.5) + ret = 2; /* significantly */ + else if (u < q->ub - 0.30 * (1.0 + fabs(q->ub))) + ret = 2; /* significantly */ + else + ret = 1; /* not significantly */ + /* set new column upper bound */ + q->ub = u; +done: return ret; +} + +/*********************************************************************** +* NAME +* +* npp_ineq_singlet - process row singleton (inequality constraint) +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_ineq_singlet(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_ineq_singlet processes row p, which is inequality +* constraint having the only non-zero coefficient: +* +* L[p] <= a[p,q] * x[q] <= U[p], (1) +* +* where L[p] < U[p], L[p] > -oo and/or U[p] < +oo. +* +* RETURNS +* +* 0 - current column bounds have not changed; +* +* 1 - current column bounds have changed, but not significantly; +* +* 2 - current column bounds have significantly changed; +* +* 3 - column has been fixed on its lower or upper bound; +* +* 4 - problem has no primal feasible solution. +* +* PROBLEM TRANSFORMATION +* +* Inequality constraint (1) defines implied bounds of column q: +* +* ( L[p] / a[p,q], if a[p,q] > 0 +* l'[q] = < (2) +* ( U[p] / a[p,q], if a[p,q] < 0 +* +* ( U[p] / a[p,q], if a[p,q] > 0 +* u'[q] = < (3) +* ( L[p] / a[p,q], if a[p,q] < 0 +* +* If these implied bounds do not violate current bounds of column q: +* +* l[q] <= x[q] <= u[q], (4) +* +* they can be used to strengthen the current column bounds: +* +* l[q] := max(l[q], l'[q]), (5) +* +* u[q] := min(u[q], u'[q]). (6) +* +* (See the routines npp_implied_lower and npp_implied_upper.) +* +* Once bounds of row p (1) have been carried over column q, the row +* becomes redundant, so it can be replaced by equivalent free row and +* removed from the problem. +* +* Note that the routine removes from the problem only row p. Column q, +* even it has been fixed, is kept in the problem. +* +* RECOVERING BASIC SOLUTION +* +* Note that the row in the dual system corresponding to column q is +* the following: +* +* sum a[i,q] pi[i] + lambda[q] = c[q] ==> +* i +* (7) +* sum a[i,q] pi[i] + a[p,q] pi[p] + lambda[q] = c[q], +* i!=p +* +* where pi[i] for all i != p are known in solution to the transformed +* problem. Row p does not exist in the transformed problem, so it has +* zero multiplier there. This allows computing multiplier for column q +* in solution to the transformed problem: +* +* lambda~[q] = c[q] - sum a[i,q] pi[i]. (8) +* i!=p +* +* Let in solution to the transformed problem column q be non-basic +* with lower bound active (GLP_NL, lambda~[q] >= 0), and this lower +* bound be implied one l'[q]. From the original problem's standpoint +* this then means that actually the original column lower bound l[q] +* is inactive, and active is that row bound L[p] or U[p] that defines +* the implied bound l'[q] (2). In this case in solution to the +* original problem column q is assigned status GLP_BS while row p is +* assigned status GLP_NL (if a[p,q] > 0) or GLP_NU (if a[p,q] < 0). +* Since now column q is basic, its multiplier lambda[q] is zero. This +* allows using (7) and (8) to find multiplier for row p in solution to +* the original problem: +* +* 1 +* pi[p] = ------ (c[q] - sum a[i,q] pi[i]) = lambda~[q] / a[p,q] (9) +* a[p,q] i!=p +* +* Now let in solution to the transformed problem column q be non-basic +* with upper bound active (GLP_NU, lambda~[q] <= 0), and this upper +* bound be implied one u'[q]. As in the previous case this then means +* that from the original problem's standpoint actually the original +* column upper bound u[q] is inactive, and active is that row bound +* L[p] or U[p] that defines the implied bound u'[q] (3). In this case +* in solution to the original problem column q is assigned status +* GLP_BS, row p is assigned status GLP_NU (if a[p,q] > 0) or GLP_NL +* (if a[p,q] < 0), and its multiplier is computed with formula (9). +* +* Strengthening bounds of column q according to (5) and (6) may make +* it fixed. Thus, if in solution to the transformed problem column q is +* non-basic and fixed (GLP_NS), we can suppose that if lambda~[q] > 0, +* column q has active lower bound (GLP_NL), and if lambda~[q] < 0, +* column q has active upper bound (GLP_NU), reducing this case to two +* previous ones. If, however, lambda~[q] is close to zero or +* corresponding bound of row p does not exist (this may happen if +* lambda~[q] has wrong sign due to round-off errors, in which case it +* is expected to be close to zero, since solution is assumed to be dual +* feasible), column q can be assigned status GLP_BS (basic), and row p +* can be made active on its existing bound. In the latter case row +* multiplier pi[p] computed with formula (9) will be also close to +* zero, and dual feasibility will be kept. +* +* In all other cases, namely, if in solution to the transformed +* problem column q is basic (GLP_BS), or non-basic with original lower +* bound l[q] active (GLP_NL), or non-basic with original upper bound +* u[q] active (GLP_NU), constraint (1) is inactive. So in solution to +* the original problem status of column q remains unchanged, row p is +* assigned status GLP_BS, and its multiplier pi[p] is assigned zero +* value. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* First, value of multiplier for column q in solution to the original +* problem is computed with formula (8). If lambda~[q] > 0 and column q +* has implied lower bound, or if lambda~[q] < 0 and column q has +* implied upper bound, this means that from the original problem's +* standpoint actually row p has corresponding active bound, in which +* case its multiplier pi[p] is computed with formula (9). In other +* cases, when the sign of lambda~[q] corresponds to original bound of +* column q, or when lambda~[q] =~ 0, value of row multiplier pi[p] is +* assigned zero value. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct ineq_singlet +{ /* row singleton (inequality constraint) */ + int p; + /* row reference number */ + int q; + /* column reference number */ + double apq; + /* constraint coefficient a[p,q] */ + double c; + /* objective coefficient at x[q] */ + double lb; + /* row lower bound */ + double ub; + /* row upper bound */ + char lb_changed; + /* this flag is set if column lower bound was changed */ + char ub_changed; + /* this flag is set if column upper bound was changed */ + NPPLFE *ptr; + /* list of non-zero coefficients a[i,q], i != p */ +}; + +static int rcv_ineq_singlet(NPP *npp, void *info); + +int npp_ineq_singlet(NPP *npp, NPPROW *p) +{ /* process row singleton (inequality constraint) */ + struct ineq_singlet *info; + NPPCOL *q; + NPPAIJ *apq, *aij; + NPPLFE *lfe; + int lb_changed, ub_changed; + double ll, uu; + /* the row must be singleton inequality constraint */ + xassert(p->lb != -DBL_MAX || p->ub != +DBL_MAX); + xassert(p->lb < p->ub); + xassert(p->ptr != NULL && p->ptr->r_next == NULL); + /* compute implied column bounds */ + apq = p->ptr; + q = apq->col; + xassert(q->lb < q->ub); + if (apq->val > 0.0) + { ll = (p->lb == -DBL_MAX ? -DBL_MAX : p->lb / apq->val); + uu = (p->ub == +DBL_MAX ? +DBL_MAX : p->ub / apq->val); + } + else + { ll = (p->ub == +DBL_MAX ? -DBL_MAX : p->ub / apq->val); + uu = (p->lb == -DBL_MAX ? +DBL_MAX : p->lb / apq->val); + } + /* process implied column lower bound */ + if (ll == -DBL_MAX) + lb_changed = 0; + else + { lb_changed = npp_implied_lower(npp, q, ll); + xassert(0 <= lb_changed && lb_changed <= 4); + if (lb_changed == 4) return 4; /* infeasible */ + } + /* process implied column upper bound */ + if (uu == +DBL_MAX) + ub_changed = 0; + else if (lb_changed == 3) + { /* column was fixed on its upper bound due to l'[q] = u[q] */ + /* note that L[p] < U[p], so l'[q] = u[q] < u'[q] */ + ub_changed = 0; + } + else + { ub_changed = npp_implied_upper(npp, q, uu); + xassert(0 <= ub_changed && ub_changed <= 4); + if (ub_changed == 4) return 4; /* infeasible */ + } + /* if neither lower nor upper column bound was changed, the row + is originally redundant and can be replaced by free row */ + if (!lb_changed && !ub_changed) + { p->lb = -DBL_MAX, p->ub = +DBL_MAX; + npp_free_row(npp, p); + return 0; + } + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_ineq_singlet, sizeof(struct ineq_singlet)); + info->p = p->i; + info->q = q->j; + info->apq = apq->val; + info->c = q->coef; + info->lb = p->lb; + info->ub = p->ub; + info->lb_changed = (char)lb_changed; + info->ub_changed = (char)ub_changed; + info->ptr = NULL; + /* save column coefficients a[i,q], i != p (not needed for MIP + solution) */ + if (npp->sol != GLP_MIP) + { for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { if (aij == apq) continue; /* skip a[p,q] */ + lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = aij->row->i; + lfe->val = aij->val; + lfe->next = info->ptr; + info->ptr = lfe; + } + } + /* remove the row from the problem */ + npp_del_row(npp, p); + return lb_changed >= ub_changed ? lb_changed : ub_changed; +} + +static int rcv_ineq_singlet(NPP *npp, void *_info) +{ /* recover row singleton (inequality constraint) */ + struct ineq_singlet *info = _info; + NPPLFE *lfe; + double lambda; + if (npp->sol == GLP_MIP) goto done; + /* compute lambda~[q] in solution to the transformed problem + with formula (8) */ + lambda = info->c; + for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) + lambda -= lfe->val * npp->r_pi[lfe->ref]; + if (npp->sol == GLP_SOL) + { /* recover basic solution */ + if (npp->c_stat[info->q] == GLP_BS) + { /* column q is basic, so row p is inactive */ + npp->r_stat[info->p] = GLP_BS; + npp->r_pi[info->p] = 0.0; + } + else if (npp->c_stat[info->q] == GLP_NL) +nl: { /* column q is non-basic with lower bound active */ + if (info->lb_changed) + { /* it is implied bound, so actually row p is active + while column q is basic */ + npp->r_stat[info->p] = + (char)(info->apq > 0.0 ? GLP_NL : GLP_NU); + npp->c_stat[info->q] = GLP_BS; + npp->r_pi[info->p] = lambda / info->apq; + } + else + { /* it is original bound, so row p is inactive */ + npp->r_stat[info->p] = GLP_BS; + npp->r_pi[info->p] = 0.0; + } + } + else if (npp->c_stat[info->q] == GLP_NU) +nu: { /* column q is non-basic with upper bound active */ + if (info->ub_changed) + { /* it is implied bound, so actually row p is active + while column q is basic */ + npp->r_stat[info->p] = + (char)(info->apq > 0.0 ? GLP_NU : GLP_NL); + npp->c_stat[info->q] = GLP_BS; + npp->r_pi[info->p] = lambda / info->apq; + } + else + { /* it is original bound, so row p is inactive */ + npp->r_stat[info->p] = GLP_BS; + npp->r_pi[info->p] = 0.0; + } + } + else if (npp->c_stat[info->q] == GLP_NS) + { /* column q is non-basic and fixed; note, however, that in + in the original problem it is non-fixed */ + if (lambda > +1e-7) + { if (info->apq > 0.0 && info->lb != -DBL_MAX || + info->apq < 0.0 && info->ub != +DBL_MAX || + !info->lb_changed) + { /* either corresponding bound of row p exists or + column q remains non-basic with its original lower + bound active */ + npp->c_stat[info->q] = GLP_NL; + goto nl; + } + } + if (lambda < -1e-7) + { if (info->apq > 0.0 && info->ub != +DBL_MAX || + info->apq < 0.0 && info->lb != -DBL_MAX || + !info->ub_changed) + { /* either corresponding bound of row p exists or + column q remains non-basic with its original upper + bound active */ + npp->c_stat[info->q] = GLP_NU; + goto nu; + } + } + /* either lambda~[q] is close to zero, or corresponding + bound of row p does not exist, because lambda~[q] has + wrong sign due to round-off errors; in the latter case + lambda~[q] is also assumed to be close to zero; so, we + can make row p active on its existing bound and column q + basic; pi[p] will have wrong sign, but it also will be + close to zero (rarus casus of dual degeneracy) */ + if (info->lb != -DBL_MAX && info->ub == +DBL_MAX) + { /* row lower bound exists, but upper bound doesn't */ + npp->r_stat[info->p] = GLP_NL; + } + else if (info->lb == -DBL_MAX && info->ub != +DBL_MAX) + { /* row upper bound exists, but lower bound doesn't */ + npp->r_stat[info->p] = GLP_NU; + } + else if (info->lb != -DBL_MAX && info->ub != +DBL_MAX) + { /* both row lower and upper bounds exist */ + /* to choose proper active row bound we should not use + lambda~[q], because its value being close to zero is + unreliable; so we choose that bound which provides + primal feasibility for original constraint (1) */ + if (info->apq * npp->c_value[info->q] <= + 0.5 * (info->lb + info->ub)) + npp->r_stat[info->p] = GLP_NL; + else + npp->r_stat[info->p] = GLP_NU; + } + else + { npp_error(); + return 1; + } + npp->c_stat[info->q] = GLP_BS; + npp->r_pi[info->p] = lambda / info->apq; + } + else + { npp_error(); + return 1; + } + } + if (npp->sol == GLP_IPT) + { /* recover interior-point solution */ + if (lambda > +DBL_EPSILON && info->lb_changed || + lambda < -DBL_EPSILON && info->ub_changed) + { /* actually row p has corresponding active bound */ + npp->r_pi[info->p] = lambda / info->apq; + } + else + { /* either bounds of column q are both inactive or its + original bound is active */ + npp->r_pi[info->p] = 0.0; + } + } +done: return 0; +} + +/*********************************************************************** +* NAME +* +* npp_implied_slack - process column singleton (implied slack variable) +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_implied_slack(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_implied_slack processes column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] < u[q], having the only non-zero coefficient in row p, +* which is equality constraint: +* +* sum a[p,j] x[j] + a[p,q] x[q] = b. (2) +* j!=q +* +* PROBLEM TRANSFORMATION +* +* (If x[q] is integral, this transformation must not be used.) +* +* The term a[p,q] x[q] in constraint (2) can be considered as a slack +* variable that allows to carry bounds of column q over row p and then +* remove column q from the problem. +* +* Constraint (2) can be written as follows: +* +* sum a[p,j] x[j] = b - a[p,q] x[q]. (3) +* j!=q +* +* According to (1) constraint (3) is equivalent to the following +* inequality constraint: +* +* L[p] <= sum a[p,j] x[j] <= U[p], (4) +* j!=q +* +* where +* +* ( b - a[p,q] u[q], if a[p,q] > 0 +* L[p] = < (5) +* ( b - a[p,q] l[q], if a[p,q] < 0 +* +* ( b - a[p,q] l[q], if a[p,q] > 0 +* U[p] = < (6) +* ( b - a[p,q] u[q], if a[p,q] < 0 +* +* From (2) it follows that: +* +* 1 +* x[q] = ------ (b - sum a[p,j] x[j]). (7) +* a[p,q] j!=q +* +* In order to eliminate x[q] from the objective row we substitute it +* from (6) to that row: +* +* z = sum c[j] x[j] + c[q] x[q] + c[0] = +* j!=q +* 1 +* = sum c[j] x[j] + c[q] [------ (b - sum a[p,j] x[j])] + c0 = +* j!=q a[p,q] j!=q +* +* = sum c~[j] x[j] + c~[0], +* j!=q +* a[p,j] b +* c~[j] = c[j] - c[q] ------, c~0 = c0 - c[q] ------ (8) +* a[p,q] a[p,q] +* +* are values of objective coefficients and constant term, resp., in +* the transformed problem. +* +* Note that column q is column singleton, so in the dual system of the +* original problem it corresponds to the following row singleton: +* +* a[p,q] pi[p] + lambda[q] = c[q]. (9) +* +* In the transformed problem row (9) would be the following: +* +* a[p,q] pi~[p] + lambda[q] = c~[q] = 0. (10) +* +* Subtracting (10) from (9) we have: +* +* a[p,q] (pi[p] - pi~[p]) = c[q] +* +* that gives the following formula to compute multiplier for row p in +* solution to the original problem using its value in solution to the +* transformed problem: +* +* pi[p] = pi~[p] + c[q] / a[p,q]. (11) +* +* RECOVERING BASIC SOLUTION +* +* Status of column q in solution to the original problem is defined +* by status of row p in solution to the transformed problem and the +* sign of coefficient a[p,q] in the original inequality constraint (2) +* as follows: +* +* +-----------------------+---------+--------------------+ +* | Status of row p | Sign of | Status of column q | +* | (transformed problem) | a[p,q] | (original problem) | +* +-----------------------+---------+--------------------+ +* | GLP_BS | + / - | GLP_BS | +* | GLP_NL | + | GLP_NU | +* | GLP_NL | - | GLP_NL | +* | GLP_NU | + | GLP_NL | +* | GLP_NU | - | GLP_NU | +* | GLP_NF | + / - | GLP_NF | +* +-----------------------+---------+--------------------+ +* +* Value of column q is computed with formula (7). Since originally row +* p is equality constraint, its status is assigned GLP_NS, and value of +* its multiplier pi[p] is computed with formula (11). +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q is computed with formula (7). Row multiplier value +* pi[p] is computed with formula (11). +* +* RECOVERING MIP SOLUTION +* +* Value of column q is computed with formula (7). */ + +struct implied_slack +{ /* column singleton (implied slack variable) */ + int p; + /* row reference number */ + int q; + /* column reference number */ + double apq; + /* constraint coefficient a[p,q] */ + double b; + /* right-hand side of original equality constraint */ + double c; + /* original objective coefficient at x[q] */ + NPPLFE *ptr; + /* list of non-zero coefficients a[p,j], j != q */ +}; + +static int rcv_implied_slack(NPP *npp, void *info); + +void npp_implied_slack(NPP *npp, NPPCOL *q) +{ /* process column singleton (implied slack variable) */ + struct implied_slack *info; + NPPROW *p; + NPPAIJ *aij; + NPPLFE *lfe; + /* the column must be non-integral non-fixed singleton */ + xassert(!q->is_int); + xassert(q->lb < q->ub); + xassert(q->ptr != NULL && q->ptr->c_next == NULL); + /* corresponding row must be equality constraint */ + aij = q->ptr; + p = aij->row; + xassert(p->lb == p->ub); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_implied_slack, sizeof(struct implied_slack)); + info->p = p->i; + info->q = q->j; + info->apq = aij->val; + info->b = p->lb; + info->c = q->coef; + info->ptr = NULL; + /* save row coefficients a[p,j], j != q, and substitute x[q] + into the objective row */ + for (aij = p->ptr; aij != NULL; aij = aij->r_next) + { if (aij->col == q) continue; /* skip a[p,q] */ + lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = aij->col->j; + lfe->val = aij->val; + lfe->next = info->ptr; + info->ptr = lfe; + aij->col->coef -= info->c * (aij->val / info->apq); + } + npp->c0 += info->c * (info->b / info->apq); + /* compute new row bounds */ + if (info->apq > 0.0) + { p->lb = (q->ub == +DBL_MAX ? + -DBL_MAX : info->b - info->apq * q->ub); + p->ub = (q->lb == -DBL_MAX ? + +DBL_MAX : info->b - info->apq * q->lb); + } + else + { p->lb = (q->lb == -DBL_MAX ? + -DBL_MAX : info->b - info->apq * q->lb); + p->ub = (q->ub == +DBL_MAX ? + +DBL_MAX : info->b - info->apq * q->ub); + } + /* remove the column from the problem */ + npp_del_col(npp, q); + return; +} + +static int rcv_implied_slack(NPP *npp, void *_info) +{ /* recover column singleton (implied slack variable) */ + struct implied_slack *info = _info; + NPPLFE *lfe; + double temp; + if (npp->sol == GLP_SOL) + { /* assign statuses to row p and column q */ + if (npp->r_stat[info->p] == GLP_BS || + npp->r_stat[info->p] == GLP_NF) + npp->c_stat[info->q] = npp->r_stat[info->p]; + else if (npp->r_stat[info->p] == GLP_NL) + npp->c_stat[info->q] = + (char)(info->apq > 0.0 ? GLP_NU : GLP_NL); + else if (npp->r_stat[info->p] == GLP_NU) + npp->c_stat[info->q] = + (char)(info->apq > 0.0 ? GLP_NL : GLP_NU); + else + { npp_error(); + return 1; + } + npp->r_stat[info->p] = GLP_NS; + } + if (npp->sol != GLP_MIP) + { /* compute multiplier for row p */ + npp->r_pi[info->p] += info->c / info->apq; + } + /* compute value of column q */ + temp = info->b; + for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) + temp -= lfe->val * npp->c_value[lfe->ref]; + npp->c_value[info->q] = temp / info->apq; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_implied_free - process column singleton (implied free variable) +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_implied_free(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_implied_free processes column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* having non-zero coefficient in the only row p, which is inequality +* constraint: +* +* L[p] <= sum a[p,j] x[j] + a[p,q] x[q] <= U[p], (2) +* j!=q +* +* where l[q] < u[q], L[p] < U[p], L[p] > -oo and/or U[p] < +oo. +* +* RETURNS +* +* 0 - success; +* +* 1 - column lower and/or upper bound(s) can be active; +* +* 2 - problem has no dual feasible solution. +* +* PROBLEM TRANSFORMATION +* +* Constraint (2) can be written as follows: +* +* L[p] - sum a[p,j] x[j] <= a[p,q] x[q] <= U[p] - sum a[p,j] x[j], +* j!=q j!=q +* +* from which it follows that: +* +* alfa <= a[p,q] x[q] <= beta, (3) +* +* where +* +* alfa = inf(L[p] - sum a[p,j] x[j]) = +* j!=q +* +* = L[p] - sup sum a[p,j] x[j] = (4) +* j!=q +* +* = L[p] - sum a[p,j] u[j] - sum a[p,j] l[j], +* j in Jp j in Jn +* +* beta = sup(L[p] - sum a[p,j] x[j]) = +* j!=q +* +* = L[p] - inf sum a[p,j] x[j] = (5) +* j!=q +* +* = L[p] - sum a[p,j] l[j] - sum a[p,j] u[j], +* j in Jp j in Jn +* +* Jp = {j != q: a[p,j] > 0}, Jn = {j != q: a[p,j] < 0}. (6) +* +* Inequality (3) defines implied bounds of variable x[q]: +* +* l'[q] <= x[q] <= u'[q], (7) +* +* where +* +* ( alfa / a[p,q], if a[p,q] > 0 +* l'[q] = < (8a) +* ( beta / a[p,q], if a[p,q] < 0 +* +* ( beta / a[p,q], if a[p,q] > 0 +* u'[q] = < (8b) +* ( alfa / a[p,q], if a[p,q] < 0 +* +* Thus, if l'[q] > l[q] - eps and u'[q] < u[q] + eps, where eps is +* an absolute tolerance for column value, column bounds (1) cannot be +* active, in which case column q can be replaced by equivalent free +* (unbounded) column. +* +* Note that column q is column singleton, so in the dual system of the +* original problem it corresponds to the following row singleton: +* +* a[p,q] pi[p] + lambda[q] = c[q], (9) +* +* from which it follows that: +* +* pi[p] = (c[q] - lambda[q]) / a[p,q]. (10) +* +* Let x[q] be implied free (unbounded) variable. Then column q can be +* only basic, so its multiplier lambda[q] is equal to zero, and from +* (10) we have: +* +* pi[p] = c[q] / a[p,q]. (11) +* +* There are possible three cases: +* +* 1) pi[p] < -eps, where eps is an absolute tolerance for row +* multiplier. In this case, to provide dual feasibility of the +* original problem, row p must be active on its lower bound, and +* if its lower bound does not exist (L[p] = -oo), the problem has +* no dual feasible solution; +* +* 2) pi[p] > +eps. In this case row p must be active on its upper +* bound, and if its upper bound does not exist (U[p] = +oo), the +* problem has no dual feasible solution; +* +* 3) -eps <= pi[p] <= +eps. In this case any (either lower or upper) +* bound of row p can be active, because this does not affect dual +* feasibility. +* +* Thus, in all three cases original inequality constraint (2) can be +* replaced by equality constraint, where the right-hand side is either +* lower or upper bound of row p, and bounds of column q can be removed +* that makes it free (unbounded). (May note that this transformation +* can be followed by transformation "Column singleton (implied slack +* variable)" performed by the routine npp_implied_slack.) +* +* RECOVERING BASIC SOLUTION +* +* Status of row p in solution to the original problem is determined +* by its status in solution to the transformed problem and its bound, +* which was choosen to be active: +* +* +-----------------------+--------+--------------------+ +* | Status of row p | Active | Status of row p | +* | (transformed problem) | bound | (original problem) | +* +-----------------------+--------+--------------------+ +* | GLP_BS | L[p] | GLP_BS | +* | GLP_BS | U[p] | GLP_BS | +* | GLP_NS | L[p] | GLP_NL | +* | GLP_NS | U[p] | GLP_NU | +* +-----------------------+--------+--------------------+ +* +* Value of row multiplier pi[p] (as well as value of column q) in +* solution to the original problem is the same as in solution to the +* transformed problem. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of row multiplier pi[p] in solution to the original problem is +* the same as in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct implied_free +{ /* column singleton (implied free variable) */ + int p; + /* row reference number */ + char stat; + /* row status: + GLP_NL - active constraint on lower bound + GLP_NU - active constraint on upper bound */ +}; + +static int rcv_implied_free(NPP *npp, void *info); + +int npp_implied_free(NPP *npp, NPPCOL *q) +{ /* process column singleton (implied free variable) */ + struct implied_free *info; + NPPROW *p; + NPPAIJ *apq, *aij; + double alfa, beta, l, u, pi, eps; + /* the column must be non-fixed singleton */ + xassert(q->lb < q->ub); + xassert(q->ptr != NULL && q->ptr->c_next == NULL); + /* corresponding row must be inequality constraint */ + apq = q->ptr; + p = apq->row; + xassert(p->lb != -DBL_MAX || p->ub != +DBL_MAX); + xassert(p->lb < p->ub); + /* compute alfa */ + alfa = p->lb; + if (alfa != -DBL_MAX) + { for (aij = p->ptr; aij != NULL; aij = aij->r_next) + { if (aij == apq) continue; /* skip a[p,q] */ + if (aij->val > 0.0) + { if (aij->col->ub == +DBL_MAX) + { alfa = -DBL_MAX; + break; + } + alfa -= aij->val * aij->col->ub; + } + else /* < 0.0 */ + { if (aij->col->lb == -DBL_MAX) + { alfa = -DBL_MAX; + break; + } + alfa -= aij->val * aij->col->lb; + } + } + } + /* compute beta */ + beta = p->ub; + if (beta != +DBL_MAX) + { for (aij = p->ptr; aij != NULL; aij = aij->r_next) + { if (aij == apq) continue; /* skip a[p,q] */ + if (aij->val > 0.0) + { if (aij->col->lb == -DBL_MAX) + { beta = +DBL_MAX; + break; + } + beta -= aij->val * aij->col->lb; + } + else /* < 0.0 */ + { if (aij->col->ub == +DBL_MAX) + { beta = +DBL_MAX; + break; + } + beta -= aij->val * aij->col->ub; + } + } + } + /* compute implied column lower bound l'[q] */ + if (apq->val > 0.0) + l = (alfa == -DBL_MAX ? -DBL_MAX : alfa / apq->val); + else /* < 0.0 */ + l = (beta == +DBL_MAX ? -DBL_MAX : beta / apq->val); + /* compute implied column upper bound u'[q] */ + if (apq->val > 0.0) + u = (beta == +DBL_MAX ? +DBL_MAX : beta / apq->val); + else + u = (alfa == -DBL_MAX ? +DBL_MAX : alfa / apq->val); + /* check if column lower bound l[q] can be active */ + if (q->lb != -DBL_MAX) + { eps = 1e-9 + 1e-12 * fabs(q->lb); + if (l < q->lb - eps) return 1; /* yes, it can */ + } + /* check if column upper bound u[q] can be active */ + if (q->ub != +DBL_MAX) + { eps = 1e-9 + 1e-12 * fabs(q->ub); + if (u > q->ub + eps) return 1; /* yes, it can */ + } + /* okay; make column q free (unbounded) */ + q->lb = -DBL_MAX, q->ub = +DBL_MAX; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_implied_free, sizeof(struct implied_free)); + info->p = p->i; + info->stat = -1; + /* compute row multiplier pi[p] */ + pi = q->coef / apq->val; + /* check dual feasibility for row p */ + if (pi > +DBL_EPSILON) + { /* lower bound L[p] must be active */ + if (p->lb != -DBL_MAX) +nl: { info->stat = GLP_NL; + p->ub = p->lb; + } + else + { if (pi > +1e-5) return 2; /* dual infeasibility */ + /* take a chance on U[p] */ + xassert(p->ub != +DBL_MAX); + goto nu; + } + } + else if (pi < -DBL_EPSILON) + { /* upper bound U[p] must be active */ + if (p->ub != +DBL_MAX) +nu: { info->stat = GLP_NU; + p->lb = p->ub; + } + else + { if (pi < -1e-5) return 2; /* dual infeasibility */ + /* take a chance on L[p] */ + xassert(p->lb != -DBL_MAX); + goto nl; + } + } + else + { /* any bound (either L[p] or U[p]) can be made active */ + if (p->ub == +DBL_MAX) + { xassert(p->lb != -DBL_MAX); + goto nl; + } + if (p->lb == -DBL_MAX) + { xassert(p->ub != +DBL_MAX); + goto nu; + } + if (fabs(p->lb) <= fabs(p->ub)) goto nl; else goto nu; + } + return 0; +} + +static int rcv_implied_free(NPP *npp, void *_info) +{ /* recover column singleton (implied free variable) */ + struct implied_free *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] == GLP_BS) + npp->r_stat[info->p] = GLP_BS; + else if (npp->r_stat[info->p] == GLP_NS) + { xassert(info->stat == GLP_NL || info->stat == GLP_NU); + npp->r_stat[info->p] = info->stat; + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_eq_doublet - process row doubleton (equality constraint) +* +* SYNOPSIS +* +* #include "glpnpp.h" +* NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_eq_doublet processes row p, which is equality +* constraint having exactly two non-zero coefficients: +* +* a[p,q] x[q] + a[p,r] x[r] = b. (1) +* +* As the result of processing one of columns q or r is eliminated from +* all other rows and, thus, becomes column singleton of type "implied +* slack variable". Row p is not changed and along with column q and r +* remains in the problem. +* +* RETURNS +* +* The routine npp_eq_doublet returns pointer to the descriptor of that +* column q or r which has been eliminated. If, due to some reason, the +* elimination was not performed, the routine returns NULL. +* +* PROBLEM TRANSFORMATION +* +* First, we decide which column q or r will be eliminated. Let it be +* column q. Consider i-th constraint row, where column q has non-zero +* coefficient a[i,q] != 0: +* +* L[i] <= sum a[i,j] x[j] <= U[i]. (2) +* j +* +* In order to eliminate column q from row (2) we subtract from it row +* (1) multiplied by gamma[i] = a[i,q] / a[p,q], i.e. we replace in the +* transformed problem row (2) by its linear combination with row (1). +* This transformation changes only coefficients in columns q and r, +* and bounds of row i as follows: +* +* a~[i,q] = a[i,q] - gamma[i] a[p,q] = 0, (3) +* +* a~[i,r] = a[i,r] - gamma[i] a[p,r], (4) +* +* L~[i] = L[i] - gamma[i] b, (5) +* +* U~[i] = U[i] - gamma[i] b. (6) +* +* RECOVERING BASIC SOLUTION +* +* The transformation of the primal system of the original problem: +* +* L <= A x <= U (7) +* +* is equivalent to multiplying from the left a transformation matrix F +* by components of this primal system, which in the transformed problem +* becomes the following: +* +* F L <= F A x <= F U ==> L~ <= A~x <= U~. (8) +* +* The matrix F has the following structure: +* +* ( 1 -gamma[1] ) +* ( ) +* ( 1 -gamma[2] ) +* ( ) +* ( ... ... ) +* ( ) +* F = ( 1 -gamma[p-1] ) (9) +* ( ) +* ( 1 ) +* ( ) +* ( -gamma[p+1] 1 ) +* ( ) +* ( ... ... ) +* +* where its column containing elements -gamma[i] corresponds to row p +* of the primal system. +* +* From (8) it follows that the dual system of the original problem: +* +* A'pi + lambda = c, (10) +* +* in the transformed problem becomes the following: +* +* A'F'inv(F')pi + lambda = c ==> (A~)'pi~ + lambda = c, (11) +* +* where: +* +* pi~ = inv(F')pi (12) +* +* is the vector of row multipliers in the transformed problem. Thus: +* +* pi = F'pi~. (13) +* +* Therefore, as it follows from (13), value of multiplier for row p in +* solution to the original problem can be computed as follows: +* +* pi[p] = pi~[p] - sum gamma[i] pi~[i], (14) +* i +* +* where pi~[i] = pi[i] is multiplier for row i (i != p). +* +* Note that the statuses of all rows and columns are not changed. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Multiplier for row p in solution to the original problem is computed +* with formula (14). +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct eq_doublet +{ /* row doubleton (equality constraint) */ + int p; + /* row reference number */ + double apq; + /* constraint coefficient a[p,q] */ + NPPLFE *ptr; + /* list of non-zero coefficients a[i,q], i != p */ +}; + +static int rcv_eq_doublet(NPP *npp, void *info); + +NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p) +{ /* process row doubleton (equality constraint) */ + struct eq_doublet *info; + NPPROW *i; + NPPCOL *q, *r; + NPPAIJ *apq, *apr, *aiq, *air, *next; + NPPLFE *lfe; + double gamma; + /* the row must be doubleton equality constraint */ + xassert(p->lb == p->ub); + xassert(p->ptr != NULL && p->ptr->r_next != NULL && + p->ptr->r_next->r_next == NULL); + /* choose column to be eliminated */ + { NPPAIJ *a1, *a2; + a1 = p->ptr, a2 = a1->r_next; + if (fabs(a2->val) < 0.001 * fabs(a1->val)) + { /* only first column can be eliminated, because second one + has too small constraint coefficient */ + apq = a1, apr = a2; + } + else if (fabs(a1->val) < 0.001 * fabs(a2->val)) + { /* only second column can be eliminated, because first one + has too small constraint coefficient */ + apq = a2, apr = a1; + } + else + { /* both columns are appropriate; choose that one which is + shorter to minimize fill-in */ + if (npp_col_nnz(npp, a1->col) <= npp_col_nnz(npp, a2->col)) + { /* first column is shorter */ + apq = a1, apr = a2; + } + else + { /* second column is shorter */ + apq = a2, apr = a1; + } + } + } + /* now columns q and r have been chosen */ + q = apq->col, r = apr->col; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_eq_doublet, sizeof(struct eq_doublet)); + info->p = p->i; + info->apq = apq->val; + info->ptr = NULL; + /* transform each row i (i != p), where a[i,q] != 0, to eliminate + column q */ + for (aiq = q->ptr; aiq != NULL; aiq = next) + { next = aiq->c_next; + if (aiq == apq) continue; /* skip row p */ + i = aiq->row; /* row i to be transformed */ + /* save constraint coefficient a[i,q] */ + if (npp->sol != GLP_MIP) + { lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = i->i; + lfe->val = aiq->val; + lfe->next = info->ptr; + info->ptr = lfe; + } + /* find coefficient a[i,r] in row i */ + for (air = i->ptr; air != NULL; air = air->r_next) + if (air->col == r) break; + /* if a[i,r] does not exist, create a[i,r] = 0 */ + if (air == NULL) + air = npp_add_aij(npp, i, r, 0.0); + /* compute gamma[i] = a[i,q] / a[p,q] */ + gamma = aiq->val / apq->val; + /* (row i) := (row i) - gamma[i] * (row p); see (3)-(6) */ + /* new a[i,q] is exact zero due to elimnation; remove it from + row i */ + npp_del_aij(npp, aiq); + /* compute new a[i,r] */ + air->val -= gamma * apr->val; + /* if new a[i,r] is close to zero due to numeric cancelation, + remove it from row i */ + if (fabs(air->val) <= 1e-10) + npp_del_aij(npp, air); + /* compute new lower and upper bounds of row i */ + if (i->lb == i->ub) + i->lb = i->ub = (i->lb - gamma * p->lb); + else + { if (i->lb != -DBL_MAX) + i->lb -= gamma * p->lb; + if (i->ub != +DBL_MAX) + i->ub -= gamma * p->lb; + } + } + return q; +} + +static int rcv_eq_doublet(NPP *npp, void *_info) +{ /* recover row doubleton (equality constraint) */ + struct eq_doublet *info = _info; + NPPLFE *lfe; + double gamma, temp; + /* we assume that processing row p is followed by processing + column q as singleton of type "implied slack variable", in + which case row p must always be active equality constraint */ + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] != GLP_NS) + { npp_error(); + return 1; + } + } + if (npp->sol != GLP_MIP) + { /* compute value of multiplier for row p; see (14) */ + temp = npp->r_pi[info->p]; + for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) + { gamma = lfe->val / info->apq; /* a[i,q] / a[p,q] */ + temp -= gamma * npp->r_pi[lfe->ref]; + } + npp->r_pi[info->p] = temp; + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_forcing_row - process forcing row +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_forcing_row(NPP *npp, NPPROW *p, int at); +* +* DESCRIPTION +* +* The routine npp_forcing row processes row p of general format: +* +* L[p] <= sum a[p,j] x[j] <= U[p], (1) +* j +* +* l[j] <= x[j] <= u[j], (2) +* +* where L[p] <= U[p] and l[j] < u[j] for all a[p,j] != 0. It is also +* assumed that: +* +* 1) if at = 0 then |L[p] - U'[p]| <= eps, where U'[p] is implied +* row upper bound (see below), eps is an absolute tolerance for row +* value; +* +* 2) if at = 1 then |U[p] - L'[p]| <= eps, where L'[p] is implied +* row lower bound (see below). +* +* RETURNS +* +* 0 - success; +* +* 1 - cannot fix columns due to too small constraint coefficients. +* +* PROBLEM TRANSFORMATION +* +* Implied lower and upper bounds of row (1) are determined by bounds +* of corresponding columns (variables) as follows: +* +* L'[p] = inf sum a[p,j] x[j] = +* j +* (3) +* = sum a[p,j] l[j] + sum a[p,j] u[j], +* j in Jp j in Jn +* +* U'[p] = sup sum a[p,j] x[j] = +* (4) +* = sum a[p,j] u[j] + sum a[p,j] l[j], +* j in Jp j in Jn +* +* Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) +* +* If L[p] =~ U'[p] (at = 0), solution can be primal feasible only when +* all variables take their boundary values as defined by (4): +* +* ( u[j], if j in Jp +* x[j] = < (6) +* ( l[j], if j in Jn +* +* Similarly, if U[p] =~ L'[p] (at = 1), solution can be primal feasible +* only when all variables take their boundary values as defined by (3): +* +* ( l[j], if j in Jp +* x[j] = < (7) +* ( u[j], if j in Jn +* +* Condition (6) or (7) allows fixing all columns (variables x[j]) +* in row (1) on their bounds and then removing them from the problem +* (see the routine npp_fixed_col). Due to this row p becomes redundant, +* so it can be replaced by equivalent free (unbounded) row and also +* removed from the problem (see the routine npp_free_row). +* +* 1. To apply this transformation row (1) should not have coefficients +* whose magnitude is too small, i.e. all a[p,j] should satisfy to +* the following condition: +* +* |a[p,j]| >= eps * max(1, |a[p,k]|), (8) +* k +* where eps is a relative tolerance for constraint coefficients. +* Otherwise, fixing columns may be numerically unreliable and may +* lead to wrong solution. +* +* 2. The routine fixes columns and remove bounds of row p, however, +* it does not remove the row and columns from the problem. +* +* RECOVERING BASIC SOLUTION +* +* In the transformed problem row p being inactive constraint is +* assigned status GLP_BS (as the result of transformation of free +* row), and all columns in this row are assigned status GLP_NS (as the +* result of transformation of fixed columns). +* +* Note that in the dual system of the transformed (as well as original) +* problem every column j in row p corresponds to the following row: +* +* sum a[i,j] pi[i] + a[p,j] pi[p] + lambda[j] = c[j], (9) +* i!=p +* +* from which it follows that: +* +* lambda[j] = c[j] - sum a[i,j] pi[i] - a[p,j] pi[p]. (10) +* i!=p +* +* In the transformed problem values of all multipliers pi[i] are known +* (including pi[i], whose value is zero, since row p is inactive). +* Thus, using formula (10) it is possible to compute values of +* multipliers lambda[j] for all columns in row p. +* +* Note also that in the original problem all columns in row p are +* bounded, not fixed. So status GLP_NS assigned to every such column +* must be changed to GLP_NL or GLP_NU depending on which bound the +* corresponding column has been fixed. This status change may lead to +* dual feasibility violation for solution of the original problem, +* because now column multipliers must satisfy to the following +* condition: +* +* ( >= 0, if status of column j is GLP_NL, +* lambda[j] < (11) +* ( <= 0, if status of column j is GLP_NU. +* +* If this condition holds, solution to the original problem is the +* same as to the transformed problem. Otherwise, we have to perform +* one degenerate pivoting step of the primal simplex method to obtain +* dual feasible (hence, optimal) solution to the original problem as +* follows. If, on problem transformation, row p was made active on its +* lower bound (case at = 0), we change its status to GLP_NL (or GLP_NS) +* and start increasing its multiplier pi[p]. Otherwise, if row p was +* made active on its upper bound (case at = 1), we change its status +* to GLP_NU (or GLP_NS) and start decreasing pi[p]. From (10) it +* follows that: +* +* delta lambda[j] = - a[p,j] * delta pi[p] = - a[p,j] pi[p]. (12) +* +* Simple analysis of formulae (3)-(5) shows that changing pi[p] in the +* specified direction causes increasing lambda[j] for every column j +* assigned status GLP_NL (delta lambda[j] > 0) and decreasing lambda[j] +* for every column j assigned status GLP_NU (delta lambda[j] < 0). It +* is understood that once the last lambda[q], which violates condition +* (11), has reached zero, multipliers lambda[j] for all columns get +* valid signs. Such column q can be determined as follows. Let d[j] be +* initial value of lambda[j] (i.e. reduced cost of column j) in the +* transformed problem computed with formula (10) when pi[p] = 0. Then +* lambda[j] = d[j] + delta lambda[j], and from (12) it follows that +* lambda[j] becomes zero if: +* +* delta lambda[j] = - a[p,j] pi[p] = - d[j] ==> +* (13) +* pi[p] = d[j] / a[p,j]. +* +* Therefore, the last column q, for which lambda[q] becomes zero, can +* be determined from the following condition: +* +* |d[q] / a[p,q]| = max |pi[p]| = max |d[j] / a[p,j]|, (14) +* j in D j in D +* +* where D is a set of columns j whose, reduced costs d[j] have invalid +* signs, i.e. violate condition (11). (Thus, if D is empty, solution +* to the original problem is the same as solution to the transformed +* problem, and no correction is needed as was noticed above.) In +* solution to the original problem column q is assigned status GLP_BS, +* since it replaces column of auxiliary variable of row p (becoming +* active) in the basis, and multiplier for row p is assigned its new +* value, which is pi[p] = d[q] / a[p,q]. Note that due to primal +* degeneracy values of all columns having non-zero coefficients in row +* p remain unchanged. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of multiplier pi[p] in solution to the original problem is +* corrected in the same way as for basic solution. Values of all +* columns having non-zero coefficients in row p remain unchanged. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct forcing_col +{ /* column fixed on its bound by forcing row */ + int j; + /* column reference number */ + char stat; + /* original column status: + GLP_NL - fixed on lower bound + GLP_NU - fixed on upper bound */ + double a; + /* constraint coefficient a[p,j] */ + double c; + /* objective coefficient c[j] */ + NPPLFE *ptr; + /* list of non-zero coefficients a[i,j], i != p */ + struct forcing_col *next; + /* pointer to another column fixed by forcing row */ +}; + +struct forcing_row +{ /* forcing row */ + int p; + /* row reference number */ + char stat; + /* status assigned to the row if it becomes active: + GLP_NS - active equality constraint + GLP_NL - inequality constraint with lower bound active + GLP_NU - inequality constraint with upper bound active */ + struct forcing_col *ptr; + /* list of all columns having non-zero constraint coefficient + a[p,j] in the forcing row */ +}; + +static int rcv_forcing_row(NPP *npp, void *info); + +int npp_forcing_row(NPP *npp, NPPROW *p, int at) +{ /* process forcing row */ + struct forcing_row *info; + struct forcing_col *col = NULL; + NPPCOL *j; + NPPAIJ *apj, *aij; + NPPLFE *lfe; + double big; + xassert(at == 0 || at == 1); + /* determine maximal magnitude of the row coefficients */ + big = 1.0; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + if (big < fabs(apj->val)) big = fabs(apj->val); + /* if there are too small coefficients in the row, transformation + should not be applied */ + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + if (fabs(apj->val) < 1e-7 * big) return 1; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_forcing_row, sizeof(struct forcing_row)); + info->p = p->i; + if (p->lb == p->ub) + { /* equality constraint */ + info->stat = GLP_NS; + } + else if (at == 0) + { /* inequality constraint; case L[p] = U'[p] */ + info->stat = GLP_NL; + xassert(p->lb != -DBL_MAX); + } + else /* at == 1 */ + { /* inequality constraint; case U[p] = L'[p] */ + info->stat = GLP_NU; + xassert(p->ub != +DBL_MAX); + } + info->ptr = NULL; + /* scan the forcing row, fix columns at corresponding bounds, and + save column information (the latter is not needed for MIP) */ + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { /* column j has non-zero coefficient in the forcing row */ + j = apj->col; + /* it must be non-fixed */ + xassert(j->lb < j->ub); + /* allocate stack entry to save column information */ + if (npp->sol != GLP_MIP) + { col = dmp_get_atom(npp->stack, sizeof(struct forcing_col)); + col->j = j->j; + col->stat = -1; /* will be set below */ + col->a = apj->val; + col->c = j->coef; + col->ptr = NULL; + col->next = info->ptr; + info->ptr = col; + } + /* fix column j */ + if (at == 0 && apj->val < 0.0 || at != 0 && apj->val > 0.0) + { /* at its lower bound */ + if (npp->sol != GLP_MIP) + col->stat = GLP_NL; + xassert(j->lb != -DBL_MAX); + j->ub = j->lb; + } + else + { /* at its upper bound */ + if (npp->sol != GLP_MIP) + col->stat = GLP_NU; + xassert(j->ub != +DBL_MAX); + j->lb = j->ub; + } + /* save column coefficients a[i,j], i != p */ + if (npp->sol != GLP_MIP) + { for (aij = j->ptr; aij != NULL; aij = aij->c_next) + { if (aij == apj) continue; /* skip a[p,j] */ + lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = aij->row->i; + lfe->val = aij->val; + lfe->next = col->ptr; + col->ptr = lfe; + } + } + } + /* make the row free (unbounded) */ + p->lb = -DBL_MAX, p->ub = +DBL_MAX; + return 0; +} + +static int rcv_forcing_row(NPP *npp, void *_info) +{ /* recover forcing row */ + struct forcing_row *info = _info; + struct forcing_col *col, *piv; + NPPLFE *lfe; + double d, big, temp; + if (npp->sol == GLP_MIP) goto done; + /* initially solution to the original problem is the same as + to the transformed problem, where row p is inactive constraint + with pi[p] = 0, and all columns are non-basic */ + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] != GLP_BS) + { npp_error(); + return 1; + } + for (col = info->ptr; col != NULL; col = col->next) + { if (npp->c_stat[col->j] != GLP_NS) + { npp_error(); + return 1; + } + npp->c_stat[col->j] = col->stat; /* original status */ + } + } + /* compute reduced costs d[j] for all columns with formula (10) + and store them in col.c instead objective coefficients */ + for (col = info->ptr; col != NULL; col = col->next) + { d = col->c; + for (lfe = col->ptr; lfe != NULL; lfe = lfe->next) + d -= lfe->val * npp->r_pi[lfe->ref]; + col->c = d; + } + /* consider columns j, whose multipliers lambda[j] has wrong + sign in solution to the transformed problem (where lambda[j] = + d[j]), and choose column q, whose multipler lambda[q] reaches + zero last on changing row multiplier pi[p]; see (14) */ + piv = NULL, big = 0.0; + for (col = info->ptr; col != NULL; col = col->next) + { d = col->c; /* d[j] */ + temp = fabs(d / col->a); + if (col->stat == GLP_NL) + { /* column j has active lower bound */ + if (d < 0.0 && big < temp) + piv = col, big = temp; + } + else if (col->stat == GLP_NU) + { /* column j has active upper bound */ + if (d > 0.0 && big < temp) + piv = col, big = temp; + } + else + { npp_error(); + return 1; + } + } + /* if column q does not exist, no correction is needed */ + if (piv != NULL) + { /* correct solution; row p becomes active constraint while + column q becomes basic */ + if (npp->sol == GLP_SOL) + { npp->r_stat[info->p] = info->stat; + npp->c_stat[piv->j] = GLP_BS; + } + /* assign new value to row multiplier pi[p] = d[p] / a[p,q] */ + npp->r_pi[info->p] = piv->c / piv->a; + } +done: return 0; +} + +/*********************************************************************** +* NAME +* +* npp_analyze_row - perform general row analysis +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_analyze_row(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_analyze_row performs analysis of row p of general +* format: +* +* L[p] <= sum a[p,j] x[j] <= U[p], (1) +* j +* +* l[j] <= x[j] <= u[j], (2) +* +* where L[p] <= U[p] and l[j] <= u[j] for all a[p,j] != 0. +* +* RETURNS +* +* 0x?0 - row lower bound does not exist or is redundant; +* +* 0x?1 - row lower bound can be active; +* +* 0x?2 - row lower bound is a forcing bound; +* +* 0x0? - row upper bound does not exist or is redundant; +* +* 0x1? - row upper bound can be active; +* +* 0x2? - row upper bound is a forcing bound; +* +* 0x33 - row bounds are inconsistent with column bounds. +* +* ALGORITHM +* +* Analysis of row (1) is based on analysis of its implied lower and +* upper bounds, which are determined by bounds of corresponding columns +* (variables) as follows: +* +* L'[p] = inf sum a[p,j] x[j] = +* j +* (3) +* = sum a[p,j] l[j] + sum a[p,j] u[j], +* j in Jp j in Jn +* +* U'[p] = sup sum a[p,j] x[j] = +* (4) +* = sum a[p,j] u[j] + sum a[p,j] l[j], +* j in Jp j in Jn +* +* Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) +* +* (Note that bounds of all columns in row p are assumed to be correct, +* so L'[p] <= U'[p].) +* +* Analysis of row lower bound L[p] includes the following cases: +* +* 1) if L[p] > U'[p] + eps, where eps is an absolute tolerance for row +* value, row lower bound L[p] and implied row upper bound U'[p] are +* inconsistent, ergo, the problem has no primal feasible solution; +* +* 2) if U'[p] - eps <= L[p] <= U'[p] + eps, i.e. if L[p] =~ U'[p], +* the row is a forcing row on its lower bound (see description of +* the routine npp_forcing_row); +* +* 3) if L[p] > L'[p] + eps, row lower bound L[p] can be active (this +* conclusion does not account other rows in the problem); +* +* 4) if L[p] <= L'[p] + eps, row lower bound L[p] cannot be active, so +* it is redundant and can be removed (replaced by -oo). +* +* Analysis of row upper bound U[p] is performed in a similar way and +* includes the following cases: +* +* 1) if U[p] < L'[p] - eps, row upper bound U[p] and implied row lower +* bound L'[p] are inconsistent, ergo the problem has no primal +* feasible solution; +* +* 2) if L'[p] - eps <= U[p] <= L'[p] + eps, i.e. if U[p] =~ L'[p], +* the row is a forcing row on its upper bound (see description of +* the routine npp_forcing_row); +* +* 3) if U[p] < U'[p] - eps, row upper bound U[p] can be active (this +* conclusion does not account other rows in the problem); +* +* 4) if U[p] >= U'[p] - eps, row upper bound U[p] cannot be active, so +* it is redundant and can be removed (replaced by +oo). */ + +int npp_analyze_row(NPP *npp, NPPROW *p) +{ /* perform general row analysis */ + NPPAIJ *aij; + int ret = 0x00; + double l, u, eps; + xassert(npp == npp); + /* compute implied lower bound L'[p]; see (3) */ + l = 0.0; + for (aij = p->ptr; aij != NULL; aij = aij->r_next) + { if (aij->val > 0.0) + { if (aij->col->lb == -DBL_MAX) + { l = -DBL_MAX; + break; + } + l += aij->val * aij->col->lb; + } + else /* aij->val < 0.0 */ + { if (aij->col->ub == +DBL_MAX) + { l = -DBL_MAX; + break; + } + l += aij->val * aij->col->ub; + } + } + /* compute implied upper bound U'[p]; see (4) */ + u = 0.0; + for (aij = p->ptr; aij != NULL; aij = aij->r_next) + { if (aij->val > 0.0) + { if (aij->col->ub == +DBL_MAX) + { u = +DBL_MAX; + break; + } + u += aij->val * aij->col->ub; + } + else /* aij->val < 0.0 */ + { if (aij->col->lb == -DBL_MAX) + { u = +DBL_MAX; + break; + } + u += aij->val * aij->col->lb; + } + } + /* column bounds are assumed correct, so L'[p] <= U'[p] */ + /* check if row lower bound is consistent */ + if (p->lb != -DBL_MAX) + { eps = 1e-3 + 1e-6 * fabs(p->lb); + if (p->lb - eps > u) + { ret = 0x33; + goto done; + } + } + /* check if row upper bound is consistent */ + if (p->ub != +DBL_MAX) + { eps = 1e-3 + 1e-6 * fabs(p->ub); + if (p->ub + eps < l) + { ret = 0x33; + goto done; + } + } + /* check if row lower bound can be active/forcing */ + if (p->lb != -DBL_MAX) + { eps = 1e-9 + 1e-12 * fabs(p->lb); + if (p->lb - eps > l) + { if (p->lb + eps <= u) + ret |= 0x01; + else + ret |= 0x02; + } + } + /* check if row upper bound can be active/forcing */ + if (p->ub != +DBL_MAX) + { eps = 1e-9 + 1e-12 * fabs(p->ub); + if (p->ub + eps < u) + { /* check if the upper bound is forcing */ + if (p->ub - eps >= l) + ret |= 0x10; + else + ret |= 0x20; + } + } +done: return ret; +} + +/*********************************************************************** +* NAME +* +* npp_inactive_bound - remove row lower/upper inactive bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_inactive_bound(NPP *npp, NPPROW *p, int which); +* +* DESCRIPTION +* +* The routine npp_inactive_bound removes lower (if which = 0) or upper +* (if which = 1) bound of row p: +* +* L[p] <= sum a[p,j] x[j] <= U[p], +* +* which (bound) is assumed to be redundant. +* +* PROBLEM TRANSFORMATION +* +* If which = 0, current lower bound L[p] of row p is assigned -oo. +* If which = 1, current upper bound U[p] of row p is assigned +oo. +* +* RECOVERING BASIC SOLUTION +* +* If in solution to the transformed problem row p is inactive +* constraint (GLP_BS), its status is not changed in solution to the +* original problem. Otherwise, status of row p in solution to the +* original problem is defined by its type before transformation and +* its status in solution to the transformed problem as follows: +* +* +---------------------+-------+---------------+---------------+ +* | Row | Flag | Row status in | Row status in | +* | type | which | transfmd soln | original soln | +* +---------------------+-------+---------------+---------------+ +* | sum >= L[p] | 0 | GLP_NF | GLP_NL | +* | sum <= U[p] | 1 | GLP_NF | GLP_NU | +* | L[p] <= sum <= U[p] | 0 | GLP_NU | GLP_NU | +* | L[p] <= sum <= U[p] | 1 | GLP_NL | GLP_NL | +* | sum = L[p] = U[p] | 0 | GLP_NU | GLP_NS | +* | sum = L[p] = U[p] | 1 | GLP_NL | GLP_NS | +* +---------------------+-------+---------------+---------------+ +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* None needed. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct inactive_bound +{ /* row inactive bound */ + int p; + /* row reference number */ + char stat; + /* row status (if active constraint) */ +}; + +static int rcv_inactive_bound(NPP *npp, void *info); + +void npp_inactive_bound(NPP *npp, NPPROW *p, int which) +{ /* remove row lower/upper inactive bound */ + struct inactive_bound *info; + if (npp->sol == GLP_SOL) + { /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_inactive_bound, sizeof(struct inactive_bound)); + info->p = p->i; + if (p->ub == +DBL_MAX) + info->stat = GLP_NL; + else if (p->lb == -DBL_MAX) + info->stat = GLP_NU; + else if (p->lb != p->ub) + info->stat = (char)(which == 0 ? GLP_NU : GLP_NL); + else + info->stat = GLP_NS; + } + /* remove row inactive bound */ + if (which == 0) + { xassert(p->lb != -DBL_MAX); + p->lb = -DBL_MAX; + } + else if (which == 1) + { xassert(p->ub != +DBL_MAX); + p->ub = +DBL_MAX; + } + else + xassert(which != which); + return; +} + +static int rcv_inactive_bound(NPP *npp, void *_info) +{ /* recover row status */ + struct inactive_bound *info = _info; + if (npp->sol != GLP_SOL) + { npp_error(); + return 1; + } + if (npp->r_stat[info->p] == GLP_BS) + npp->r_stat[info->p] = GLP_BS; + else + npp->r_stat[info->p] = info->stat; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_implied_bounds - determine implied column bounds +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_implied_bounds(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_implied_bounds inspects general row (constraint) p: +* +* L[p] <= sum a[p,j] x[j] <= U[p], (1) +* +* l[j] <= x[j] <= u[j], (2) +* +* where L[p] <= U[p] and l[j] <= u[j] for all a[p,j] != 0, to compute +* implied bounds of columns (variables x[j]) in this row. +* +* The routine stores implied column bounds l'[j] and u'[j] in column +* descriptors (NPPCOL); it does not change current column bounds l[j] +* and u[j]. (Implied column bounds can be then used to strengthen the +* current column bounds; see the routines npp_implied_lower and +* npp_implied_upper). +* +* ALGORITHM +* +* Current column bounds (2) define implied lower and upper bounds of +* row (1) as follows: +* +* L'[p] = inf sum a[p,j] x[j] = +* j +* (3) +* = sum a[p,j] l[j] + sum a[p,j] u[j], +* j in Jp j in Jn +* +* U'[p] = sup sum a[p,j] x[j] = +* (4) +* = sum a[p,j] u[j] + sum a[p,j] l[j], +* j in Jp j in Jn +* +* Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) +* +* (Note that bounds of all columns in row p are assumed to be correct, +* so L'[p] <= U'[p].) +* +* If L[p] > L'[p] and/or U[p] < U'[p], the lower and/or upper bound of +* row (1) can be active, in which case such row defines implied bounds +* of its variables. +* +* Let x[k] be some variable having in row (1) coefficient a[p,k] != 0. +* Consider a case when row lower bound can be active (L[p] > L'[p]): +* +* sum a[p,j] x[j] >= L[p] ==> +* j +* +* sum a[p,j] x[j] + a[p,k] x[k] >= L[p] ==> +* j!=k +* (6) +* a[p,k] x[k] >= L[p] - sum a[p,j] x[j] ==> +* j!=k +* +* a[p,k] x[k] >= L[p,k], +* +* where +* +* L[p,k] = inf(L[p] - sum a[p,j] x[j]) = +* j!=k +* +* = L[p] - sup sum a[p,j] x[j] = (7) +* j!=k +* +* = L[p] - sum a[p,j] u[j] - sum a[p,j] l[j]. +* j in Jp\{k} j in Jn\{k} +* +* Thus: +* +* x[k] >= l'[k] = L[p,k] / a[p,k], if a[p,k] > 0, (8) +* +* x[k] <= u'[k] = L[p,k] / a[p,k], if a[p,k] < 0. (9) +* +* where l'[k] and u'[k] are implied lower and upper bounds of variable +* x[k], resp. +* +* Now consider a similar case when row upper bound can be active +* (U[p] < U'[p]): +* +* sum a[p,j] x[j] <= U[p] ==> +* j +* +* sum a[p,j] x[j] + a[p,k] x[k] <= U[p] ==> +* j!=k +* (10) +* a[p,k] x[k] <= U[p] - sum a[p,j] x[j] ==> +* j!=k +* +* a[p,k] x[k] <= U[p,k], +* +* where: +* +* U[p,k] = sup(U[p] - sum a[p,j] x[j]) = +* j!=k +* +* = U[p] - inf sum a[p,j] x[j] = (11) +* j!=k +* +* = U[p] - sum a[p,j] l[j] - sum a[p,j] u[j]. +* j in Jp\{k} j in Jn\{k} +* +* Thus: +* +* x[k] <= u'[k] = U[p,k] / a[p,k], if a[p,k] > 0, (12) +* +* x[k] >= l'[k] = U[p,k] / a[p,k], if a[p,k] < 0. (13) +* +* Note that in formulae (8), (9), (12), and (13) coefficient a[p,k] +* must not be too small in magnitude relatively to other non-zero +* coefficients in row (1), i.e. the following condition must hold: +* +* |a[p,k]| >= eps * max(1, |a[p,j]|), (14) +* j +* +* where eps is a relative tolerance for constraint coefficients. +* Otherwise the implied column bounds can be numerical inreliable. For +* example, using formula (8) for the following inequality constraint: +* +* 1e-12 x1 - x2 - x3 >= 0, +* +* where x1 >= -1, x2, x3, >= 0, may lead to numerically unreliable +* conclusion that x1 >= 0. +* +* Using formulae (8), (9), (12), and (13) to compute implied bounds +* for one variable requires |J| operations, where J = {j: a[p,j] != 0}, +* because this needs computing L[p,k] and U[p,k]. Thus, computing +* implied bounds for all variables in row (1) would require |J|^2 +* operations, that is not a good technique. However, the total number +* of operations can be reduced to |J| as follows. +* +* Let a[p,k] > 0. Then from (7) and (11) we have: +* +* L[p,k] = L[p] - (U'[p] - a[p,k] u[k]) = +* +* = L[p] - U'[p] + a[p,k] u[k], +* +* U[p,k] = U[p] - (L'[p] - a[p,k] l[k]) = +* +* = U[p] - L'[p] + a[p,k] l[k], +* +* where L'[p] and U'[p] are implied row lower and upper bounds defined +* by formulae (3) and (4). Substituting these expressions into (8) and +* (12) gives: +* +* l'[k] = L[p,k] / a[p,k] = u[k] + (L[p] - U'[p]) / a[p,k], (15) +* +* u'[k] = U[p,k] / a[p,k] = l[k] + (U[p] - L'[p]) / a[p,k]. (16) +* +* Similarly, if a[p,k] < 0, according to (7) and (11) we have: +* +* L[p,k] = L[p] - (U'[p] - a[p,k] l[k]) = +* +* = L[p] - U'[p] + a[p,k] l[k], +* +* U[p,k] = U[p] - (L'[p] - a[p,k] u[k]) = +* +* = U[p] - L'[p] + a[p,k] u[k], +* +* and substituting these expressions into (8) and (12) gives: +* +* l'[k] = U[p,k] / a[p,k] = u[k] + (U[p] - L'[p]) / a[p,k], (17) +* +* u'[k] = L[p,k] / a[p,k] = l[k] + (L[p] - U'[p]) / a[p,k]. (18) +* +* Note that formulae (15)-(18) can be used only if L'[p] and U'[p] +* exist. However, if for some variable x[j] it happens that l[j] = -oo +* and/or u[j] = +oo, values of L'[p] (if a[p,j] > 0) and/or U'[p] (if +* a[p,j] < 0) are undefined. Consider, therefore, the most general +* situation, when some column bounds (2) may not exist. +* +* Let: +* +* J' = {j : (a[p,j] > 0 and l[j] = -oo) or +* (19) +* (a[p,j] < 0 and u[j] = +oo)}. +* +* Then (assuming that row upper bound U[p] can be active) the following +* three cases are possible: +* +* 1) |J'| = 0. In this case L'[p] exists, thus, for all variables x[j] +* in row (1) we can use formulae (16) and (17); +* +* 2) J' = {k}. In this case L'[p] = -oo, however, U[p,k] (11) exists, +* so for variable x[k] we can use formulae (12) and (13). Note that +* for all other variables x[j] (j != k) l'[j] = -oo (if a[p,j] < 0) +* or u'[j] = +oo (if a[p,j] > 0); +* +* 3) |J'| > 1. In this case for all variables x[j] in row [1] we have +* l'[j] = -oo (if a[p,j] < 0) or u'[j] = +oo (if a[p,j] > 0). +* +* Similarly, let: +* +* J'' = {j : (a[p,j] > 0 and u[j] = +oo) or +* (20) +* (a[p,j] < 0 and l[j] = -oo)}. +* +* Then (assuming that row lower bound L[p] can be active) the following +* three cases are possible: +* +* 1) |J''| = 0. In this case U'[p] exists, thus, for all variables x[j] +* in row (1) we can use formulae (15) and (18); +* +* 2) J'' = {k}. In this case U'[p] = +oo, however, L[p,k] (7) exists, +* so for variable x[k] we can use formulae (8) and (9). Note that +* for all other variables x[j] (j != k) l'[j] = -oo (if a[p,j] > 0) +* or u'[j] = +oo (if a[p,j] < 0); +* +* 3) |J''| > 1. In this case for all variables x[j] in row (1) we have +* l'[j] = -oo (if a[p,j] > 0) or u'[j] = +oo (if a[p,j] < 0). */ + +void npp_implied_bounds(NPP *npp, NPPROW *p) +{ NPPAIJ *apj, *apk; + double big, eps, temp; + xassert(npp == npp); + /* initialize implied bounds for all variables and determine + maximal magnitude of row coefficients a[p,j] */ + big = 1.0; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { apj->col->ll.ll = -DBL_MAX, apj->col->uu.uu = +DBL_MAX; + if (big < fabs(apj->val)) big = fabs(apj->val); + } + eps = 1e-6 * big; + /* process row lower bound (assuming that it can be active) */ + if (p->lb != -DBL_MAX) + { apk = NULL; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj->val > 0.0 && apj->col->ub == +DBL_MAX || + apj->val < 0.0 && apj->col->lb == -DBL_MAX) + { if (apk == NULL) + apk = apj; + else + goto skip1; + } + } + /* if a[p,k] = NULL then |J'| = 0 else J' = { k } */ + temp = p->lb; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj == apk) + /* skip a[p,k] */; + else if (apj->val > 0.0) + temp -= apj->val * apj->col->ub; + else /* apj->val < 0.0 */ + temp -= apj->val * apj->col->lb; + } + /* compute column implied bounds */ + if (apk == NULL) + { /* temp = L[p] - U'[p] */ + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj->val >= +eps) + { /* l'[j] := u[j] + (L[p] - U'[p]) / a[p,j] */ + apj->col->ll.ll = apj->col->ub + temp / apj->val; + } + else if (apj->val <= -eps) + { /* u'[j] := l[j] + (L[p] - U'[p]) / a[p,j] */ + apj->col->uu.uu = apj->col->lb + temp / apj->val; + } + } + } + else + { /* temp = L[p,k] */ + if (apk->val >= +eps) + { /* l'[k] := L[p,k] / a[p,k] */ + apk->col->ll.ll = temp / apk->val; + } + else if (apk->val <= -eps) + { /* u'[k] := L[p,k] / a[p,k] */ + apk->col->uu.uu = temp / apk->val; + } + } +skip1: ; + } + /* process row upper bound (assuming that it can be active) */ + if (p->ub != +DBL_MAX) + { apk = NULL; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj->val > 0.0 && apj->col->lb == -DBL_MAX || + apj->val < 0.0 && apj->col->ub == +DBL_MAX) + { if (apk == NULL) + apk = apj; + else + goto skip2; + } + } + /* if a[p,k] = NULL then |J''| = 0 else J'' = { k } */ + temp = p->ub; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj == apk) + /* skip a[p,k] */; + else if (apj->val > 0.0) + temp -= apj->val * apj->col->lb; + else /* apj->val < 0.0 */ + temp -= apj->val * apj->col->ub; + } + /* compute column implied bounds */ + if (apk == NULL) + { /* temp = U[p] - L'[p] */ + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj->val >= +eps) + { /* u'[j] := l[j] + (U[p] - L'[p]) / a[p,j] */ + apj->col->uu.uu = apj->col->lb + temp / apj->val; + } + else if (apj->val <= -eps) + { /* l'[j] := u[j] + (U[p] - L'[p]) / a[p,j] */ + apj->col->ll.ll = apj->col->ub + temp / apj->val; + } + } + } + else + { /* temp = U[p,k] */ + if (apk->val >= +eps) + { /* u'[k] := U[p,k] / a[p,k] */ + apk->col->uu.uu = temp / apk->val; + } + else if (apk->val <= -eps) + { /* l'[k] := U[p,k] / a[p,k] */ + apk->col->ll.ll = temp / apk->val; + } + } +skip2: ; + } + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp04.c b/resources/3rdparty/glpk-4.53/src/glpnpp04.c new file mode 100644 index 000000000..925b1ba0f --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpnpp04.c @@ -0,0 +1,1415 @@ +/* glpnpp04.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpnpp.h" + +/*********************************************************************** +* NAME +* +* npp_binarize_prob - binarize MIP problem +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_binarize_prob(NPP *npp); +* +* DESCRIPTION +* +* The routine npp_binarize_prob replaces in the original MIP problem +* every integer variable: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] < u[q], by an equivalent sum of binary variables. +* +* RETURNS +* +* The routine returns the number of integer variables for which the +* transformation failed, because u[q] - l[q] > d_max. +* +* PROBLEM TRANSFORMATION +* +* If variable x[q] has non-zero lower bound, it is first processed +* with the routine npp_lbnd_col. Thus, we can assume that: +* +* 0 <= x[q] <= u[q]. (2) +* +* If u[q] = 1, variable x[q] is already binary, so further processing +* is not needed. Let, therefore, that 2 <= u[q] <= d_max, and n be a +* smallest integer such that u[q] <= 2^n - 1 (n >= 2, since u[q] >= 2). +* Then variable x[q] can be replaced by the following sum: +* +* n-1 +* x[q] = sum 2^k x[k], (3) +* k=0 +* +* where x[k] are binary columns (variables). If u[q] < 2^n - 1, the +* following additional inequality constraint must be also included in +* the transformed problem: +* +* n-1 +* sum 2^k x[k] <= u[q]. (4) +* k=0 +* +* Note: Assuming that in the transformed problem x[q] becomes binary +* variable x[0], this transformation causes new n-1 binary variables +* to appear. +* +* Substituting x[q] from (3) to the objective row gives: +* +* z = sum c[j] x[j] + c[0] = +* j +* +* = sum c[j] x[j] + c[q] x[q] + c[0] = +* j!=q +* n-1 +* = sum c[j] x[j] + c[q] sum 2^k x[k] + c[0] = +* j!=q k=0 +* n-1 +* = sum c[j] x[j] + sum c[k] x[k] + c[0], +* j!=q k=0 +* +* where: +* +* c[k] = 2^k c[q], k = 0, ..., n-1. (5) +* +* And substituting x[q] from (3) to i-th constraint row i gives: +* +* L[i] <= sum a[i,j] x[j] <= U[i] ==> +* j +* +* L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> +* j!=q +* n-1 +* L[i] <= sum a[i,j] x[j] + a[i,q] sum 2^k x[k] <= U[i] ==> +* j!=q k=0 +* n-1 +* L[i] <= sum a[i,j] x[j] + sum a[i,k] x[k] <= U[i], +* j!=q k=0 +* +* where: +* +* a[i,k] = 2^k a[i,q], k = 0, ..., n-1. (6) +* +* RECOVERING SOLUTION +* +* Value of variable x[q] is computed with formula (3). */ + +struct binarize +{ int q; + /* column reference number for x[q] = x[0] */ + int j; + /* column reference number for x[1]; x[2] has reference number + j+1, x[3] - j+2, etc. */ + int n; + /* total number of binary variables, n >= 2 */ +}; + +static int rcv_binarize_prob(NPP *npp, void *info); + +int npp_binarize_prob(NPP *npp) +{ /* binarize MIP problem */ + struct binarize *info; + NPPROW *row; + NPPCOL *col, *bin; + NPPAIJ *aij; + int u, n, k, temp, nfails, nvars, nbins, nrows; + /* new variables will be added to the end of the column list, so + we go from the end to beginning of the column list */ + nfails = nvars = nbins = nrows = 0; + for (col = npp->c_tail; col != NULL; col = col->prev) + { /* skip continuous variable */ + if (!col->is_int) continue; + /* skip fixed variable */ + if (col->lb == col->ub) continue; + /* skip binary variable */ + if (col->lb == 0.0 && col->ub == 1.0) continue; + /* check if the transformation is applicable */ + if (col->lb < -1e6 || col->ub > +1e6 || + col->ub - col->lb > 4095.0) + { /* unfortunately, not */ + nfails++; + continue; + } + /* process integer non-binary variable x[q] */ + nvars++; + /* make x[q] non-negative, if its lower bound is non-zero */ + if (col->lb != 0.0) + npp_lbnd_col(npp, col); + /* now 0 <= x[q] <= u[q] */ + xassert(col->lb == 0.0); + u = (int)col->ub; + xassert(col->ub == (double)u); + /* if x[q] is binary, further processing is not needed */ + if (u == 1) continue; + /* determine smallest n such that u <= 2^n - 1 (thus, n is the + number of binary variables needed) */ + n = 2, temp = 4; + while (u >= temp) + n++, temp += temp; + nbins += n; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_binarize_prob, sizeof(struct binarize)); + info->q = col->j; + info->j = 0; /* will be set below */ + info->n = n; + /* if u < 2^n - 1, we need one additional row for (4) */ + if (u < temp - 1) + { row = npp_add_row(npp), nrows++; + row->lb = -DBL_MAX, row->ub = u; + } + else + row = NULL; + /* in the transformed problem variable x[q] becomes binary + variable x[0], so its objective and constraint coefficients + are not changed */ + col->ub = 1.0; + /* include x[0] into constraint (4) */ + if (row != NULL) + npp_add_aij(npp, row, col, 1.0); + /* add other binary variables x[1], ..., x[n-1] */ + for (k = 1, temp = 2; k < n; k++, temp += temp) + { /* add new binary variable x[k] */ + bin = npp_add_col(npp); + bin->is_int = 1; + bin->lb = 0.0, bin->ub = 1.0; + bin->coef = (double)temp * col->coef; + /* store column reference number for x[1] */ + if (info->j == 0) + info->j = bin->j; + else + xassert(info->j + (k-1) == bin->j); + /* duplicate constraint coefficients for x[k]; this also + automatically includes x[k] into constraint (4) */ + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + npp_add_aij(npp, aij->row, bin, (double)temp * aij->val); + } + } + if (nvars > 0) + xprintf("%d integer variable(s) were replaced by %d binary one" + "s\n", nvars, nbins); + if (nrows > 0) + xprintf("%d row(s) were added due to binarization\n", nrows); + if (nfails > 0) + xprintf("Binarization failed for %d integer variable(s)\n", + nfails); + return nfails; +} + +static int rcv_binarize_prob(NPP *npp, void *_info) +{ /* recovery binarized variable */ + struct binarize *info = _info; + int k, temp; + double sum; + /* compute value of x[q]; see formula (3) */ + sum = npp->c_value[info->q]; + for (k = 1, temp = 2; k < info->n; k++, temp += temp) + sum += (double)temp * npp->c_value[info->j + (k-1)]; + npp->c_value[info->q] = sum; + return 0; +} + +/**********************************************************************/ + +struct elem +{ /* linear form element a[j] x[j] */ + double aj; + /* non-zero coefficient value */ + NPPCOL *xj; + /* pointer to variable (column) */ + struct elem *next; + /* pointer to another term */ +}; + +static struct elem *copy_form(NPP *npp, NPPROW *row, double s) +{ /* copy linear form */ + NPPAIJ *aij; + struct elem *ptr, *e; + ptr = NULL; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { e = dmp_get_atom(npp->pool, sizeof(struct elem)); + e->aj = s * aij->val; + e->xj = aij->col; + e->next = ptr; + ptr = e; + } + return ptr; +} + +static void drop_form(NPP *npp, struct elem *ptr) +{ /* drop linear form */ + struct elem *e; + while (ptr != NULL) + { e = ptr; + ptr = e->next; + dmp_free_atom(npp->pool, e, sizeof(struct elem)); + } + return; +} + +/*********************************************************************** +* NAME +* +* npp_is_packing - test if constraint is packing inequality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_is_packing(NPP *npp, NPPROW *row); +* +* RETURNS +* +* If the specified row (constraint) is packing inequality (see below), +* the routine npp_is_packing returns non-zero. Otherwise, it returns +* zero. +* +* PACKING INEQUALITIES +* +* In canonical format the packing inequality is the following: +* +* sum x[j] <= 1, (1) +* j in J +* +* where all variables x[j] are binary. This inequality expresses the +* condition that in any integer feasible solution at most one variable +* from set J can take non-zero (unity) value while other variables +* must be equal to zero. W.l.o.g. it is assumed that |J| >= 2, because +* if J is empty or |J| = 1, the inequality (1) is redundant. +* +* In general case the packing inequality may include original variables +* x[j] as well as their complements x~[j]: +* +* sum x[j] + sum x~[j] <= 1, (2) +* j in Jp j in Jn +* +* where Jp and Jn are not intersected. Therefore, using substitution +* x~[j] = 1 - x[j] gives the packing inequality in generalized format: +* +* sum x[j] - sum x[j] <= 1 - |Jn|. (3) +* j in Jp j in Jn */ + +int npp_is_packing(NPP *npp, NPPROW *row) +{ /* test if constraint is packing inequality */ + NPPCOL *col; + NPPAIJ *aij; + int b; + xassert(npp == npp); + if (!(row->lb == -DBL_MAX && row->ub != +DBL_MAX)) + return 0; + b = 1; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + return 0; + if (aij->val == +1.0) + ; + else if (aij->val == -1.0) + b--; + else + return 0; + } + if (row->ub != (double)b) return 0; + return 1; +} + +/*********************************************************************** +* NAME +* +* npp_hidden_packing - identify hidden packing inequality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_hidden_packing(NPP *npp, NPPROW *row); +* +* DESCRIPTION +* +* The routine npp_hidden_packing processes specified inequality +* constraint, which includes only binary variables, and the number of +* the variables is not less than two. If the original inequality is +* equivalent to a packing inequality, the routine replaces it by this +* equivalent inequality. If the original constraint is double-sided +* inequality, it is replaced by a pair of single-sided inequalities, +* if necessary. +* +* RETURNS +* +* If the original inequality constraint was replaced by equivalent +* packing inequality, the routine npp_hidden_packing returns non-zero. +* Otherwise, it returns zero. +* +* PROBLEM TRANSFORMATION +* +* Consider an inequality constraint: +* +* sum a[j] x[j] <= b, (1) +* j in J +* +* where all variables x[j] are binary, and |J| >= 2. (In case of '>=' +* inequality it can be transformed to '<=' format by multiplying both +* its sides by -1.) +* +* Let Jp = {j: a[j] > 0}, Jn = {j: a[j] < 0}. Performing substitution +* x[j] = 1 - x~[j] for all j in Jn, we have: +* +* sum a[j] x[j] <= b ==> +* j in J +* +* sum a[j] x[j] + sum a[j] x[j] <= b ==> +* j in Jp j in Jn +* +* sum a[j] x[j] + sum a[j] (1 - x~[j]) <= b ==> +* j in Jp j in Jn +* +* sum a[j] x[j] - sum a[j] x~[j] <= b - sum a[j]. +* j in Jp j in Jn j in Jn +* +* Thus, meaning the transformation above, we can assume that in +* inequality (1) all coefficients a[j] are positive. Moreover, we can +* assume that a[j] <= b. In fact, let a[j] > b; then the following +* three cases are possible: +* +* 1) b < 0. In this case inequality (1) is infeasible, so the problem +* has no feasible solution (see the routine npp_analyze_row); +* +* 2) b = 0. In this case inequality (1) is a forcing inequality on its +* upper bound (see the routine npp_forcing row), from which it +* follows that all variables x[j] should be fixed at zero; +* +* 3) b > 0. In this case inequality (1) defines an implied zero upper +* bound for variable x[j] (see the routine npp_implied_bounds), from +* which it follows that x[j] should be fixed at zero. +* +* It is assumed that all three cases listed above have been recognized +* by the routine npp_process_prob, which performs basic MIP processing +* prior to a call the routine npp_hidden_packing. So, if one of these +* cases occurs, we should just skip processing such constraint. +* +* Thus, let 0 < a[j] <= b. Then it is obvious that constraint (1) is +* equivalent to packing inquality only if: +* +* a[j] + a[k] > b + eps (2) +* +* for all j, k in J, j != k, where eps is an absolute tolerance for +* row (linear form) value. Checking the condition (2) for all j and k, +* j != k, requires time O(|J|^2). However, this time can be reduced to +* O(|J|), if use minimal a[j] and a[k], in which case it is sufficient +* to check the condition (2) only once. +* +* Once the original inequality (1) is replaced by equivalent packing +* inequality, we need to perform back substitution x~[j] = 1 - x[j] for +* all j in Jn (see above). +* +* RECOVERING SOLUTION +* +* None needed. */ + +static int hidden_packing(NPP *npp, struct elem *ptr, double *_b) +{ /* process inequality constraint: sum a[j] x[j] <= b; + 0 - specified row is NOT hidden packing inequality; + 1 - specified row is packing inequality; + 2 - specified row is hidden packing inequality. */ + struct elem *e, *ej, *ek; + int neg; + double b = *_b, eps; + xassert(npp == npp); + /* a[j] must be non-zero, x[j] must be binary, for all j in J */ + for (e = ptr; e != NULL; e = e->next) + { xassert(e->aj != 0.0); + xassert(e->xj->is_int); + xassert(e->xj->lb == 0.0 && e->xj->ub == 1.0); + } + /* check if the specified inequality constraint already has the + form of packing inequality */ + neg = 0; /* neg is |Jn| */ + for (e = ptr; e != NULL; e = e->next) + { if (e->aj == +1.0) + ; + else if (e->aj == -1.0) + neg++; + else + break; + } + if (e == NULL) + { /* all coefficients a[j] are +1 or -1; check rhs b */ + if (b == (double)(1 - neg)) + { /* it is packing inequality; no processing is needed */ + return 1; + } + } + /* substitute x[j] = 1 - x~[j] for all j in Jn to make all a[j] + positive; the result is a~[j] = |a[j]| and new rhs b */ + for (e = ptr; e != NULL; e = e->next) + if (e->aj < 0) b -= e->aj; + /* now a[j] > 0 for all j in J (actually |a[j]| are used) */ + /* if a[j] > b, skip processing--this case must not appear */ + for (e = ptr; e != NULL; e = e->next) + if (fabs(e->aj) > b) return 0; + /* now 0 < a[j] <= b for all j in J */ + /* find two minimal coefficients a[j] and a[k], j != k */ + ej = NULL; + for (e = ptr; e != NULL; e = e->next) + if (ej == NULL || fabs(ej->aj) > fabs(e->aj)) ej = e; + xassert(ej != NULL); + ek = NULL; + for (e = ptr; e != NULL; e = e->next) + if (e != ej) + if (ek == NULL || fabs(ek->aj) > fabs(e->aj)) ek = e; + xassert(ek != NULL); + /* the specified constraint is equivalent to packing inequality + iff a[j] + a[k] > b + eps */ + eps = 1e-3 + 1e-6 * fabs(b); + if (fabs(ej->aj) + fabs(ek->aj) <= b + eps) return 0; + /* perform back substitution x~[j] = 1 - x[j] and construct the + final equivalent packing inequality in generalized format */ + b = 1.0; + for (e = ptr; e != NULL; e = e->next) + { if (e->aj > 0.0) + e->aj = +1.0; + else /* e->aj < 0.0 */ + e->aj = -1.0, b -= 1.0; + } + *_b = b; + return 2; +} + +int npp_hidden_packing(NPP *npp, NPPROW *row) +{ /* identify hidden packing inequality */ + NPPROW *copy; + NPPAIJ *aij; + struct elem *ptr, *e; + int kase, ret, count = 0; + double b; + /* the row must be inequality constraint */ + xassert(row->lb < row->ub); + for (kase = 0; kase <= 1; kase++) + { if (kase == 0) + { /* process row upper bound */ + if (row->ub == +DBL_MAX) continue; + ptr = copy_form(npp, row, +1.0); + b = + row->ub; + } + else + { /* process row lower bound */ + if (row->lb == -DBL_MAX) continue; + ptr = copy_form(npp, row, -1.0); + b = - row->lb; + } + /* now the inequality has the form "sum a[j] x[j] <= b" */ + ret = hidden_packing(npp, ptr, &b); + xassert(0 <= ret && ret <= 2); + if (kase == 1 && ret == 1 || ret == 2) + { /* the original inequality has been identified as hidden + packing inequality */ + count++; +#ifdef GLP_DEBUG + xprintf("Original constraint:\n"); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + xprintf(" %+g x%d", aij->val, aij->col->j); + if (row->lb != -DBL_MAX) xprintf(", >= %g", row->lb); + if (row->ub != +DBL_MAX) xprintf(", <= %g", row->ub); + xprintf("\n"); + xprintf("Equivalent packing inequality:\n"); + for (e = ptr; e != NULL; e = e->next) + xprintf(" %sx%d", e->aj > 0.0 ? "+" : "-", e->xj->j); + xprintf(", <= %g\n", b); +#endif + if (row->lb == -DBL_MAX || row->ub == +DBL_MAX) + { /* the original row is single-sided inequality; no copy + is needed */ + copy = NULL; + } + else + { /* the original row is double-sided inequality; we need + to create its copy for other bound before replacing it + with the equivalent inequality */ + copy = npp_add_row(npp); + if (kase == 0) + { /* the copy is for lower bound */ + copy->lb = row->lb, copy->ub = +DBL_MAX; + } + else + { /* the copy is for upper bound */ + copy->lb = -DBL_MAX, copy->ub = row->ub; + } + /* copy original row coefficients */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_add_aij(npp, copy, aij->col, aij->val); + } + /* replace the original inequality by equivalent one */ + npp_erase_row(npp, row); + row->lb = -DBL_MAX, row->ub = b; + for (e = ptr; e != NULL; e = e->next) + npp_add_aij(npp, row, e->xj, e->aj); + /* continue processing lower bound for the copy */ + if (copy != NULL) row = copy; + } + drop_form(npp, ptr); + } + return count; +} + +/*********************************************************************** +* NAME +* +* npp_implied_packing - identify implied packing inequality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_implied_packing(NPP *npp, NPPROW *row, int which, +* NPPCOL *var[], char set[]); +* +* DESCRIPTION +* +* The routine npp_implied_packing processes specified row (constraint) +* of general format: +* +* L <= sum a[j] x[j] <= U. (1) +* j +* +* If which = 0, only lower bound L, which must exist, is considered, +* while upper bound U is ignored. Similarly, if which = 1, only upper +* bound U, which must exist, is considered, while lower bound L is +* ignored. Thus, if the specified row is a double-sided inequality or +* equality constraint, this routine should be called twice for both +* lower and upper bounds. +* +* The routine npp_implied_packing attempts to find a non-trivial (i.e. +* having not less than two binary variables) packing inequality: +* +* sum x[j] - sum x[j] <= 1 - |Jn|, (2) +* j in Jp j in Jn +* +* which is relaxation of the constraint (1) in the sense that any +* solution satisfying to that constraint also satisfies to the packing +* inequality (2). If such relaxation exists, the routine stores +* pointers to descriptors of corresponding binary variables and their +* flags, resp., to locations var[1], var[2], ..., var[len] and set[1], +* set[2], ..., set[len], where set[j] = 0 means that j in Jp and +* set[j] = 1 means that j in Jn. +* +* RETURNS +* +* The routine npp_implied_packing returns len, which is the total +* number of binary variables in the packing inequality found, len >= 2. +* However, if the relaxation does not exist, the routine returns zero. +* +* ALGORITHM +* +* If which = 0, the constraint coefficients (1) are multiplied by -1 +* and b is assigned -L; if which = 1, the constraint coefficients (1) +* are not changed and b is assigned +U. In both cases the specified +* constraint gets the following format: +* +* sum a[j] x[j] <= b. (3) +* j +* +* (Note that (3) is a relaxation of (1), because one of bounds L or U +* is ignored.) +* +* Let J be set of binary variables, Kp be set of non-binary (integer +* or continuous) variables with a[j] > 0, and Kn be set of non-binary +* variables with a[j] < 0. Then the inequality (3) can be written as +* follows: +* +* sum a[j] x[j] <= b - sum a[j] x[j] - sum a[j] x[j]. (4) +* j in J j in Kp j in Kn +* +* To get rid of non-binary variables we can replace the inequality (4) +* by the following relaxed inequality: +* +* sum a[j] x[j] <= b~, (5) +* j in J +* +* where: +* +* b~ = sup(b - sum a[j] x[j] - sum a[j] x[j]) = +* j in Kp j in Kn +* +* = b - inf sum a[j] x[j] - inf sum a[j] x[j] = (6) +* j in Kp j in Kn +* +* = b - sum a[j] l[j] - sum a[j] u[j]. +* j in Kp j in Kn +* +* Note that if lower bound l[j] (if j in Kp) or upper bound u[j] +* (if j in Kn) of some non-binary variable x[j] does not exist, then +* formally b = +oo, in which case further analysis is not performed. +* +* Let Bp = {j in J: a[j] > 0}, Bn = {j in J: a[j] < 0}. To make all +* the inequality coefficients in (5) positive, we replace all x[j] in +* Bn by their complementaries, substituting x[j] = 1 - x~[j] for all +* j in Bn, that gives: +* +* sum a[j] x[j] - sum a[j] x~[j] <= b~ - sum a[j]. (7) +* j in Bp j in Bn j in Bn +* +* This inequality is a relaxation of the original constraint (1), and +* it is a binary knapsack inequality. Writing it in the standard format +* we have: +* +* sum alfa[j] z[j] <= beta, (8) +* j in J +* +* where: +* ( + a[j], if j in Bp, +* alfa[j] = < (9) +* ( - a[j], if j in Bn, +* +* ( x[j], if j in Bp, +* z[j] = < (10) +* ( 1 - x[j], if j in Bn, +* +* beta = b~ - sum a[j]. (11) +* j in Bn +* +* In the inequality (8) all coefficients are positive, therefore, the +* packing relaxation to be found for this inequality is the following: +* +* sum z[j] <= 1. (12) +* j in P +* +* It is obvious that set P within J, which we would like to find, must +* satisfy to the following condition: +* +* alfa[j] + alfa[k] > beta + eps for all j, k in P, j != k, (13) +* +* where eps is an absolute tolerance for value of the linear form. +* Thus, it is natural to take P = {j: alpha[j] > (beta + eps) / 2}. +* Moreover, if in the equality (8) there exist coefficients alfa[k], +* for which alfa[k] <= (beta + eps) / 2, but which, nevertheless, +* satisfies to the condition (13) for all j in P, *one* corresponding +* variable z[k] (having, for example, maximal coefficient alfa[k]) can +* be included in set P, that allows increasing the number of binary +* variables in (12) by one. +* +* Once the set P has been built, for the inequality (12) we need to +* perform back substitution according to (10) in order to express it +* through the original binary variables. As the result of such back +* substitution the relaxed packing inequality get its final format (2), +* where Jp = J intersect Bp, and Jn = J intersect Bn. */ + +int npp_implied_packing(NPP *npp, NPPROW *row, int which, + NPPCOL *var[], char set[]) +{ struct elem *ptr, *e, *i, *k; + int len = 0; + double b, eps; + /* build inequality (3) */ + if (which == 0) + { ptr = copy_form(npp, row, -1.0); + xassert(row->lb != -DBL_MAX); + b = - row->lb; + } + else if (which == 1) + { ptr = copy_form(npp, row, +1.0); + xassert(row->ub != +DBL_MAX); + b = + row->ub; + } + /* remove non-binary variables to build relaxed inequality (5); + compute its right-hand side b~ with formula (6) */ + for (e = ptr; e != NULL; e = e->next) + { if (!(e->xj->is_int && e->xj->lb == 0.0 && e->xj->ub == 1.0)) + { /* x[j] is non-binary variable */ + if (e->aj > 0.0) + { if (e->xj->lb == -DBL_MAX) goto done; + b -= e->aj * e->xj->lb; + } + else /* e->aj < 0.0 */ + { if (e->xj->ub == +DBL_MAX) goto done; + b -= e->aj * e->xj->ub; + } + /* a[j] = 0 means that variable x[j] is removed */ + e->aj = 0.0; + } + } + /* substitute x[j] = 1 - x~[j] to build knapsack inequality (8); + compute its right-hand side beta with formula (11) */ + for (e = ptr; e != NULL; e = e->next) + if (e->aj < 0.0) b -= e->aj; + /* if beta is close to zero, the knapsack inequality is either + infeasible or forcing inequality; this must never happen, so + we skip further analysis */ + if (b < 1e-3) goto done; + /* build set P as well as sets Jp and Jn, and determine x[k] as + explained above in comments to the routine */ + eps = 1e-3 + 1e-6 * b; + i = k = NULL; + for (e = ptr; e != NULL; e = e->next) + { /* note that alfa[j] = |a[j]| */ + if (fabs(e->aj) > 0.5 * (b + eps)) + { /* alfa[j] > (b + eps) / 2; include x[j] in set P, i.e. in + set Jp or Jn */ + var[++len] = e->xj; + set[len] = (char)(e->aj > 0.0 ? 0 : 1); + /* alfa[i] = min alfa[j] over all j included in set P */ + if (i == NULL || fabs(i->aj) > fabs(e->aj)) i = e; + } + else if (fabs(e->aj) >= 1e-3) + { /* alfa[k] = max alfa[j] over all j not included in set P; + we skip coefficient a[j] if it is close to zero to avoid + numerically unreliable results */ + if (k == NULL || fabs(k->aj) < fabs(e->aj)) k = e; + } + } + /* if alfa[k] satisfies to condition (13) for all j in P, include + x[k] in P */ + if (i != NULL && k != NULL && fabs(i->aj) + fabs(k->aj) > b + eps) + { var[++len] = k->xj; + set[len] = (char)(k->aj > 0.0 ? 0 : 1); + } + /* trivial packing inequality being redundant must never appear, + so we just ignore it */ + if (len < 2) len = 0; +done: drop_form(npp, ptr); + return len; +} + +/*********************************************************************** +* NAME +* +* npp_is_covering - test if constraint is covering inequality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_is_covering(NPP *npp, NPPROW *row); +* +* RETURNS +* +* If the specified row (constraint) is covering inequality (see below), +* the routine npp_is_covering returns non-zero. Otherwise, it returns +* zero. +* +* COVERING INEQUALITIES +* +* In canonical format the covering inequality is the following: +* +* sum x[j] >= 1, (1) +* j in J +* +* where all variables x[j] are binary. This inequality expresses the +* condition that in any integer feasible solution variables in set J +* cannot be all equal to zero at the same time, i.e. at least one +* variable must take non-zero (unity) value. W.l.o.g. it is assumed +* that |J| >= 2, because if J is empty, the inequality (1) is +* infeasible, and if |J| = 1, the inequality (1) is a forcing row. +* +* In general case the covering inequality may include original +* variables x[j] as well as their complements x~[j]: +* +* sum x[j] + sum x~[j] >= 1, (2) +* j in Jp j in Jn +* +* where Jp and Jn are not intersected. Therefore, using substitution +* x~[j] = 1 - x[j] gives the packing inequality in generalized format: +* +* sum x[j] - sum x[j] >= 1 - |Jn|. (3) +* j in Jp j in Jn +* +* (May note that the inequality (3) cuts off infeasible solutions, +* where x[j] = 0 for all j in Jp and x[j] = 1 for all j in Jn.) +* +* NOTE: If |J| = 2, the inequality (3) is equivalent to packing +* inequality (see the routine npp_is_packing). */ + +int npp_is_covering(NPP *npp, NPPROW *row) +{ /* test if constraint is covering inequality */ + NPPCOL *col; + NPPAIJ *aij; + int b; + xassert(npp == npp); + if (!(row->lb != -DBL_MAX && row->ub == +DBL_MAX)) + return 0; + b = 1; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + return 0; + if (aij->val == +1.0) + ; + else if (aij->val == -1.0) + b--; + else + return 0; + } + if (row->lb != (double)b) return 0; + return 1; +} + +/*********************************************************************** +* NAME +* +* npp_hidden_covering - identify hidden covering inequality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_hidden_covering(NPP *npp, NPPROW *row); +* +* DESCRIPTION +* +* The routine npp_hidden_covering processes specified inequality +* constraint, which includes only binary variables, and the number of +* the variables is not less than three. If the original inequality is +* equivalent to a covering inequality (see below), the routine +* replaces it by the equivalent inequality. If the original constraint +* is double-sided inequality, it is replaced by a pair of single-sided +* inequalities, if necessary. +* +* RETURNS +* +* If the original inequality constraint was replaced by equivalent +* covering inequality, the routine npp_hidden_covering returns +* non-zero. Otherwise, it returns zero. +* +* PROBLEM TRANSFORMATION +* +* Consider an inequality constraint: +* +* sum a[j] x[j] >= b, (1) +* j in J +* +* where all variables x[j] are binary, and |J| >= 3. (In case of '<=' +* inequality it can be transformed to '>=' format by multiplying both +* its sides by -1.) +* +* Let Jp = {j: a[j] > 0}, Jn = {j: a[j] < 0}. Performing substitution +* x[j] = 1 - x~[j] for all j in Jn, we have: +* +* sum a[j] x[j] >= b ==> +* j in J +* +* sum a[j] x[j] + sum a[j] x[j] >= b ==> +* j in Jp j in Jn +* +* sum a[j] x[j] + sum a[j] (1 - x~[j]) >= b ==> +* j in Jp j in Jn +* +* sum m a[j] x[j] - sum a[j] x~[j] >= b - sum a[j]. +* j in Jp j in Jn j in Jn +* +* Thus, meaning the transformation above, we can assume that in +* inequality (1) all coefficients a[j] are positive. Moreover, we can +* assume that b > 0, because otherwise the inequality (1) would be +* redundant (see the routine npp_analyze_row). It is then obvious that +* constraint (1) is equivalent to covering inequality only if: +* +* a[j] >= b, (2) +* +* for all j in J. +* +* Once the original inequality (1) is replaced by equivalent covering +* inequality, we need to perform back substitution x~[j] = 1 - x[j] for +* all j in Jn (see above). +* +* RECOVERING SOLUTION +* +* None needed. */ + +static int hidden_covering(NPP *npp, struct elem *ptr, double *_b) +{ /* process inequality constraint: sum a[j] x[j] >= b; + 0 - specified row is NOT hidden covering inequality; + 1 - specified row is covering inequality; + 2 - specified row is hidden covering inequality. */ + struct elem *e; + int neg; + double b = *_b, eps; + xassert(npp == npp); + /* a[j] must be non-zero, x[j] must be binary, for all j in J */ + for (e = ptr; e != NULL; e = e->next) + { xassert(e->aj != 0.0); + xassert(e->xj->is_int); + xassert(e->xj->lb == 0.0 && e->xj->ub == 1.0); + } + /* check if the specified inequality constraint already has the + form of covering inequality */ + neg = 0; /* neg is |Jn| */ + for (e = ptr; e != NULL; e = e->next) + { if (e->aj == +1.0) + ; + else if (e->aj == -1.0) + neg++; + else + break; + } + if (e == NULL) + { /* all coefficients a[j] are +1 or -1; check rhs b */ + if (b == (double)(1 - neg)) + { /* it is covering inequality; no processing is needed */ + return 1; + } + } + /* substitute x[j] = 1 - x~[j] for all j in Jn to make all a[j] + positive; the result is a~[j] = |a[j]| and new rhs b */ + for (e = ptr; e != NULL; e = e->next) + if (e->aj < 0) b -= e->aj; + /* now a[j] > 0 for all j in J (actually |a[j]| are used) */ + /* if b <= 0, skip processing--this case must not appear */ + if (b < 1e-3) return 0; + /* now a[j] > 0 for all j in J, and b > 0 */ + /* the specified constraint is equivalent to covering inequality + iff a[j] >= b for all j in J */ + eps = 1e-9 + 1e-12 * fabs(b); + for (e = ptr; e != NULL; e = e->next) + if (fabs(e->aj) < b - eps) return 0; + /* perform back substitution x~[j] = 1 - x[j] and construct the + final equivalent covering inequality in generalized format */ + b = 1.0; + for (e = ptr; e != NULL; e = e->next) + { if (e->aj > 0.0) + e->aj = +1.0; + else /* e->aj < 0.0 */ + e->aj = -1.0, b -= 1.0; + } + *_b = b; + return 2; +} + +int npp_hidden_covering(NPP *npp, NPPROW *row) +{ /* identify hidden covering inequality */ + NPPROW *copy; + NPPAIJ *aij; + struct elem *ptr, *e; + int kase, ret, count = 0; + double b; + /* the row must be inequality constraint */ + xassert(row->lb < row->ub); + for (kase = 0; kase <= 1; kase++) + { if (kase == 0) + { /* process row lower bound */ + if (row->lb == -DBL_MAX) continue; + ptr = copy_form(npp, row, +1.0); + b = + row->lb; + } + else + { /* process row upper bound */ + if (row->ub == +DBL_MAX) continue; + ptr = copy_form(npp, row, -1.0); + b = - row->ub; + } + /* now the inequality has the form "sum a[j] x[j] >= b" */ + ret = hidden_covering(npp, ptr, &b); + xassert(0 <= ret && ret <= 2); + if (kase == 1 && ret == 1 || ret == 2) + { /* the original inequality has been identified as hidden + covering inequality */ + count++; +#ifdef GLP_DEBUG + xprintf("Original constraint:\n"); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + xprintf(" %+g x%d", aij->val, aij->col->j); + if (row->lb != -DBL_MAX) xprintf(", >= %g", row->lb); + if (row->ub != +DBL_MAX) xprintf(", <= %g", row->ub); + xprintf("\n"); + xprintf("Equivalent covering inequality:\n"); + for (e = ptr; e != NULL; e = e->next) + xprintf(" %sx%d", e->aj > 0.0 ? "+" : "-", e->xj->j); + xprintf(", >= %g\n", b); +#endif + if (row->lb == -DBL_MAX || row->ub == +DBL_MAX) + { /* the original row is single-sided inequality; no copy + is needed */ + copy = NULL; + } + else + { /* the original row is double-sided inequality; we need + to create its copy for other bound before replacing it + with the equivalent inequality */ + copy = npp_add_row(npp); + if (kase == 0) + { /* the copy is for upper bound */ + copy->lb = -DBL_MAX, copy->ub = row->ub; + } + else + { /* the copy is for lower bound */ + copy->lb = row->lb, copy->ub = +DBL_MAX; + } + /* copy original row coefficients */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_add_aij(npp, copy, aij->col, aij->val); + } + /* replace the original inequality by equivalent one */ + npp_erase_row(npp, row); + row->lb = b, row->ub = +DBL_MAX; + for (e = ptr; e != NULL; e = e->next) + npp_add_aij(npp, row, e->xj, e->aj); + /* continue processing upper bound for the copy */ + if (copy != NULL) row = copy; + } + drop_form(npp, ptr); + } + return count; +} + +/*********************************************************************** +* NAME +* +* npp_is_partitioning - test if constraint is partitioning equality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_is_partitioning(NPP *npp, NPPROW *row); +* +* RETURNS +* +* If the specified row (constraint) is partitioning equality (see +* below), the routine npp_is_partitioning returns non-zero. Otherwise, +* it returns zero. +* +* PARTITIONING EQUALITIES +* +* In canonical format the partitioning equality is the following: +* +* sum x[j] = 1, (1) +* j in J +* +* where all variables x[j] are binary. This equality expresses the +* condition that in any integer feasible solution exactly one variable +* in set J must take non-zero (unity) value while other variables must +* be equal to zero. W.l.o.g. it is assumed that |J| >= 2, because if +* J is empty, the inequality (1) is infeasible, and if |J| = 1, the +* inequality (1) is a fixing row. +* +* In general case the partitioning equality may include original +* variables x[j] as well as their complements x~[j]: +* +* sum x[j] + sum x~[j] = 1, (2) +* j in Jp j in Jn +* +* where Jp and Jn are not intersected. Therefore, using substitution +* x~[j] = 1 - x[j] leads to the partitioning equality in generalized +* format: +* +* sum x[j] - sum x[j] = 1 - |Jn|. (3) +* j in Jp j in Jn */ + +int npp_is_partitioning(NPP *npp, NPPROW *row) +{ /* test if constraint is partitioning equality */ + NPPCOL *col; + NPPAIJ *aij; + int b; + xassert(npp == npp); + if (row->lb != row->ub) return 0; + b = 1; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + return 0; + if (aij->val == +1.0) + ; + else if (aij->val == -1.0) + b--; + else + return 0; + } + if (row->lb != (double)b) return 0; + return 1; +} + +/*********************************************************************** +* NAME +* +* npp_reduce_ineq_coef - reduce inequality constraint coefficients +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_reduce_ineq_coef(NPP *npp, NPPROW *row); +* +* DESCRIPTION +* +* The routine npp_reduce_ineq_coef processes specified inequality +* constraint attempting to replace it by an equivalent constraint, +* where magnitude of coefficients at binary variables is smaller than +* in the original constraint. If the inequality is double-sided, it is +* replaced by a pair of single-sided inequalities, if necessary. +* +* RETURNS +* +* The routine npp_reduce_ineq_coef returns the number of coefficients +* reduced. +* +* BACKGROUND +* +* Consider an inequality constraint: +* +* sum a[j] x[j] >= b. (1) +* j in J +* +* (In case of '<=' inequality it can be transformed to '>=' format by +* multiplying both its sides by -1.) Let x[k] be a binary variable; +* other variables can be integer as well as continuous. We can write +* constraint (1) as follows: +* +* a[k] x[k] + t[k] >= b, (2) +* +* where: +* +* t[k] = sum a[j] x[j]. (3) +* j in J\{k} +* +* Since x[k] is binary, constraint (2) is equivalent to disjunction of +* the following two constraints: +* +* x[k] = 0, t[k] >= b (4) +* +* OR +* +* x[k] = 1, t[k] >= b - a[k]. (5) +* +* Let also that for the partial sum t[k] be known some its implied +* lower bound inf t[k]. +* +* Case a[k] > 0. Let inf t[k] < b, since otherwise both constraints +* (4) and (5) and therefore constraint (2) are redundant. +* If inf t[k] > b - a[k], only constraint (5) is redundant, in which +* case it can be replaced with the following redundant and therefore +* equivalent constraint: +* +* t[k] >= b - a'[k] = inf t[k], (6) +* +* where: +* +* a'[k] = b - inf t[k]. (7) +* +* Thus, the original constraint (2) is equivalent to the following +* constraint with coefficient at variable x[k] changed: +* +* a'[k] x[k] + t[k] >= b. (8) +* +* From inf t[k] < b it follows that a'[k] > 0, i.e. the coefficient +* at x[k] keeps its sign. And from inf t[k] > b - a[k] it follows that +* a'[k] < a[k], i.e. the coefficient reduces in magnitude. +* +* Case a[k] < 0. Let inf t[k] < b - a[k], since otherwise both +* constraints (4) and (5) and therefore constraint (2) are redundant. +* If inf t[k] > b, only constraint (4) is redundant, in which case it +* can be replaced with the following redundant and therefore equivalent +* constraint: +* +* t[k] >= b' = inf t[k]. (9) +* +* Rewriting constraint (5) as follows: +* +* t[k] >= b - a[k] = b' - a'[k], (10) +* +* where: +* +* a'[k] = a[k] + b' - b = a[k] + inf t[k] - b, (11) +* +* we can see that disjunction of constraint (9) and (10) is equivalent +* to disjunction of constraint (4) and (5), from which it follows that +* the original constraint (2) is equivalent to the following constraint +* with both coefficient at variable x[k] and right-hand side changed: +* +* a'[k] x[k] + t[k] >= b'. (12) +* +* From inf t[k] < b - a[k] it follows that a'[k] < 0, i.e. the +* coefficient at x[k] keeps its sign. And from inf t[k] > b it follows +* that a'[k] > a[k], i.e. the coefficient reduces in magnitude. +* +* PROBLEM TRANSFORMATION +* +* In the routine npp_reduce_ineq_coef the following implied lower +* bound of the partial sum (3) is used: +* +* inf t[k] = sum a[j] l[j] + sum a[j] u[j], (13) +* j in Jp\{k} k in Jn\{k} +* +* where Jp = {j : a[j] > 0}, Jn = {j : a[j] < 0}, l[j] and u[j] are +* lower and upper bounds, resp., of variable x[j]. +* +* In order to compute inf t[k] more efficiently, the following formula, +* which is equivalent to (13), is actually used: +* +* ( h - a[k] l[k] = h, if a[k] > 0, +* inf t[k] = < (14) +* ( h - a[k] u[k] = h - a[k], if a[k] < 0, +* +* where: +* +* h = sum a[j] l[j] + sum a[j] u[j] (15) +* j in Jp j in Jn +* +* is the implied lower bound of row (1). +* +* Reduction of positive coefficient (a[k] > 0) does not change value +* of h, since l[k] = 0. In case of reduction of negative coefficient +* (a[k] < 0) from (11) it follows that: +* +* delta a[k] = a'[k] - a[k] = inf t[k] - b (> 0), (16) +* +* so new value of h (accounting that u[k] = 1) can be computed as +* follows: +* +* h := h + delta a[k] = h + (inf t[k] - b). (17) +* +* RECOVERING SOLUTION +* +* None needed. */ + +static int reduce_ineq_coef(NPP *npp, struct elem *ptr, double *_b) +{ /* process inequality constraint: sum a[j] x[j] >= b */ + /* returns: the number of coefficients reduced */ + struct elem *e; + int count = 0; + double h, inf_t, new_a, b = *_b; + xassert(npp == npp); + /* compute h; see (15) */ + h = 0.0; + for (e = ptr; e != NULL; e = e->next) + { if (e->aj > 0.0) + { if (e->xj->lb == -DBL_MAX) goto done; + h += e->aj * e->xj->lb; + } + else /* e->aj < 0.0 */ + { if (e->xj->ub == +DBL_MAX) goto done; + h += e->aj * e->xj->ub; + } + } + /* perform reduction of coefficients at binary variables */ + for (e = ptr; e != NULL; e = e->next) + { /* skip non-binary variable */ + if (!(e->xj->is_int && e->xj->lb == 0.0 && e->xj->ub == 1.0)) + continue; + if (e->aj > 0.0) + { /* compute inf t[k]; see (14) */ + inf_t = h; + if (b - e->aj < inf_t && inf_t < b) + { /* compute reduced coefficient a'[k]; see (7) */ + new_a = b - inf_t; + if (new_a >= +1e-3 && + e->aj - new_a >= 0.01 * (1.0 + e->aj)) + { /* accept a'[k] */ +#ifdef GLP_DEBUG + xprintf("+"); +#endif + e->aj = new_a; + count++; + } + } + } + else /* e->aj < 0.0 */ + { /* compute inf t[k]; see (14) */ + inf_t = h - e->aj; + if (b < inf_t && inf_t < b - e->aj) + { /* compute reduced coefficient a'[k]; see (11) */ + new_a = e->aj + (inf_t - b); + if (new_a <= -1e-3 && + new_a - e->aj >= 0.01 * (1.0 - e->aj)) + { /* accept a'[k] */ +#ifdef GLP_DEBUG + xprintf("-"); +#endif + e->aj = new_a; + /* update h; see (17) */ + h += (inf_t - b); + /* compute b'; see (9) */ + b = inf_t; + count++; + } + } + } + } + *_b = b; +done: return count; +} + +int npp_reduce_ineq_coef(NPP *npp, NPPROW *row) +{ /* reduce inequality constraint coefficients */ + NPPROW *copy; + NPPAIJ *aij; + struct elem *ptr, *e; + int kase, count[2]; + double b; + /* the row must be inequality constraint */ + xassert(row->lb < row->ub); + count[0] = count[1] = 0; + for (kase = 0; kase <= 1; kase++) + { if (kase == 0) + { /* process row lower bound */ + if (row->lb == -DBL_MAX) continue; +#ifdef GLP_DEBUG + xprintf("L"); +#endif + ptr = copy_form(npp, row, +1.0); + b = + row->lb; + } + else + { /* process row upper bound */ + if (row->ub == +DBL_MAX) continue; +#ifdef GLP_DEBUG + xprintf("U"); +#endif + ptr = copy_form(npp, row, -1.0); + b = - row->ub; + } + /* now the inequality has the form "sum a[j] x[j] >= b" */ + count[kase] = reduce_ineq_coef(npp, ptr, &b); + if (count[kase] > 0) + { /* the original inequality has been replaced by equivalent + one with coefficients reduced */ + if (row->lb == -DBL_MAX || row->ub == +DBL_MAX) + { /* the original row is single-sided inequality; no copy + is needed */ + copy = NULL; + } + else + { /* the original row is double-sided inequality; we need + to create its copy for other bound before replacing it + with the equivalent inequality */ +#ifdef GLP_DEBUG + xprintf("*"); +#endif + copy = npp_add_row(npp); + if (kase == 0) + { /* the copy is for upper bound */ + copy->lb = -DBL_MAX, copy->ub = row->ub; + } + else + { /* the copy is for lower bound */ + copy->lb = row->lb, copy->ub = +DBL_MAX; + } + /* copy original row coefficients */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_add_aij(npp, copy, aij->col, aij->val); + } + /* replace the original inequality by equivalent one */ + npp_erase_row(npp, row); + row->lb = b, row->ub = +DBL_MAX; + for (e = ptr; e != NULL; e = e->next) + npp_add_aij(npp, row, e->xj, e->aj); + /* continue processing upper bound for the copy */ + if (copy != NULL) row = copy; + } + drop_form(npp, ptr); + } + return count[0] + count[1]; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp05.c b/resources/3rdparty/glpk-4.53/src/glpnpp05.c new file mode 100644 index 000000000..8c8818508 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpnpp05.c @@ -0,0 +1,810 @@ +/* glpnpp05.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpnpp.h" + +/*********************************************************************** +* NAME +* +* npp_clean_prob - perform initial LP/MIP processing +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_clean_prob(NPP *npp); +* +* DESCRIPTION +* +* The routine npp_clean_prob performs initial LP/MIP processing that +* currently includes: +* +* 1) removing free rows; +* +* 2) replacing double-sided constraint rows with almost identical +* bounds, by equality constraint rows; +* +* 3) removing fixed columns; +* +* 4) replacing double-bounded columns with almost identical bounds by +* fixed columns and removing those columns; +* +* 5) initial processing constraint coefficients (not implemented); +* +* 6) initial processing objective coefficients (not implemented). */ + +void npp_clean_prob(NPP *npp) +{ /* perform initial LP/MIP processing */ + NPPROW *row, *next_row; + NPPCOL *col, *next_col; + int ret; + xassert(npp == npp); + /* process rows which originally are free */ + for (row = npp->r_head; row != NULL; row = next_row) + { next_row = row->next; + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + { /* process free row */ +#ifdef GLP_DEBUG + xprintf("1"); +#endif + npp_free_row(npp, row); + /* row was deleted */ + } + } + /* process rows which originally are double-sided inequalities */ + for (row = npp->r_head; row != NULL; row = next_row) + { next_row = row->next; + if (row->lb != -DBL_MAX && row->ub != +DBL_MAX && + row->lb < row->ub) + { ret = npp_make_equality(npp, row); + if (ret == 0) + ; + else if (ret == 1) + { /* row was replaced by equality constraint */ +#ifdef GLP_DEBUG + xprintf("2"); +#endif + } + else + xassert(ret != ret); + } + } + /* process columns which are originally fixed */ + for (col = npp->c_head; col != NULL; col = next_col) + { next_col = col->next; + if (col->lb == col->ub) + { /* process fixed column */ +#ifdef GLP_DEBUG + xprintf("3"); +#endif + npp_fixed_col(npp, col); + /* column was deleted */ + } + } + /* process columns which are originally double-bounded */ + for (col = npp->c_head; col != NULL; col = next_col) + { next_col = col->next; + if (col->lb != -DBL_MAX && col->ub != +DBL_MAX && + col->lb < col->ub) + { ret = npp_make_fixed(npp, col); + if (ret == 0) + ; + else if (ret == 1) + { /* column was replaced by fixed column; process it */ +#ifdef GLP_DEBUG + xprintf("4"); +#endif + npp_fixed_col(npp, col); + /* column was deleted */ + } + } + } + return; +} + +/*********************************************************************** +* NAME +* +* npp_process_row - perform basic row processing +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_process_row(NPP *npp, NPPROW *row, int hard); +* +* DESCRIPTION +* +* The routine npp_process_row performs basic row processing that +* currently includes: +* +* 1) removing empty row; +* +* 2) removing equality constraint row singleton and corresponding +* column; +* +* 3) removing inequality constraint row singleton and corresponding +* column if it was fixed; +* +* 4) performing general row analysis; +* +* 5) removing redundant row bounds; +* +* 6) removing forcing row and corresponding columns; +* +* 7) removing row which becomes free due to redundant bounds; +* +* 8) computing implied bounds for all columns in the row and using +* them to strengthen current column bounds (MIP only, optional, +* performed if the flag hard is on). +* +* Additionally the routine may activate affected rows and/or columns +* for further processing. +* +* RETURNS +* +* 0 success; +* +* GLP_ENOPFS primal/integer infeasibility detected; +* +* GLP_ENODFS dual infeasibility detected. */ + +int npp_process_row(NPP *npp, NPPROW *row, int hard) +{ /* perform basic row processing */ + NPPCOL *col; + NPPAIJ *aij, *next_aij, *aaa; + int ret; + /* row must not be free */ + xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX)); + /* start processing row */ + if (row->ptr == NULL) + { /* empty row */ + ret = npp_empty_row(npp, row); + if (ret == 0) + { /* row was deleted */ +#ifdef GLP_DEBUG + xprintf("A"); +#endif + return 0; + } + else if (ret == 1) + { /* primal infeasibility */ + return GLP_ENOPFS; + } + else + xassert(ret != ret); + } + if (row->ptr->r_next == NULL) + { /* row singleton */ + col = row->ptr->col; + if (row->lb == row->ub) + { /* equality constraint */ + ret = npp_eq_singlet(npp, row); + if (ret == 0) + { /* column was fixed, row was deleted */ +#ifdef GLP_DEBUG + xprintf("B"); +#endif + /* activate rows affected by column */ + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + npp_activate_row(npp, aij->row); + /* process fixed column */ + npp_fixed_col(npp, col); + /* column was deleted */ + return 0; + } + else if (ret == 1 || ret == 2) + { /* primal/integer infeasibility */ + return GLP_ENOPFS; + } + else + xassert(ret != ret); + } + else + { /* inequality constraint */ + ret = npp_ineq_singlet(npp, row); + if (0 <= ret && ret <= 3) + { /* row was deleted */ +#ifdef GLP_DEBUG + xprintf("C"); +#endif + /* activate column, since its length was changed due to + row deletion */ + npp_activate_col(npp, col); + if (ret >= 2) + { /* column bounds changed significantly or column was + fixed */ + /* activate rows affected by column */ + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + npp_activate_row(npp, aij->row); + } + if (ret == 3) + { /* column was fixed; process it */ +#ifdef GLP_DEBUG + xprintf("D"); +#endif + npp_fixed_col(npp, col); + /* column was deleted */ + } + return 0; + } + else if (ret == 4) + { /* primal infeasibility */ + return GLP_ENOPFS; + } + else + xassert(ret != ret); + } + } +#if 0 + /* sometimes this causes too large round-off errors; probably + pivot coefficient should be chosen more carefully */ + if (row->ptr->r_next->r_next == NULL) + { /* row doubleton */ + if (row->lb == row->ub) + { /* equality constraint */ + if (!(row->ptr->col->is_int || + row->ptr->r_next->col->is_int)) + { /* both columns are continuous */ + NPPCOL *q; + q = npp_eq_doublet(npp, row); + if (q != NULL) + { /* column q was eliminated */ +#ifdef GLP_DEBUG + xprintf("E"); +#endif + /* now column q is singleton of type "implied slack + variable"; we process it here to make sure that on + recovering basic solution the row is always active + equality constraint (as required by the routine + rcv_eq_doublet) */ + xassert(npp_process_col(npp, q) == 0); + /* column q was deleted; note that row p also may be + deleted */ + return 0; + } + } + } + } +#endif + /* general row analysis */ + ret = npp_analyze_row(npp, row); + xassert(0x00 <= ret && ret <= 0xFF); + if (ret == 0x33) + { /* row bounds are inconsistent with column bounds */ + return GLP_ENOPFS; + } + if ((ret & 0x0F) == 0x00) + { /* row lower bound does not exist or redundant */ + if (row->lb != -DBL_MAX) + { /* remove redundant row lower bound */ +#ifdef GLP_DEBUG + xprintf("F"); +#endif + npp_inactive_bound(npp, row, 0); + } + } + else if ((ret & 0x0F) == 0x01) + { /* row lower bound can be active */ + /* see below */ + } + else if ((ret & 0x0F) == 0x02) + { /* row lower bound is a forcing bound */ +#ifdef GLP_DEBUG + xprintf("G"); +#endif + /* process forcing row */ + if (npp_forcing_row(npp, row, 0) == 0) +fixup: { /* columns were fixed, row was made free */ + for (aij = row->ptr; aij != NULL; aij = next_aij) + { /* process column fixed by forcing row */ +#ifdef GLP_DEBUG + xprintf("H"); +#endif + col = aij->col; + next_aij = aij->r_next; + /* activate rows affected by column */ + for (aaa = col->ptr; aaa != NULL; aaa = aaa->c_next) + npp_activate_row(npp, aaa->row); + /* process fixed column */ + npp_fixed_col(npp, col); + /* column was deleted */ + } + /* process free row (which now is empty due to deletion of + all its columns) */ + npp_free_row(npp, row); + /* row was deleted */ + return 0; + } + } + else + xassert(ret != ret); + if ((ret & 0xF0) == 0x00) + { /* row upper bound does not exist or redundant */ + if (row->ub != +DBL_MAX) + { /* remove redundant row upper bound */ +#ifdef GLP_DEBUG + xprintf("I"); +#endif + npp_inactive_bound(npp, row, 1); + } + } + else if ((ret & 0xF0) == 0x10) + { /* row upper bound can be active */ + /* see below */ + } + else if ((ret & 0xF0) == 0x20) + { /* row upper bound is a forcing bound */ +#ifdef GLP_DEBUG + xprintf("J"); +#endif + /* process forcing row */ + if (npp_forcing_row(npp, row, 1) == 0) goto fixup; + } + else + xassert(ret != ret); + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + { /* row became free due to redundant bounds removal */ +#ifdef GLP_DEBUG + xprintf("K"); +#endif + /* activate its columns, since their length will change due + to row deletion */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_activate_col(npp, aij->col); + /* process free row */ + npp_free_row(npp, row); + /* row was deleted */ + return 0; + } +#if 1 /* 23/XII-2009 */ + /* row lower and/or upper bounds can be active */ + if (npp->sol == GLP_MIP && hard) + { /* improve current column bounds (optional) */ + if (npp_improve_bounds(npp, row, 1) < 0) + return GLP_ENOPFS; + } +#endif + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_improve_bounds - improve current column bounds +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_improve_bounds(NPP *npp, NPPROW *row, int flag); +* +* DESCRIPTION +* +* The routine npp_improve_bounds analyzes specified row (inequality +* or equality constraint) to determine implied column bounds and then +* uses these bounds to improve (strengthen) current column bounds. +* +* If the flag is on and current column bounds changed significantly +* or the column was fixed, the routine activate rows affected by the +* column for further processing. (This feature is intended to be used +* in the main loop of the routine npp_process_row.) +* +* NOTE: This operation can be used for MIP problem only. +* +* RETURNS +* +* The routine npp_improve_bounds returns the number of significantly +* changed bounds plus the number of column having been fixed due to +* bound improvements. However, if the routine detects primal/integer +* infeasibility, it returns a negative value. */ + +int npp_improve_bounds(NPP *npp, NPPROW *row, int flag) +{ /* improve current column bounds */ + NPPCOL *col; + NPPAIJ *aij, *next_aij, *aaa; + int kase, ret, count = 0; + double lb, ub; + xassert(npp->sol == GLP_MIP); + /* row must not be free */ + xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX)); + /* determine implied column bounds */ + npp_implied_bounds(npp, row); + /* and use these bounds to strengthen current column bounds */ + for (aij = row->ptr; aij != NULL; aij = next_aij) + { col = aij->col; + next_aij = aij->r_next; + for (kase = 0; kase <= 1; kase++) + { /* save current column bounds */ + lb = col->lb, ub = col->ub; + if (kase == 0) + { /* process implied column lower bound */ + if (col->ll.ll == -DBL_MAX) continue; + ret = npp_implied_lower(npp, col, col->ll.ll); + } + else + { /* process implied column upper bound */ + if (col->uu.uu == +DBL_MAX) continue; + ret = npp_implied_upper(npp, col, col->uu.uu); + } + if (ret == 0 || ret == 1) + { /* current column bounds did not change or changed, but + not significantly; restore current column bounds */ + col->lb = lb, col->ub = ub; + } + else if (ret == 2 || ret == 3) + { /* current column bounds changed significantly or column + was fixed */ +#ifdef GLP_DEBUG + xprintf("L"); +#endif + count++; + /* activate other rows affected by column, if required */ + if (flag) + { for (aaa = col->ptr; aaa != NULL; aaa = aaa->c_next) + { if (aaa->row != row) + npp_activate_row(npp, aaa->row); + } + } + if (ret == 3) + { /* process fixed column */ +#ifdef GLP_DEBUG + xprintf("M"); +#endif + npp_fixed_col(npp, col); + /* column was deleted */ + break; /* for kase */ + } + } + else if (ret == 4) + { /* primal/integer infeasibility */ + return -1; + } + else + xassert(ret != ret); + } + } + return count; +} + +/*********************************************************************** +* NAME +* +* npp_process_col - perform basic column processing +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_process_col(NPP *npp, NPPCOL *col); +* +* DESCRIPTION +* +* The routine npp_process_col performs basic column processing that +* currently includes: +* +* 1) fixing and removing empty column; +* +* 2) removing column singleton, which is implied slack variable, and +* corresponding row if it becomes free; +* +* 3) removing bounds of column, which is implied free variable, and +* replacing corresponding row by equality constraint. +* +* Additionally the routine may activate affected rows and/or columns +* for further processing. +* +* RETURNS +* +* 0 success; +* +* GLP_ENOPFS primal/integer infeasibility detected; +* +* GLP_ENODFS dual infeasibility detected. */ + +int npp_process_col(NPP *npp, NPPCOL *col) +{ /* perform basic column processing */ + NPPROW *row; + NPPAIJ *aij; + int ret; + /* column must not be fixed */ + xassert(col->lb < col->ub); + /* start processing column */ + if (col->ptr == NULL) + { /* empty column */ + ret = npp_empty_col(npp, col); + if (ret == 0) + { /* column was fixed and deleted */ +#ifdef GLP_DEBUG + xprintf("N"); +#endif + return 0; + } + else if (ret == 1) + { /* dual infeasibility */ + return GLP_ENODFS; + } + else + xassert(ret != ret); + } + if (col->ptr->c_next == NULL) + { /* column singleton */ + row = col->ptr->row; + if (row->lb == row->ub) + { /* equality constraint */ + if (!col->is_int) +slack: { /* implied slack variable */ +#ifdef GLP_DEBUG + xprintf("O"); +#endif + npp_implied_slack(npp, col); + /* column was deleted */ + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + { /* row became free due to implied slack variable */ +#ifdef GLP_DEBUG + xprintf("P"); +#endif + /* activate columns affected by row */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_activate_col(npp, aij->col); + /* process free row */ + npp_free_row(npp, row); + /* row was deleted */ + } + else + { /* row became inequality constraint; activate it + since its length changed due to column deletion */ + npp_activate_row(npp, row); + } + return 0; + } + } + else + { /* inequality constraint */ + if (!col->is_int) + { ret = npp_implied_free(npp, col); + if (ret == 0) + { /* implied free variable */ +#ifdef GLP_DEBUG + xprintf("Q"); +#endif + /* column bounds were removed, row was replaced by + equality constraint */ + goto slack; + } + else if (ret == 1) + { /* column is not implied free variable, because its + lower and/or upper bounds can be active */ + } + else if (ret == 2) + { /* dual infeasibility */ + return GLP_ENODFS; + } + } + } + } + /* column still exists */ + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_process_prob - perform basic LP/MIP processing +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_process_prob(NPP *npp, int hard); +* +* DESCRIPTION +* +* The routine npp_process_prob performs basic LP/MIP processing that +* currently includes: +* +* 1) initial LP/MIP processing (see the routine npp_clean_prob), +* +* 2) basic row processing (see the routine npp_process_row), and +* +* 3) basic column processing (see the routine npp_process_col). +* +* If the flag hard is on, the routine attempts to improve current +* column bounds multiple times within the main processing loop, in +* which case this feature may take a time. Otherwise, if the flag hard +* is off, improving column bounds is performed only once at the end of +* the main loop. (Note that this feature is used for MIP only.) +* +* The routine uses two sets: the set of active rows and the set of +* active columns. Rows/columns are marked by a flag (the field temp in +* NPPROW/NPPCOL). If the flag is non-zero, the row/column is active, +* in which case it is placed in the beginning of the row/column list; +* otherwise, if the flag is zero, the row/column is inactive, in which +* case it is placed in the end of the row/column list. If a row/column +* being currently processed may affect other rows/columns, the latters +* are activated for further processing. +* +* RETURNS +* +* 0 success; +* +* GLP_ENOPFS primal/integer infeasibility detected; +* +* GLP_ENODFS dual infeasibility detected. */ + +int npp_process_prob(NPP *npp, int hard) +{ /* perform basic LP/MIP processing */ + NPPROW *row; + NPPCOL *col; + int processing, ret; + /* perform initial LP/MIP processing */ + npp_clean_prob(npp); + /* activate all remaining rows and columns */ + for (row = npp->r_head; row != NULL; row = row->next) + row->temp = 1; + for (col = npp->c_head; col != NULL; col = col->next) + col->temp = 1; + /* main processing loop */ + processing = 1; + while (processing) + { processing = 0; + /* process all active rows */ + for (;;) + { row = npp->r_head; + if (row == NULL || !row->temp) break; + npp_deactivate_row(npp, row); + ret = npp_process_row(npp, row, hard); + if (ret != 0) goto done; + processing = 1; + } + /* process all active columns */ + for (;;) + { col = npp->c_head; + if (col == NULL || !col->temp) break; + npp_deactivate_col(npp, col); + ret = npp_process_col(npp, col); + if (ret != 0) goto done; + processing = 1; + } + } +#if 1 /* 23/XII-2009 */ + if (npp->sol == GLP_MIP && !hard) + { /* improve current column bounds (optional) */ + for (row = npp->r_head; row != NULL; row = row->next) + { if (npp_improve_bounds(npp, row, 0) < 0) + { ret = GLP_ENOPFS; + goto done; + } + } + } +#endif + /* all seems ok */ + ret = 0; +done: xassert(ret == 0 || ret == GLP_ENOPFS || ret == GLP_ENODFS); +#ifdef GLP_DEBUG + xprintf("\n"); +#endif + return ret; +} + +/**********************************************************************/ + +int npp_simplex(NPP *npp, const glp_smcp *parm) +{ /* process LP prior to applying primal/dual simplex method */ + int ret; + xassert(npp->sol == GLP_SOL); + xassert(parm == parm); + ret = npp_process_prob(npp, 0); + return ret; +} + +/**********************************************************************/ + +int npp_integer(NPP *npp, const glp_iocp *parm) +{ /* process MIP prior to applying branch-and-bound method */ + NPPROW *row, *prev_row; + NPPCOL *col; + NPPAIJ *aij; + int count, ret; + xassert(npp->sol == GLP_MIP); + xassert(parm == parm); + /*==============================================================*/ + /* perform basic MIP processing */ + ret = npp_process_prob(npp, 1); + if (ret != 0) goto done; + /*==============================================================*/ + /* binarize problem, if required */ + if (parm->binarize) + npp_binarize_prob(npp); + /*==============================================================*/ + /* identify hidden packing inequalities */ + count = 0; + /* new rows will be added to the end of the row list, so we go + from the end to beginning of the row list */ + for (row = npp->r_tail; row != NULL; row = prev_row) + { prev_row = row->prev; + /* skip free row */ + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) continue; + /* skip equality constraint */ + if (row->lb == row->ub) continue; + /* skip row having less than two variables */ + if (row->ptr == NULL || row->ptr->r_next == NULL) continue; + /* skip row having non-binary variables */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + break; + } + if (aij != NULL) continue; + count += npp_hidden_packing(npp, row); + } + if (count > 0) + xprintf("%d hidden packing inequaliti(es) were detected\n", + count); + /*==============================================================*/ + /* identify hidden covering inequalities */ + count = 0; + /* new rows will be added to the end of the row list, so we go + from the end to beginning of the row list */ + for (row = npp->r_tail; row != NULL; row = prev_row) + { prev_row = row->prev; + /* skip free row */ + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) continue; + /* skip equality constraint */ + if (row->lb == row->ub) continue; + /* skip row having less than three variables */ + if (row->ptr == NULL || row->ptr->r_next == NULL || + row->ptr->r_next->r_next == NULL) continue; + /* skip row having non-binary variables */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + break; + } + if (aij != NULL) continue; + count += npp_hidden_covering(npp, row); + } + if (count > 0) + xprintf("%d hidden covering inequaliti(es) were detected\n", + count); + /*==============================================================*/ + /* reduce inequality constraint coefficients */ + count = 0; + /* new rows will be added to the end of the row list, so we go + from the end to beginning of the row list */ + for (row = npp->r_tail; row != NULL; row = prev_row) + { prev_row = row->prev; + /* skip equality constraint */ + if (row->lb == row->ub) continue; + count += npp_reduce_ineq_coef(npp, row); + } + if (count > 0) + xprintf("%d constraint coefficient(s) were reduced\n", count); + /*==============================================================*/ +#ifdef GLP_DEBUG + routine(npp); +#endif + /*==============================================================*/ + /* all seems ok */ + ret = 0; +done: return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp06.c b/resources/3rdparty/glpk-4.53/src/glpnpp06.c new file mode 100644 index 000000000..57d283ec9 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpnpp06.c @@ -0,0 +1,1501 @@ +/* glpnpp06.c (translate feasibility problem to CNF-SAT) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpnpp.h" + +/*********************************************************************** +* npp_sat_free_row - process free (unbounded) row +* +* This routine processes row p, which is free (i.e. has no finite +* bounds): +* +* -inf < sum a[p,j] x[j] < +inf. (1) +* +* The constraint (1) cannot be active and therefore it is redundant, +* so the routine simply removes it from the original problem. */ + +void npp_sat_free_row(NPP *npp, NPPROW *p) +{ /* the row should be free */ + xassert(p->lb == -DBL_MAX && p->ub == +DBL_MAX); + /* remove the row from the problem */ + npp_del_row(npp, p); + return; +} + +/*********************************************************************** +* npp_sat_fixed_col - process fixed column +* +* This routine processes column q, which is fixed: +* +* x[q] = s[q], (1) +* +* where s[q] is a fixed column value. +* +* The routine substitutes fixed value s[q] into constraint rows and +* then removes column x[q] from the original problem. +* +* Substitution of x[q] = s[q] into row i gives: +* +* L[i] <= sum a[i,j] x[j] <= U[i] ==> +* j +* +* L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> +* j!=q +* +* L[i] <= sum a[i,j] x[j] + a[i,q] s[q] <= U[i] ==> +* j!=q +* +* L~[i] <= sum a[i,j] x[j] <= U~[i], +* j!=q +* +* where +* +* L~[i] = L[i] - a[i,q] s[q], (2) +* +* U~[i] = U[i] - a[i,q] s[q] (3) +* +* are, respectively, lower and upper bound of row i in the transformed +* problem. +* +* On recovering solution x[q] is assigned the value of s[q]. */ + +struct sat_fixed_col +{ /* fixed column */ + int q; + /* column reference number for variable x[q] */ + int s; + /* value, at which x[q] is fixed */ +}; + +static int rcv_sat_fixed_col(NPP *, void *); + +int npp_sat_fixed_col(NPP *npp, NPPCOL *q) +{ struct sat_fixed_col *info; + NPPROW *i; + NPPAIJ *aij; + int temp; + /* the column should be fixed */ + xassert(q->lb == q->ub); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_sat_fixed_col, sizeof(struct sat_fixed_col)); + info->q = q->j; + info->s = (int)q->lb; + xassert((double)info->s == q->lb); + /* substitute x[q] = s[q] into constraint rows */ + if (info->s == 0) + goto skip; + for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row; + if (i->lb != -DBL_MAX) + { i->lb -= aij->val * (double)info->s; + temp = (int)i->lb; + if ((double)temp != i->lb) + return 1; /* integer arithmetic error */ + } + if (i->ub != +DBL_MAX) + { i->ub -= aij->val * (double)info->s; + temp = (int)i->ub; + if ((double)temp != i->ub) + return 2; /* integer arithmetic error */ + } + } +skip: /* remove the column from the problem */ + npp_del_col(npp, q); + return 0; +} + +static int rcv_sat_fixed_col(NPP *npp, void *info_) +{ struct sat_fixed_col *info = info_; + npp->c_value[info->q] = (double)info->s; + return 0; +} + +/*********************************************************************** +* npp_sat_is_bin_comb - test if row is binary combination +* +* This routine tests if the specified row is a binary combination, +* i.e. all its constraint coefficients are +1 and -1 and all variables +* are binary. If the test was passed, the routine returns non-zero, +* otherwise zero. */ + +int npp_sat_is_bin_comb(NPP *npp, NPPROW *row) +{ NPPCOL *col; + NPPAIJ *aij; + xassert(npp == npp); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { if (!(aij->val == +1.0 || aij->val == -1.0)) + return 0; /* non-unity coefficient */ + col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + return 0; /* non-binary column */ + } + return 1; /* test was passed */ +} + +/*********************************************************************** +* npp_sat_num_pos_coef - determine number of positive coefficients +* +* This routine returns the number of positive coefficients in the +* specified row. */ + +int npp_sat_num_pos_coef(NPP *npp, NPPROW *row) +{ NPPAIJ *aij; + int num = 0; + xassert(npp == npp); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { if (aij->val > 0.0) + num++; + } + return num; +} + +/*********************************************************************** +* npp_sat_num_neg_coef - determine number of negative coefficients +* +* This routine returns the number of negative coefficients in the +* specified row. */ + +int npp_sat_num_neg_coef(NPP *npp, NPPROW *row) +{ NPPAIJ *aij; + int num = 0; + xassert(npp == npp); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { if (aij->val < 0.0) + num++; + } + return num; +} + +/*********************************************************************** +* npp_sat_is_cover_ineq - test if row is covering inequality +* +* The canonical form of a covering inequality is the following: +* +* sum x[j] >= 1, (1) +* j in J +* +* where all x[j] are binary variables. +* +* In general case a covering inequality may have one of the following +* two forms: +* +* sum x[j] - sum x[j] >= 1 - |J-|, (2) +* j in J+ j in J- +* +* +* sum x[j] - sum x[j] <= |J+| - 1. (3) +* j in J+ j in J- +* +* Obviously, the inequality (2) can be transformed to the form (1) by +* substitution x[j] = 1 - x'[j] for all j in J-, where x'[j] is the +* negation of variable x[j]. And the inequality (3) can be transformed +* to (2) by multiplying both left- and right-hand sides by -1. +* +* This routine returns one of the following codes: +* +* 0, if the specified row is not a covering inequality; +* +* 1, if the specified row has the form (2); +* +* 2, if the specified row has the form (3). */ + +int npp_sat_is_cover_ineq(NPP *npp, NPPROW *row) +{ xassert(npp == npp); + if (row->lb != -DBL_MAX && row->ub == +DBL_MAX) + { /* row is inequality of '>=' type */ + if (npp_sat_is_bin_comb(npp, row)) + { /* row is a binary combination */ + if (row->lb == 1.0 - npp_sat_num_neg_coef(npp, row)) + { /* row has the form (2) */ + return 1; + } + } + } + else if (row->lb == -DBL_MAX && row->ub != +DBL_MAX) + { /* row is inequality of '<=' type */ + if (npp_sat_is_bin_comb(npp, row)) + { /* row is a binary combination */ + if (row->ub == npp_sat_num_pos_coef(npp, row) - 1.0) + { /* row has the form (3) */ + return 2; + } + } + } + /* row is not a covering inequality */ + return 0; +} + +/*********************************************************************** +* npp_sat_is_pack_ineq - test if row is packing inequality +* +* The canonical form of a packing inequality is the following: +* +* sum x[j] <= 1, (1) +* j in J +* +* where all x[j] are binary variables. +* +* In general case a packing inequality may have one of the following +* two forms: +* +* sum x[j] - sum x[j] <= 1 - |J-|, (2) +* j in J+ j in J- +* +* +* sum x[j] - sum x[j] >= |J+| - 1. (3) +* j in J+ j in J- +* +* Obviously, the inequality (2) can be transformed to the form (1) by +* substitution x[j] = 1 - x'[j] for all j in J-, where x'[j] is the +* negation of variable x[j]. And the inequality (3) can be transformed +* to (2) by multiplying both left- and right-hand sides by -1. +* +* This routine returns one of the following codes: +* +* 0, if the specified row is not a packing inequality; +* +* 1, if the specified row has the form (2); +* +* 2, if the specified row has the form (3). */ + +int npp_sat_is_pack_ineq(NPP *npp, NPPROW *row) +{ xassert(npp == npp); + if (row->lb == -DBL_MAX && row->ub != +DBL_MAX) + { /* row is inequality of '<=' type */ + if (npp_sat_is_bin_comb(npp, row)) + { /* row is a binary combination */ + if (row->ub == 1.0 - npp_sat_num_neg_coef(npp, row)) + { /* row has the form (2) */ + return 1; + } + } + } + else if (row->lb != -DBL_MAX && row->ub == +DBL_MAX) + { /* row is inequality of '>=' type */ + if (npp_sat_is_bin_comb(npp, row)) + { /* row is a binary combination */ + if (row->lb == npp_sat_num_pos_coef(npp, row) - 1.0) + { /* row has the form (3) */ + return 2; + } + } + } + /* row is not a packing inequality */ + return 0; +} + +/*********************************************************************** +* npp_sat_is_partn_eq - test if row is partitioning equality +* +* The canonical form of a partitioning equality is the following: +* +* sum x[j] = 1, (1) +* j in J +* +* where all x[j] are binary variables. +* +* In general case a partitioning equality may have one of the following +* two forms: +* +* sum x[j] - sum x[j] = 1 - |J-|, (2) +* j in J+ j in J- +* +* +* sum x[j] - sum x[j] = |J+| - 1. (3) +* j in J+ j in J- +* +* Obviously, the equality (2) can be transformed to the form (1) by +* substitution x[j] = 1 - x'[j] for all j in J-, where x'[j] is the +* negation of variable x[j]. And the equality (3) can be transformed +* to (2) by multiplying both left- and right-hand sides by -1. +* +* This routine returns one of the following codes: +* +* 0, if the specified row is not a partitioning equality; +* +* 1, if the specified row has the form (2); +* +* 2, if the specified row has the form (3). */ + +int npp_sat_is_partn_eq(NPP *npp, NPPROW *row) +{ xassert(npp == npp); + if (row->lb == row->ub) + { /* row is equality constraint */ + if (npp_sat_is_bin_comb(npp, row)) + { /* row is a binary combination */ + if (row->lb == 1.0 - npp_sat_num_neg_coef(npp, row)) + { /* row has the form (2) */ + return 1; + } + if (row->ub == npp_sat_num_pos_coef(npp, row) - 1.0) + { /* row has the form (3) */ + return 2; + } + } + } + /* row is not a partitioning equality */ + return 0; +} + +/*********************************************************************** +* npp_sat_reverse_row - multiply both sides of row by -1 +* +* This routines multiplies by -1 both left- and right-hand sides of +* the specified row: +* +* L <= sum x[j] <= U, +* +* that results in the following row: +* +* -U <= sum (-x[j]) <= -L. +* +* If no integer overflow occured, the routine returns zero, otherwise +* non-zero. */ + +int npp_sat_reverse_row(NPP *npp, NPPROW *row) +{ NPPAIJ *aij; + int temp, ret = 0; + double old_lb, old_ub; + xassert(npp == npp); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { aij->val = -aij->val; + temp = (int)aij->val; + if ((double)temp != aij->val) + ret = 1; + } + old_lb = row->lb, old_ub = row->ub; + if (old_ub == +DBL_MAX) + row->lb = -DBL_MAX; + else + { row->lb = -old_ub; + temp = (int)row->lb; + if ((double)temp != row->lb) + ret = 2; + } + if (old_lb == -DBL_MAX) + row->ub = +DBL_MAX; + else + { row->ub = -old_lb; + temp = (int)row->ub; + if ((double)temp != row->ub) + ret = 3; + } + return ret; +} + +/*********************************************************************** +* npp_sat_split_pack - split packing inequality +* +* Let there be given a packing inequality in canonical form: +* +* sum t[j] <= 1, (1) +* j in J +* +* where t[j] = x[j] or t[j] = 1 - x[j], x[j] is a binary variable. +* And let J = J1 U J2 is a partition of the set of literals. Then the +* inequality (1) is obviously equivalent to the following two packing +* inequalities: +* +* sum t[j] <= y <--> sum t[j] + (1 - y) <= 1, (2) +* j in J1 j in J1 +* +* sum t[j] <= 1 - y <--> sum t[j] + y <= 1, (3) +* j in J2 j in J2 +* +* where y is a new binary variable added to the transformed problem. +* +* Assuming that the specified row is a packing inequality (1), this +* routine constructs the set J1 by including there first nlit literals +* (terms) from the specified row, and the set J2 = J \ J1. Then the +* routine creates a new row, which corresponds to inequality (2), and +* replaces the specified row with inequality (3). */ + +NPPROW *npp_sat_split_pack(NPP *npp, NPPROW *row, int nlit) +{ NPPROW *rrr; + NPPCOL *col; + NPPAIJ *aij; + int k; + /* original row should be packing inequality (1) */ + xassert(npp_sat_is_pack_ineq(npp, row) == 1); + /* and nlit should be less than the number of literals (terms) + in the original row */ + xassert(0 < nlit && nlit < npp_row_nnz(npp, row)); + /* create new row corresponding to inequality (2) */ + rrr = npp_add_row(npp); + rrr->lb = -DBL_MAX, rrr->ub = 1.0; + /* move first nlit literals (terms) from the original row to the + new row; the original row becomes inequality (3) */ + for (k = 1; k <= nlit; k++) + { aij = row->ptr; + xassert(aij != NULL); + /* add literal to the new row */ + npp_add_aij(npp, rrr, aij->col, aij->val); + /* correct rhs */ + if (aij->val < 0.0) + rrr->ub -= 1.0, row->ub += 1.0; + /* remove literal from the original row */ + npp_del_aij(npp, aij); + } + /* create new binary variable y */ + col = npp_add_col(npp); + col->is_int = 1, col->lb = 0.0, col->ub = 1.0; + /* include literal (1 - y) in the new row */ + npp_add_aij(npp, rrr, col, -1.0); + rrr->ub -= 1.0; + /* include literal y in the original row */ + npp_add_aij(npp, row, col, +1.0); + return rrr; +} + +/*********************************************************************** +* npp_sat_encode_pack - encode packing inequality +* +* Given a packing inequality in canonical form: +* +* sum t[j] <= 1, (1) +* j in J +* +* where t[j] = x[j] or t[j] = 1 - x[j], x[j] is a binary variable, +* this routine translates it to CNF by replacing it with the following +* equivalent set of edge packing inequalities: +* +* t[j] + t[k] <= 1 for all j, k in J, j != k. (2) +* +* Then the routine transforms each edge packing inequality (2) to +* corresponding covering inequality (that encodes two-literal clause) +* by multiplying both its part by -1: +* +* - t[j] - t[k] >= -1 <--> (1 - t[j]) + (1 - t[k]) >= 1. (3) +* +* On exit the routine removes the original row from the problem. */ + +void npp_sat_encode_pack(NPP *npp, NPPROW *row) +{ NPPROW *rrr; + NPPAIJ *aij, *aik; + /* original row should be packing inequality (1) */ + xassert(npp_sat_is_pack_ineq(npp, row) == 1); + /* create equivalent system of covering inequalities (3) */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { /* due to symmetry only one of inequalities t[j] + t[k] <= 1 + and t[k] <= t[j] <= 1 can be considered */ + for (aik = aij->r_next; aik != NULL; aik = aik->r_next) + { /* create edge packing inequality (2) */ + rrr = npp_add_row(npp); + rrr->lb = -DBL_MAX, rrr->ub = 1.0; + npp_add_aij(npp, rrr, aij->col, aij->val); + if (aij->val < 0.0) + rrr->ub -= 1.0; + npp_add_aij(npp, rrr, aik->col, aik->val); + if (aik->val < 0.0) + rrr->ub -= 1.0; + /* and transform it to covering inequality (3) */ + npp_sat_reverse_row(npp, rrr); + xassert(npp_sat_is_cover_ineq(npp, rrr) == 1); + } + } + /* remove the original row from the problem */ + npp_del_row(npp, row); + return; +} + +/*********************************************************************** +* npp_sat_encode_sum2 - encode 2-bit summation +* +* Given a set containing two literals x and y this routine encodes +* the equality +* +* x + y = s + 2 * c, (1) +* +* where +* +* s = (x + y) % 2 (2) +* +* is a binary variable modeling the low sum bit, and +* +* c = (x + y) / 2 (3) +* +* is a binary variable modeling the high (carry) sum bit. */ + +void npp_sat_encode_sum2(NPP *npp, NPPLSE *set, NPPSED *sed) +{ NPPROW *row; + int x, y, s, c; + /* the set should contain exactly two literals */ + xassert(set != NULL); + xassert(set->next != NULL); + xassert(set->next->next == NULL); + sed->x = set->lit; + xassert(sed->x.neg == 0 || sed->x.neg == 1); + sed->y = set->next->lit; + xassert(sed->y.neg == 0 || sed->y.neg == 1); + sed->z.col = NULL, sed->z.neg = 0; + /* perform encoding s = (x + y) % 2 */ + sed->s = npp_add_col(npp); + sed->s->is_int = 1, sed->s->lb = 0.0, sed->s->ub = 1.0; + for (x = 0; x <= 1; x++) + { for (y = 0; y <= 1; y++) + { for (s = 0; s <= 1; s++) + { if ((x + y) % 2 != s) + { /* generate CNF clause to disable infeasible + combination */ + row = npp_add_row(npp); + row->lb = 1.0, row->ub = +DBL_MAX; + if (x == sed->x.neg) + npp_add_aij(npp, row, sed->x.col, +1.0); + else + { npp_add_aij(npp, row, sed->x.col, -1.0); + row->lb -= 1.0; + } + if (y == sed->y.neg) + npp_add_aij(npp, row, sed->y.col, +1.0); + else + { npp_add_aij(npp, row, sed->y.col, -1.0); + row->lb -= 1.0; + } + if (s == 0) + npp_add_aij(npp, row, sed->s, +1.0); + else + { npp_add_aij(npp, row, sed->s, -1.0); + row->lb -= 1.0; + } + } + } + } + } + /* perform encoding c = (x + y) / 2 */ + sed->c = npp_add_col(npp); + sed->c->is_int = 1, sed->c->lb = 0.0, sed->c->ub = 1.0; + for (x = 0; x <= 1; x++) + { for (y = 0; y <= 1; y++) + { for (c = 0; c <= 1; c++) + { if ((x + y) / 2 != c) + { /* generate CNF clause to disable infeasible + combination */ + row = npp_add_row(npp); + row->lb = 1.0, row->ub = +DBL_MAX; + if (x == sed->x.neg) + npp_add_aij(npp, row, sed->x.col, +1.0); + else + { npp_add_aij(npp, row, sed->x.col, -1.0); + row->lb -= 1.0; + } + if (y == sed->y.neg) + npp_add_aij(npp, row, sed->y.col, +1.0); + else + { npp_add_aij(npp, row, sed->y.col, -1.0); + row->lb -= 1.0; + } + if (c == 0) + npp_add_aij(npp, row, sed->c, +1.0); + else + { npp_add_aij(npp, row, sed->c, -1.0); + row->lb -= 1.0; + } + } + } + } + } + return; +} + +/*********************************************************************** +* npp_sat_encode_sum3 - encode 3-bit summation +* +* Given a set containing at least three literals this routine chooses +* some literals x, y, z from that set and encodes the equality +* +* x + y + z = s + 2 * c, (1) +* +* where +* +* s = (x + y + z) % 2 (2) +* +* is a binary variable modeling the low sum bit, and +* +* c = (x + y + z) / 2 (3) +* +* is a binary variable modeling the high (carry) sum bit. */ + +void npp_sat_encode_sum3(NPP *npp, NPPLSE *set, NPPSED *sed) +{ NPPROW *row; + int x, y, z, s, c; + /* the set should contain at least three literals */ + xassert(set != NULL); + xassert(set->next != NULL); + xassert(set->next->next != NULL); + sed->x = set->lit; + xassert(sed->x.neg == 0 || sed->x.neg == 1); + sed->y = set->next->lit; + xassert(sed->y.neg == 0 || sed->y.neg == 1); + sed->z = set->next->next->lit; + xassert(sed->z.neg == 0 || sed->z.neg == 1); + /* perform encoding s = (x + y + z) % 2 */ + sed->s = npp_add_col(npp); + sed->s->is_int = 1, sed->s->lb = 0.0, sed->s->ub = 1.0; + for (x = 0; x <= 1; x++) + { for (y = 0; y <= 1; y++) + { for (z = 0; z <= 1; z++) + { for (s = 0; s <= 1; s++) + { if ((x + y + z) % 2 != s) + { /* generate CNF clause to disable infeasible + combination */ + row = npp_add_row(npp); + row->lb = 1.0, row->ub = +DBL_MAX; + if (x == sed->x.neg) + npp_add_aij(npp, row, sed->x.col, +1.0); + else + { npp_add_aij(npp, row, sed->x.col, -1.0); + row->lb -= 1.0; + } + if (y == sed->y.neg) + npp_add_aij(npp, row, sed->y.col, +1.0); + else + { npp_add_aij(npp, row, sed->y.col, -1.0); + row->lb -= 1.0; + } + if (z == sed->z.neg) + npp_add_aij(npp, row, sed->z.col, +1.0); + else + { npp_add_aij(npp, row, sed->z.col, -1.0); + row->lb -= 1.0; + } + if (s == 0) + npp_add_aij(npp, row, sed->s, +1.0); + else + { npp_add_aij(npp, row, sed->s, -1.0); + row->lb -= 1.0; + } + } + } + } + } + } + /* perform encoding c = (x + y + z) / 2 */ + sed->c = npp_add_col(npp); + sed->c->is_int = 1, sed->c->lb = 0.0, sed->c->ub = 1.0; + for (x = 0; x <= 1; x++) + { for (y = 0; y <= 1; y++) + { for (z = 0; z <= 1; z++) + { for (c = 0; c <= 1; c++) + { if ((x + y + z) / 2 != c) + { /* generate CNF clause to disable infeasible + combination */ + row = npp_add_row(npp); + row->lb = 1.0, row->ub = +DBL_MAX; + if (x == sed->x.neg) + npp_add_aij(npp, row, sed->x.col, +1.0); + else + { npp_add_aij(npp, row, sed->x.col, -1.0); + row->lb -= 1.0; + } + if (y == sed->y.neg) + npp_add_aij(npp, row, sed->y.col, +1.0); + else + { npp_add_aij(npp, row, sed->y.col, -1.0); + row->lb -= 1.0; + } + if (z == sed->z.neg) + npp_add_aij(npp, row, sed->z.col, +1.0); + else + { npp_add_aij(npp, row, sed->z.col, -1.0); + row->lb -= 1.0; + } + if (c == 0) + npp_add_aij(npp, row, sed->c, +1.0); + else + { npp_add_aij(npp, row, sed->c, -1.0); + row->lb -= 1.0; + } + } + } + } + } + } + return; +} + +/*********************************************************************** +* npp_sat_encode_sum_ax - encode linear combination of 0-1 variables +* +* PURPOSE +* +* Given a linear combination of binary variables: +* +* sum a[j] x[j], (1) +* j +* +* which is the linear form of the specified row, this routine encodes +* (i.e. translates to CNF) the following equality: +* +* n +* sum |a[j]| t[j] = sum 2**(k-1) * y[k], (2) +* j k=1 +* +* where t[j] = x[j] (if a[j] > 0) or t[j] = 1 - x[j] (if a[j] < 0), +* and y[k] is either t[j] or a new literal created by the routine or +* a constant zero. Note that the sum in the right-hand side of (2) can +* be thought as a n-bit representation of the sum in the left-hand +* side, which is a non-negative integer number. +* +* ALGORITHM +* +* First, the number of bits, n, sufficient to represent any value in +* the left-hand side of (2) is determined. Obviously, n is the number +* of bits sufficient to represent the sum (sum |a[j]|). +* +* Let +* +* n +* |a[j]| = sum 2**(k-1) b[j,k], (3) +* k=1 +* +* where b[j,k] is k-th bit in a n-bit representation of |a[j]|. Then +* +* m n +* sum |a[j]| * t[j] = sum 2**(k-1) sum b[j,k] * t[j]. (4) +* j k=1 j=1 +* +* Introducing the set +* +* J[k] = { j : b[j,k] = 1 } (5) +* +* allows rewriting (4) as follows: +* +* n +* sum |a[j]| * t[j] = sum 2**(k-1) sum t[j]. (6) +* j k=1 j in J[k] +* +* Thus, our goal is to provide |J[k]| <= 1 for all k, in which case +* we will have the representation (1). +* +* Let |J[k]| = 2, i.e. J[k] has exactly two literals u and v. In this +* case we can apply the following transformation: +* +* u + v = s + 2 * c, (7) +* +* where s and c are, respectively, low (sum) and high (carry) bits of +* the sum of two bits. This allows to replace two literals u and v in +* J[k] by one literal s, and carry out literal c to J[k+1]. +* +* If |J[k]| >= 3, i.e. J[k] has at least three literals u, v, and w, +* we can apply the following transformation: +* +* u + v + w = s + 2 * c. (8) +* +* Again, literal s replaces literals u, v, and w in J[k], and literal +* c goes into J[k+1]. +* +* On exit the routine stores each literal from J[k] in element y[k], +* 1 <= k <= n. If J[k] is empty, y[k] is set to constant false. +* +* RETURNS +* +* The routine returns n, the number of literals in the right-hand side +* of (2), 0 <= n <= NBIT_MAX. If the sum (sum |a[j]|) is too large, so +* more than NBIT_MAX (= 31) literals are needed to encode the original +* linear combination, the routine returns a negative value. */ + +#define NBIT_MAX 31 +/* maximal number of literals in the right hand-side of (2) */ + +static NPPLSE *remove_lse(NPP *npp, NPPLSE *set, NPPCOL *col) +{ /* remove specified literal from specified literal set */ + NPPLSE *lse, *prev = NULL; + for (lse = set; lse != NULL; prev = lse, lse = lse->next) + if (lse->lit.col == col) break; + xassert(lse != NULL); + if (prev == NULL) + set = lse->next; + else + prev->next = lse->next; + dmp_free_atom(npp->pool, lse, sizeof(NPPLSE)); + return set; +} + +int npp_sat_encode_sum_ax(NPP *npp, NPPROW *row, NPPLIT y[]) +{ NPPAIJ *aij; + NPPLSE *set[1+NBIT_MAX], *lse; + NPPSED sed; + int k, n, temp; + double sum; + /* compute the sum (sum |a[j]|) */ + sum = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + sum += fabs(aij->val); + /* determine n, the number of bits in the sum */ + temp = (int)sum; + if ((double)temp != sum) + return -1; /* integer arithmetic error */ + for (n = 0; temp > 0; n++, temp >>= 1); + xassert(0 <= n && n <= NBIT_MAX); + /* build initial sets J[k], 1 <= k <= n; see (5) */ + /* set[k] is a pointer to the list of literals in J[k] */ + for (k = 1; k <= n; k++) + set[k] = NULL; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { temp = (int)fabs(aij->val); + xassert((int)temp == fabs(aij->val)); + for (k = 1; temp > 0; k++, temp >>= 1) + { if (temp & 1) + { xassert(k <= n); + lse = dmp_get_atom(npp->pool, sizeof(NPPLSE)); + lse->lit.col = aij->col; + lse->lit.neg = (aij->val > 0.0 ? 0 : 1); + lse->next = set[k]; + set[k] = lse; + } + } + } + /* main transformation loop */ + for (k = 1; k <= n; k++) + { /* reduce J[k] and set y[k] */ + for (;;) + { if (set[k] == NULL) + { /* J[k] is empty */ + /* set y[k] to constant false */ + y[k].col = NULL, y[k].neg = 0; + break; + } + if (set[k]->next == NULL) + { /* J[k] contains one literal */ + /* set y[k] to that literal */ + y[k] = set[k]->lit; + dmp_free_atom(npp->pool, set[k], sizeof(NPPLSE)); + break; + } + if (set[k]->next->next == NULL) + { /* J[k] contains two literals */ + /* apply transformation (7) */ + npp_sat_encode_sum2(npp, set[k], &sed); + } + else + { /* J[k] contains at least three literals */ + /* apply transformation (8) */ + npp_sat_encode_sum3(npp, set[k], &sed); + /* remove third literal from set[k] */ + set[k] = remove_lse(npp, set[k], sed.z.col); + } + /* remove second literal from set[k] */ + set[k] = remove_lse(npp, set[k], sed.y.col); + /* remove first literal from set[k] */ + set[k] = remove_lse(npp, set[k], sed.x.col); + /* include new literal s to set[k] */ + lse = dmp_get_atom(npp->pool, sizeof(NPPLSE)); + lse->lit.col = sed.s, lse->lit.neg = 0; + lse->next = set[k]; + set[k] = lse; + /* include new literal c to set[k+1] */ + xassert(k < n); /* FIXME: can "overflow" happen? */ + lse = dmp_get_atom(npp->pool, sizeof(NPPLSE)); + lse->lit.col = sed.c, lse->lit.neg = 0; + lse->next = set[k+1]; + set[k+1] = lse; + } + } + return n; +} + +/*********************************************************************** +* npp_sat_normalize_clause - normalize clause +* +* This routine normalizes the specified clause, which is a disjunction +* of literals, by replacing multiple literals, which refer to the same +* binary variable, with a single literal. +* +* On exit the routine returns the number of literals in the resulting +* clause. However, if the specified clause includes both a literal and +* its negation, the routine returns a negative value meaning that the +* clause is equivalent to the value true. */ + +int npp_sat_normalize_clause(NPP *npp, int size, NPPLIT lit[]) +{ int j, k, new_size; + xassert(npp == npp); + xassert(size >= 0); + new_size = 0; + for (k = 1; k <= size; k++) + { for (j = 1; j <= new_size; j++) + { if (lit[k].col == lit[j].col) + { /* lit[k] refers to the same variable as lit[j], which + is already included in the resulting clause */ + if (lit[k].neg == lit[j].neg) + { /* ignore lit[k] due to the idempotent law */ + goto skip; + } + else + { /* lit[k] is NOT lit[j]; the clause is equivalent to + the value true */ + return -1; + } + } + } + /* include lit[k] in the resulting clause */ + lit[++new_size] = lit[k]; +skip: ; + } + return new_size; +} + +/*********************************************************************** +* npp_sat_encode_clause - translate clause to cover inequality +* +* Given a clause +* +* OR t[j], (1) +* j in J +* +* where t[j] is a literal, i.e. t[j] = x[j] or t[j] = NOT x[j], this +* routine translates it to the following equivalent cover inequality, +* which is added to the transformed problem: +* +* sum t[j] >= 1, (2) +* j in J +* +* where t[j] = x[j] or t[j] = 1 - x[j]. +* +* If necessary, the clause should be normalized before a call to this +* routine. */ + +NPPROW *npp_sat_encode_clause(NPP *npp, int size, NPPLIT lit[]) +{ NPPROW *row; + int k; + xassert(size >= 1); + row = npp_add_row(npp); + row->lb = 1.0, row->ub = +DBL_MAX; + for (k = 1; k <= size; k++) + { xassert(lit[k].col != NULL); + if (lit[k].neg == 0) + npp_add_aij(npp, row, lit[k].col, +1.0); + else if (lit[k].neg == 1) + { npp_add_aij(npp, row, lit[k].col, -1.0); + row->lb -= 1.0; + } + else + xassert(lit != lit); + } + return row; +} + +/*********************************************************************** +* npp_sat_encode_geq - encode "not less than" constraint +* +* PURPOSE +* +* This routine translates to CNF the following constraint: +* +* n +* sum 2**(k-1) * y[k] >= b, (1) +* k=1 +* +* where y[k] is either a literal (i.e. y[k] = x[k] or y[k] = 1 - x[k]) +* or constant false (zero), b is a given lower bound. +* +* ALGORITHM +* +* If b < 0, the constraint is redundant, so assume that b >= 0. Let +* +* n +* b = sum 2**(k-1) b[k], (2) +* k=1 +* +* where b[k] is k-th binary digit of b. (Note that if b >= 2**n and +* therefore cannot be represented in the form (2), the constraint (1) +* is infeasible.) In this case the condition (1) is equivalent to the +* following condition: +* +* y[n] y[n-1] ... y[2] y[1] >= b[n] b[n-1] ... b[2] b[1], (3) +* +* where ">=" is understood lexicographically. +* +* Algorithmically the condition (3) can be tested as follows: +* +* for (k = n; k >= 1; k--) +* { if (y[k] < b[k]) +* y is less than b; +* if (y[k] > b[k]) +* y is greater than b; +* } +* y is equal to b; +* +* Thus, y is less than b iff there exists k, 1 <= k <= n, for which +* the following condition is satisfied: +* +* y[n] = b[n] AND ... AND y[k+1] = b[k+1] AND y[k] < b[k]. (4) +* +* Negating the condition (4) we have that y is not less than b iff for +* all k, 1 <= k <= n, the following condition is satisfied: +* +* y[n] != b[n] OR ... OR y[k+1] != b[k+1] OR y[k] >= b[k]. (5) +* +* Note that if b[k] = 0, the literal y[k] >= b[k] is always true, in +* which case the entire clause (5) is true and can be omitted. +* +* RETURNS +* +* Normally the routine returns zero. However, if the constraint (1) is +* infeasible, the routine returns non-zero. */ + +int npp_sat_encode_geq(NPP *npp, int n, NPPLIT y[], int rhs) +{ NPPLIT lit[1+NBIT_MAX]; + int j, k, size, temp, b[1+NBIT_MAX]; + xassert(0 <= n && n <= NBIT_MAX); + /* if the constraint (1) is redundant, do nothing */ + if (rhs < 0) + return 0; + /* determine binary digits of b according to (2) */ + for (k = 1, temp = rhs; k <= n; k++, temp >>= 1) + b[k] = temp & 1; + if (temp != 0) + { /* b >= 2**n; the constraint (1) is infeasible */ + return 1; + } + /* main transformation loop */ + for (k = 1; k <= n; k++) + { /* build the clause (5) for current k */ + size = 0; /* clause size = number of literals */ + /* add literal y[k] >= b[k] */ + if (b[k] == 0) + { /* b[k] = 0 -> the literal is true */ + goto skip; + } + else if (y[k].col == NULL) + { /* y[k] = 0, b[k] = 1 -> the literal is false */ + xassert(y[k].neg == 0); + } + else + { /* add literal y[k] = 1 */ + lit[++size] = y[k]; + } + for (j = k+1; j <= n; j++) + { /* add literal y[j] != b[j] */ + if (y[j].col == NULL) + { xassert(y[j].neg == 0); + if (b[j] == 0) + { /* y[j] = 0, b[j] = 0 -> the literal is false */ + continue; + } + else + { /* y[j] = 0, b[j] = 1 -> the literal is true */ + goto skip; + } + } + else + { lit[++size] = y[j]; + if (b[j] != 0) + lit[size].neg = 1 - lit[size].neg; + } + } + /* normalize the clause */ + size = npp_sat_normalize_clause(npp, size, lit); + if (size < 0) + { /* the clause is equivalent to the value true */ + goto skip; + } + if (size == 0) + { /* the clause is equivalent to the value false; this means + that the constraint (1) is infeasible */ + return 2; + } + /* translate the clause to corresponding cover inequality */ + npp_sat_encode_clause(npp, size, lit); +skip: ; + } + return 0; +} + +/*********************************************************************** +* npp_sat_encode_leq - encode "not greater than" constraint +* +* PURPOSE +* +* This routine translates to CNF the following constraint: +* +* n +* sum 2**(k-1) * y[k] <= b, (1) +* k=1 +* +* where y[k] is either a literal (i.e. y[k] = x[k] or y[k] = 1 - x[k]) +* or constant false (zero), b is a given upper bound. +* +* ALGORITHM +* +* If b < 0, the constraint is infeasible, so assume that b >= 0. Let +* +* n +* b = sum 2**(k-1) b[k], (2) +* k=1 +* +* where b[k] is k-th binary digit of b. (Note that if b >= 2**n and +* therefore cannot be represented in the form (2), the constraint (1) +* is redundant.) In this case the condition (1) is equivalent to the +* following condition: +* +* y[n] y[n-1] ... y[2] y[1] <= b[n] b[n-1] ... b[2] b[1], (3) +* +* where "<=" is understood lexicographically. +* +* Algorithmically the condition (3) can be tested as follows: +* +* for (k = n; k >= 1; k--) +* { if (y[k] < b[k]) +* y is less than b; +* if (y[k] > b[k]) +* y is greater than b; +* } +* y is equal to b; +* +* Thus, y is greater than b iff there exists k, 1 <= k <= n, for which +* the following condition is satisfied: +* +* y[n] = b[n] AND ... AND y[k+1] = b[k+1] AND y[k] > b[k]. (4) +* +* Negating the condition (4) we have that y is not greater than b iff +* for all k, 1 <= k <= n, the following condition is satisfied: +* +* y[n] != b[n] OR ... OR y[k+1] != b[k+1] OR y[k] <= b[k]. (5) +* +* Note that if b[k] = 1, the literal y[k] <= b[k] is always true, in +* which case the entire clause (5) is true and can be omitted. +* +* RETURNS +* +* Normally the routine returns zero. However, if the constraint (1) is +* infeasible, the routine returns non-zero. */ + +int npp_sat_encode_leq(NPP *npp, int n, NPPLIT y[], int rhs) +{ NPPLIT lit[1+NBIT_MAX]; + int j, k, size, temp, b[1+NBIT_MAX]; + xassert(0 <= n && n <= NBIT_MAX); + /* check if the constraint (1) is infeasible */ + if (rhs < 0) + return 1; + /* determine binary digits of b according to (2) */ + for (k = 1, temp = rhs; k <= n; k++, temp >>= 1) + b[k] = temp & 1; + if (temp != 0) + { /* b >= 2**n; the constraint (1) is redundant */ + return 0; + } + /* main transformation loop */ + for (k = 1; k <= n; k++) + { /* build the clause (5) for current k */ + size = 0; /* clause size = number of literals */ + /* add literal y[k] <= b[k] */ + if (b[k] == 1) + { /* b[k] = 1 -> the literal is true */ + goto skip; + } + else if (y[k].col == NULL) + { /* y[k] = 0, b[k] = 0 -> the literal is true */ + xassert(y[k].neg == 0); + goto skip; + } + else + { /* add literal y[k] = 0 */ + lit[++size] = y[k]; + lit[size].neg = 1 - lit[size].neg; + } + for (j = k+1; j <= n; j++) + { /* add literal y[j] != b[j] */ + if (y[j].col == NULL) + { xassert(y[j].neg == 0); + if (b[j] == 0) + { /* y[j] = 0, b[j] = 0 -> the literal is false */ + continue; + } + else + { /* y[j] = 0, b[j] = 1 -> the literal is true */ + goto skip; + } + } + else + { lit[++size] = y[j]; + if (b[j] != 0) + lit[size].neg = 1 - lit[size].neg; + } + } + /* normalize the clause */ + size = npp_sat_normalize_clause(npp, size, lit); + if (size < 0) + { /* the clause is equivalent to the value true */ + goto skip; + } + if (size == 0) + { /* the clause is equivalent to the value false; this means + that the constraint (1) is infeasible */ + return 2; + } + /* translate the clause to corresponding cover inequality */ + npp_sat_encode_clause(npp, size, lit); +skip: ; + } + return 0; +} + +/*********************************************************************** +* npp_sat_encode_row - encode constraint (row) of general type +* +* PURPOSE +* +* This routine translates to CNF the following constraint (row): +* +* L <= sum a[j] x[j] <= U, (1) +* j +* +* where all x[j] are binary variables. +* +* ALGORITHM +* +* First, the routine performs substitution x[j] = t[j] for j in J+ +* and x[j] = 1 - t[j] for j in J-, where J+ = { j : a[j] > 0 } and +* J- = { j : a[j] < 0 }. This gives: +* +* L <= sum a[j] t[j] + sum a[j] (1 - t[j]) <= U ==> +* j in J+ j in J- +* +* L' <= sum |a[j]| t[j] <= U', (2) +* j +* +* where +* +* L' = L - sum a[j], U' = U - sum a[j]. (3) +* j in J- j in J- +* +* (Actually only new bounds L' and U' are computed.) +* +* Then the routine translates to CNF the following equality: +* +* n +* sum |a[j]| t[j] = sum 2**(k-1) * y[k], (4) +* j k=1 +* +* where y[k] is either some t[j] or a new literal or a constant zero +* (see the routine npp_sat_encode_sum_ax). +* +* Finally, the routine translates to CNF the following conditions: +* +* n +* sum 2**(k-1) * y[k] >= L' (5) +* k=1 +* +* and +* +* n +* sum 2**(k-1) * y[k] <= U' (6) +* k=1 +* +* (see the routines npp_sat_encode_geq and npp_sat_encode_leq). +* +* All resulting clauses are encoded as cover inequalities and included +* into the transformed problem. +* +* Note that on exit the routine removes the specified constraint (row) +* from the original problem. +* +* RETURNS +* +* The routine returns one of the following codes: +* +* 0 - translation was successful; +* 1 - constraint (1) was found infeasible; +* 2 - integer arithmetic error occured. */ + +int npp_sat_encode_row(NPP *npp, NPPROW *row) +{ NPPAIJ *aij; + NPPLIT y[1+NBIT_MAX]; + int n, rhs; + double lb, ub; + /* the row should not be free */ + xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX)); + /* compute new bounds L' and U' (3) */ + lb = row->lb; + ub = row->ub; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { if (aij->val < 0.0) + { if (lb != -DBL_MAX) + lb -= aij->val; + if (ub != -DBL_MAX) + ub -= aij->val; + } + } + /* encode the equality (4) */ + n = npp_sat_encode_sum_ax(npp, row, y); + if (n < 0) + return 2; /* integer arithmetic error */ + /* encode the condition (5) */ + if (lb != -DBL_MAX) + { rhs = (int)lb; + if ((double)rhs != lb) + return 2; /* integer arithmetic error */ + if (npp_sat_encode_geq(npp, n, y, rhs) != 0) + return 1; /* original constraint is infeasible */ + } + /* encode the condition (6) */ + if (ub != +DBL_MAX) + { rhs = (int)ub; + if ((double)rhs != ub) + return 2; /* integer arithmetic error */ + if (npp_sat_encode_leq(npp, n, y, rhs) != 0) + return 1; /* original constraint is infeasible */ + } + /* remove the specified row from the problem */ + npp_del_row(npp, row); + return 0; +} + +/*********************************************************************** +* npp_sat_encode_prob - encode 0-1 feasibility problem +* +* This routine translates the specified 0-1 feasibility problem to an +* equivalent SAT-CNF problem. +* +* N.B. Currently this is a very crude implementation. +* +* RETURNS +* +* 0 success; +* +* GLP_ENOPFS primal/integer infeasibility detected; +* +* GLP_ERANGE integer overflow occured. */ + +int npp_sat_encode_prob(NPP *npp) +{ NPPROW *row, *next_row, *prev_row; + NPPCOL *col, *next_col; + int cover = 0, pack = 0, partn = 0, ret; + /* process and remove free rows */ + for (row = npp->r_head; row != NULL; row = next_row) + { next_row = row->next; + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + npp_sat_free_row(npp, row); + } + /* process and remove fixed columns */ + for (col = npp->c_head; col != NULL; col = next_col) + { next_col = col->next; + if (col->lb == col->ub) + xassert(npp_sat_fixed_col(npp, col) == 0); + } + /* only binary variables should remain */ + for (col = npp->c_head; col != NULL; col = col->next) + xassert(col->is_int && col->lb == 0.0 && col->ub == 1.0); + /* new rows may be added to the end of the row list, so we walk + from the end to beginning of the list */ + for (row = npp->r_tail; row != NULL; row = prev_row) + { prev_row = row->prev; + /* process special cases */ + ret = npp_sat_is_cover_ineq(npp, row); + if (ret != 0) + { /* row is covering inequality */ + cover++; + /* since it already encodes a clause, just transform it to + canonical form */ + if (ret == 2) + { xassert(npp_sat_reverse_row(npp, row) == 0); + ret = npp_sat_is_cover_ineq(npp, row); + } + xassert(ret == 1); + continue; + } + ret = npp_sat_is_partn_eq(npp, row); + if (ret != 0) + { /* row is partitioning equality */ + NPPROW *cov; + NPPAIJ *aij; + partn++; + /* transform it to canonical form */ + if (ret == 2) + { xassert(npp_sat_reverse_row(npp, row) == 0); + ret = npp_sat_is_partn_eq(npp, row); + } + xassert(ret == 1); + /* and split it into covering and packing inequalities, + both in canonical forms */ + cov = npp_add_row(npp); + cov->lb = row->lb, cov->ub = +DBL_MAX; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_add_aij(npp, cov, aij->col, aij->val); + xassert(npp_sat_is_cover_ineq(npp, cov) == 1); + /* the cover inequality already encodes a clause and do + not need any further processing */ + row->lb = -DBL_MAX; + xassert(npp_sat_is_pack_ineq(npp, row) == 1); + /* the packing inequality will be processed below */ + pack--; + } + ret = npp_sat_is_pack_ineq(npp, row); + if (ret != 0) + { /* row is packing inequality */ + NPPROW *rrr; + int nlit, desired_nlit = 4; + pack++; + /* transform it to canonical form */ + if (ret == 2) + { xassert(npp_sat_reverse_row(npp, row) == 0); + ret = npp_sat_is_pack_ineq(npp, row); + } + xassert(ret == 1); + /* process the packing inequality */ + for (;;) + { /* determine the number of literals in the remaining + inequality */ + nlit = npp_row_nnz(npp, row); + if (nlit <= desired_nlit) + break; + /* split the current inequality into one having not more + than desired_nlit literals and remaining one */ + rrr = npp_sat_split_pack(npp, row, desired_nlit-1); + /* translate the former inequality to CNF and remove it + from the original problem */ + npp_sat_encode_pack(npp, rrr); + } + /* translate the remaining inequality to CNF and remove it + from the original problem */ + npp_sat_encode_pack(npp, row); + continue; + } + /* translate row of general type to CNF and remove it from the + original problem */ + ret = npp_sat_encode_row(npp, row); + if (ret == 0) + ; + else if (ret == 1) + ret = GLP_ENOPFS; + else if (ret == 2) + ret = GLP_ERANGE; + else + xassert(ret != ret); + if (ret != 0) + goto done; + } + ret = 0; + if (cover != 0) + xprintf("%d covering inequalities\n", cover); + if (pack != 0) + xprintf("%d packing inequalities\n", pack); + if (partn != 0) + xprintf("%d partitioning equalities\n", partn); +done: return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glprgr.c b/resources/3rdparty/glpk-4.53/src/glprgr.c new file mode 100644 index 000000000..382a932ca --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glprgr.c @@ -0,0 +1,165 @@ +/* glprgr.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#define _GLPSTD_ERRNO +#define _GLPSTD_STDIO +#include "env.h" +#include "glprgr.h" +#define xfault xerror + +/*********************************************************************** +* NAME +* +* rgr_write_bmp16 - write 16-color raster image in BMP file format +* +* SYNOPSIS +* +* #include "glprgr.h" +* int rgr_write_bmp16(const char *fname, int m, int n, const char +* map[]); +* +* DESCRIPTION +* +* The routine rgr_write_bmp16 writes 16-color raster image in +* uncompressed BMP file format (Windows bitmap) to a binary file whose +* name is specified by the character string fname. +* +* The parameters m and n specify, respectively, the number of rows and +* the numbers of columns (i.e. height and width) of the raster image. +* +* The character array map has m*n elements. Elements map[0, ..., n-1] +* correspond to the first (top) scanline, elements map[n, ..., 2*n-1] +* correspond to the second scanline, etc. +* +* Each element of the array map specifies a color of the corresponding +* pixel as 8-bit binary number XXXXIRGB, where four high-order bits (X) +* are ignored, I is high intensity bit, R is red color bit, G is green +* color bit, and B is blue color bit. Thus, all 16 possible colors are +* coded as following hexadecimal numbers: +* +* 0x00 = black 0x08 = dark gray +* 0x01 = blue 0x09 = bright blue +* 0x02 = green 0x0A = bright green +* 0x03 = cyan 0x0B = bright cyan +* 0x04 = red 0x0C = bright red +* 0x05 = magenta 0x0D = bright magenta +* 0x06 = brown 0x0E = yellow +* 0x07 = light gray 0x0F = white +* +* RETURNS +* +* If no error occured, the routine returns zero; otherwise, it prints +* an appropriate error message and returns non-zero. */ + +static void put_byte(FILE *fp, int c) +{ fputc(c, fp); + return; +} + +static void put_word(FILE *fp, int w) +{ /* big endian */ + put_byte(fp, w); + put_byte(fp, w >> 8); + return; +} + +static void put_dword(FILE *fp, int d) +{ /* big endian */ + put_word(fp, d); + put_word(fp, d >> 16); + return; +} + +int rgr_write_bmp16(const char *fname, int m, int n, const char map[]) +{ FILE *fp; + int offset, bmsize, i, j, b, ret = 0; + if (!(1 <= m && m <= 32767)) + xfault("rgr_write_bmp16: m = %d; invalid height\n", m); + if (!(1 <= n && n <= 32767)) + xfault("rgr_write_bmp16: n = %d; invalid width\n", n); + fp = fopen(fname, "wb"); + if (fp == NULL) + { xprintf("rgr_write_bmp16: unable to create `%s' - %s\n", + fname, strerror(errno)); + ret = 1; + goto fini; + } + offset = 14 + 40 + 16 * 4; + bmsize = (4 * n + 31) / 32; + /* struct BMPFILEHEADER (14 bytes) */ + /* UINT bfType */ put_byte(fp, 'B'), put_byte(fp, 'M'); + /* DWORD bfSize */ put_dword(fp, offset + bmsize * 4); + /* UINT bfReserved1 */ put_word(fp, 0); + /* UNIT bfReserved2 */ put_word(fp, 0); + /* DWORD bfOffBits */ put_dword(fp, offset); + /* struct BMPINFOHEADER (40 bytes) */ + /* DWORD biSize */ put_dword(fp, 40); + /* LONG biWidth */ put_dword(fp, n); + /* LONG biHeight */ put_dword(fp, m); + /* WORD biPlanes */ put_word(fp, 1); + /* WORD biBitCount */ put_word(fp, 4); + /* DWORD biCompression */ put_dword(fp, 0 /* BI_RGB */); + /* DWORD biSizeImage */ put_dword(fp, 0); + /* LONG biXPelsPerMeter */ put_dword(fp, 2953 /* 75 dpi */); + /* LONG biYPelsPerMeter */ put_dword(fp, 2953 /* 75 dpi */); + /* DWORD biClrUsed */ put_dword(fp, 0); + /* DWORD biClrImportant */ put_dword(fp, 0); + /* struct RGBQUAD (16 * 4 = 64 bytes) */ + /* CGA-compatible colors: */ + /* 0x00 = black */ put_dword(fp, 0x000000); + /* 0x01 = blue */ put_dword(fp, 0x000080); + /* 0x02 = green */ put_dword(fp, 0x008000); + /* 0x03 = cyan */ put_dword(fp, 0x008080); + /* 0x04 = red */ put_dword(fp, 0x800000); + /* 0x05 = magenta */ put_dword(fp, 0x800080); + /* 0x06 = brown */ put_dword(fp, 0x808000); + /* 0x07 = light gray */ put_dword(fp, 0xC0C0C0); + /* 0x08 = dark gray */ put_dword(fp, 0x808080); + /* 0x09 = bright blue */ put_dword(fp, 0x0000FF); + /* 0x0A = bright green */ put_dword(fp, 0x00FF00); + /* 0x0B = bright cyan */ put_dword(fp, 0x00FFFF); + /* 0x0C = bright red */ put_dword(fp, 0xFF0000); + /* 0x0D = bright magenta */ put_dword(fp, 0xFF00FF); + /* 0x0E = yellow */ put_dword(fp, 0xFFFF00); + /* 0x0F = white */ put_dword(fp, 0xFFFFFF); + /* pixel data bits */ + b = 0; + for (i = m - 1; i >= 0; i--) + { for (j = 0; j < ((n + 7) / 8) * 8; j++) + { b <<= 4; + b |= (j < n ? map[i * n + j] & 15 : 0); + if (j & 1) put_byte(fp, b); + } + } + fflush(fp); + if (ferror(fp)) + { xprintf("rgr_write_bmp16: write error on `%s' - %s\n", + fname, strerror(errno)); + ret = 1; + } +fini: if (fp != NULL) fclose(fp); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glprgr.h b/resources/3rdparty/glpk-4.53/src/glprgr.h new file mode 100644 index 000000000..71e089e91 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glprgr.h @@ -0,0 +1,34 @@ +/* glprgr.h (raster graphics) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPRGR_H +#define GLPRGR_H + +#define rgr_write_bmp16 _glp_rgr_write_bmp16 +int rgr_write_bmp16(const char *fname, int m, int n, const char map[]); +/* write 16-color raster image in BMP file format */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpscl.c b/resources/3rdparty/glpk-4.53/src/glpscl.c new file mode 100644 index 000000000..de769a8b1 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpscl.c @@ -0,0 +1,478 @@ +/* glpscl.c (problem scaling routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "misc.h" +#include "prob.h" + +/*********************************************************************** +* min_row_aij - determine minimal |a[i,j]| in i-th row +* +* This routine returns minimal magnitude of (non-zero) constraint +* coefficients in i-th row of the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If i-th row of the matrix is empty, the routine returns 1. */ + +static double min_row_aij(glp_prob *lp, int i, int scaled) +{ GLPAIJ *aij; + double min_aij, temp; + xassert(1 <= i && i <= lp->m); + min_aij = 1.0; + for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { temp = fabs(aij->val); + if (scaled) temp *= (aij->row->rii * aij->col->sjj); + if (aij->r_prev == NULL || min_aij > temp) + min_aij = temp; + } + return min_aij; +} + +/*********************************************************************** +* max_row_aij - determine maximal |a[i,j]| in i-th row +* +* This routine returns maximal magnitude of (non-zero) constraint +* coefficients in i-th row of the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If i-th row of the matrix is empty, the routine returns 1. */ + +static double max_row_aij(glp_prob *lp, int i, int scaled) +{ GLPAIJ *aij; + double max_aij, temp; + xassert(1 <= i && i <= lp->m); + max_aij = 1.0; + for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { temp = fabs(aij->val); + if (scaled) temp *= (aij->row->rii * aij->col->sjj); + if (aij->r_prev == NULL || max_aij < temp) + max_aij = temp; + } + return max_aij; +} + +/*********************************************************************** +* min_col_aij - determine minimal |a[i,j]| in j-th column +* +* This routine returns minimal magnitude of (non-zero) constraint +* coefficients in j-th column of the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If j-th column of the matrix is empty, the routine returns 1. */ + +static double min_col_aij(glp_prob *lp, int j, int scaled) +{ GLPAIJ *aij; + double min_aij, temp; + xassert(1 <= j && j <= lp->n); + min_aij = 1.0; + for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) + { temp = fabs(aij->val); + if (scaled) temp *= (aij->row->rii * aij->col->sjj); + if (aij->c_prev == NULL || min_aij > temp) + min_aij = temp; + } + return min_aij; +} + +/*********************************************************************** +* max_col_aij - determine maximal |a[i,j]| in j-th column +* +* This routine returns maximal magnitude of (non-zero) constraint +* coefficients in j-th column of the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If j-th column of the matrix is empty, the routine returns 1. */ + +static double max_col_aij(glp_prob *lp, int j, int scaled) +{ GLPAIJ *aij; + double max_aij, temp; + xassert(1 <= j && j <= lp->n); + max_aij = 1.0; + for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) + { temp = fabs(aij->val); + if (scaled) temp *= (aij->row->rii * aij->col->sjj); + if (aij->c_prev == NULL || max_aij < temp) + max_aij = temp; + } + return max_aij; +} + +/*********************************************************************** +* min_mat_aij - determine minimal |a[i,j]| in constraint matrix +* +* This routine returns minimal magnitude of (non-zero) constraint +* coefficients in the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If the matrix is empty, the routine returns 1. */ + +static double min_mat_aij(glp_prob *lp, int scaled) +{ int i; + double min_aij, temp; + min_aij = 1.0; + for (i = 1; i <= lp->m; i++) + { temp = min_row_aij(lp, i, scaled); + if (i == 1 || min_aij > temp) + min_aij = temp; + } + return min_aij; +} + +/*********************************************************************** +* max_mat_aij - determine maximal |a[i,j]| in constraint matrix +* +* This routine returns maximal magnitude of (non-zero) constraint +* coefficients in the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If the matrix is empty, the routine returns 1. */ + +static double max_mat_aij(glp_prob *lp, int scaled) +{ int i; + double max_aij, temp; + max_aij = 1.0; + for (i = 1; i <= lp->m; i++) + { temp = max_row_aij(lp, i, scaled); + if (i == 1 || max_aij < temp) + max_aij = temp; + } + return max_aij; +} + +/*********************************************************************** +* eq_scaling - perform equilibration scaling +* +* This routine performs equilibration scaling of rows and columns of +* the constraint matrix. +* +* If the parameter flag is zero, the routine scales rows at first and +* then columns. Otherwise, the routine scales columns and then rows. +* +* Rows are scaled as follows: +* +* n +* a'[i,j] = a[i,j] / max |a[i,j]|, i = 1,...,m. +* j=1 +* +* This makes the infinity (maximum) norm of each row of the matrix +* equal to 1. +* +* Columns are scaled as follows: +* +* m +* a'[i,j] = a[i,j] / max |a[i,j]|, j = 1,...,n. +* i=1 +* +* This makes the infinity (maximum) norm of each column of the matrix +* equal to 1. */ + +static void eq_scaling(glp_prob *lp, int flag) +{ int i, j, pass; + double temp; + xassert(flag == 0 || flag == 1); + for (pass = 0; pass <= 1; pass++) + { if (pass == flag) + { /* scale rows */ + for (i = 1; i <= lp->m; i++) + { temp = max_row_aij(lp, i, 1); + glp_set_rii(lp, i, glp_get_rii(lp, i) / temp); + } + } + else + { /* scale columns */ + for (j = 1; j <= lp->n; j++) + { temp = max_col_aij(lp, j, 1); + glp_set_sjj(lp, j, glp_get_sjj(lp, j) / temp); + } + } + } + return; +} + +/*********************************************************************** +* gm_scaling - perform geometric mean scaling +* +* This routine performs geometric mean scaling of rows and columns of +* the constraint matrix. +* +* If the parameter flag is zero, the routine scales rows at first and +* then columns. Otherwise, the routine scales columns and then rows. +* +* Rows are scaled as follows: +* +* a'[i,j] = a[i,j] / sqrt(alfa[i] * beta[i]), i = 1,...,m, +* +* where: +* n n +* alfa[i] = min |a[i,j]|, beta[i] = max |a[i,j]|. +* j=1 j=1 +* +* This allows decreasing the ratio beta[i] / alfa[i] for each row of +* the matrix. +* +* Columns are scaled as follows: +* +* a'[i,j] = a[i,j] / sqrt(alfa[j] * beta[j]), j = 1,...,n, +* +* where: +* m m +* alfa[j] = min |a[i,j]|, beta[j] = max |a[i,j]|. +* i=1 i=1 +* +* This allows decreasing the ratio beta[j] / alfa[j] for each column +* of the matrix. */ + +static void gm_scaling(glp_prob *lp, int flag) +{ int i, j, pass; + double temp; + xassert(flag == 0 || flag == 1); + for (pass = 0; pass <= 1; pass++) + { if (pass == flag) + { /* scale rows */ + for (i = 1; i <= lp->m; i++) + { temp = min_row_aij(lp, i, 1) * max_row_aij(lp, i, 1); + glp_set_rii(lp, i, glp_get_rii(lp, i) / sqrt(temp)); + } + } + else + { /* scale columns */ + for (j = 1; j <= lp->n; j++) + { temp = min_col_aij(lp, j, 1) * max_col_aij(lp, j, 1); + glp_set_sjj(lp, j, glp_get_sjj(lp, j) / sqrt(temp)); + } + } + } + return; +} + +/*********************************************************************** +* max_row_ratio - determine worst scaling "quality" for rows +* +* This routine returns the worst scaling "quality" for rows of the +* currently scaled constraint matrix: +* +* m +* ratio = max ratio[i], +* i=1 +* where: +* n n +* ratio[i] = max |a[i,j]| / min |a[i,j]|, 1 <= i <= m, +* j=1 j=1 +* +* is the scaling "quality" of i-th row. */ + +static double max_row_ratio(glp_prob *lp) +{ int i; + double ratio, temp; + ratio = 1.0; + for (i = 1; i <= lp->m; i++) + { temp = max_row_aij(lp, i, 1) / min_row_aij(lp, i, 1); + if (i == 1 || ratio < temp) ratio = temp; + } + return ratio; +} + +/*********************************************************************** +* max_col_ratio - determine worst scaling "quality" for columns +* +* This routine returns the worst scaling "quality" for columns of the +* currently scaled constraint matrix: +* +* n +* ratio = max ratio[j], +* j=1 +* where: +* m m +* ratio[j] = max |a[i,j]| / min |a[i,j]|, 1 <= j <= n, +* i=1 i=1 +* +* is the scaling "quality" of j-th column. */ + +static double max_col_ratio(glp_prob *lp) +{ int j; + double ratio, temp; + ratio = 1.0; + for (j = 1; j <= lp->n; j++) + { temp = max_col_aij(lp, j, 1) / min_col_aij(lp, j, 1); + if (j == 1 || ratio < temp) ratio = temp; + } + return ratio; +} + +/*********************************************************************** +* gm_iterate - perform iterative geometric mean scaling +* +* This routine performs iterative geometric mean scaling of rows and +* columns of the constraint matrix. +* +* The parameter it_max specifies the maximal number of iterations. +* Recommended value of it_max is 15. +* +* The parameter tau specifies a minimal improvement of the scaling +* "quality" on each iteration, 0 < tau < 1. It means than the scaling +* process continues while the following condition is satisfied: +* +* ratio[k] <= tau * ratio[k-1], +* +* where ratio = max |a[i,j]| / min |a[i,j]| is the scaling "quality" +* to be minimized, k is the iteration number. Recommended value of tau +* is 0.90. */ + +static void gm_iterate(glp_prob *lp, int it_max, double tau) +{ int k, flag; + double ratio = 0.0, r_old; + /* if the scaling "quality" for rows is better than for columns, + the rows are scaled first; otherwise, the columns are scaled + first */ + flag = (max_row_ratio(lp) > max_col_ratio(lp)); + for (k = 1; k <= it_max; k++) + { /* save the scaling "quality" from previous iteration */ + r_old = ratio; + /* determine the current scaling "quality" */ + ratio = max_mat_aij(lp, 1) / min_mat_aij(lp, 1); +#if 0 + xprintf("k = %d; ratio = %g\n", k, ratio); +#endif + /* if improvement is not enough, terminate scaling */ + if (k > 1 && ratio > tau * r_old) break; + /* otherwise, perform another iteration */ + gm_scaling(lp, flag); + } + return; +} + +/*********************************************************************** +* NAME +* +* scale_prob - scale problem data +* +* SYNOPSIS +* +* #include "glpscl.h" +* void scale_prob(glp_prob *lp, int flags); +* +* DESCRIPTION +* +* The routine scale_prob performs automatic scaling of problem data +* for the specified problem object. */ + +static void scale_prob(glp_prob *lp, int flags) +{ static const char *fmt = + "%s: min|aij| = %10.3e max|aij| = %10.3e ratio = %10.3e\n"; + double min_aij, max_aij, ratio; + xprintf("Scaling...\n"); + /* cancel the current scaling effect */ + glp_unscale_prob(lp); + /* report original scaling "quality" */ + min_aij = min_mat_aij(lp, 1); + max_aij = max_mat_aij(lp, 1); + ratio = max_aij / min_aij; + xprintf(fmt, " A", min_aij, max_aij, ratio); + /* check if the problem is well scaled */ + if (min_aij >= 0.10 && max_aij <= 10.0) + { xprintf("Problem data seem to be well scaled\n"); + /* skip scaling, if required */ + if (flags & GLP_SF_SKIP) goto done; + } + /* perform iterative geometric mean scaling, if required */ + if (flags & GLP_SF_GM) + { gm_iterate(lp, 15, 0.90); + min_aij = min_mat_aij(lp, 1); + max_aij = max_mat_aij(lp, 1); + ratio = max_aij / min_aij; + xprintf(fmt, "GM", min_aij, max_aij, ratio); + } + /* perform equilibration scaling, if required */ + if (flags & GLP_SF_EQ) + { eq_scaling(lp, max_row_ratio(lp) > max_col_ratio(lp)); + min_aij = min_mat_aij(lp, 1); + max_aij = max_mat_aij(lp, 1); + ratio = max_aij / min_aij; + xprintf(fmt, "EQ", min_aij, max_aij, ratio); + } + /* round scale factors to nearest power of two, if required */ + if (flags & GLP_SF_2N) + { int i, j; + for (i = 1; i <= lp->m; i++) + glp_set_rii(lp, i, round2n(glp_get_rii(lp, i))); + for (j = 1; j <= lp->n; j++) + glp_set_sjj(lp, j, round2n(glp_get_sjj(lp, j))); + min_aij = min_mat_aij(lp, 1); + max_aij = max_mat_aij(lp, 1); + ratio = max_aij / min_aij; + xprintf(fmt, "2N", min_aij, max_aij, ratio); + } +done: return; +} + +/*********************************************************************** +* NAME +* +* glp_scale_prob - scale problem data +* +* SYNOPSIS +* +* void glp_scale_prob(glp_prob *lp, int flags); +* +* DESCRIPTION +* +* The routine glp_scale_prob performs automatic scaling of problem +* data for the specified problem object. +* +* The parameter flags specifies scaling options used by the routine. +* Options can be combined with the bitwise OR operator and may be the +* following: +* +* GLP_SF_GM perform geometric mean scaling; +* GLP_SF_EQ perform equilibration scaling; +* GLP_SF_2N round scale factors to nearest power of two; +* GLP_SF_SKIP skip scaling, if the problem is well scaled. +* +* The parameter flags may be specified as GLP_SF_AUTO, in which case +* the routine chooses scaling options automatically. */ + +void glp_scale_prob(glp_prob *lp, int flags) +{ if (flags & ~(GLP_SF_GM | GLP_SF_EQ | GLP_SF_2N | GLP_SF_SKIP | + GLP_SF_AUTO)) + xerror("glp_scale_prob: flags = 0x%02X; invalid scaling option" + "s\n", flags); + if (flags & GLP_SF_AUTO) + flags = (GLP_SF_GM | GLP_SF_EQ | GLP_SF_SKIP); + scale_prob(lp, flags); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpsdf.c b/resources/3rdparty/glpk-4.53/src/glpsdf.c new file mode 100644 index 000000000..bd167f2dd --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpsdf.c @@ -0,0 +1,259 @@ +/* glpsdf.c (plain data file reading routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpsdf.h" +#include "misc.h" + +struct glp_data +{ /* plain data file */ + char *fname; + /* name of data file */ + glp_file *fp; + /* stream assigned to data file */ + void *jump; /* jmp_buf jump; */ + /* label for go to in case of error */ + int count; + /* line count */ + int c; + /* current character of EOF */ + char item[255+1]; + /* current data item */ +}; + +static void next_char(glp_data *data); + +glp_data *glp_sdf_open_file(const char *fname) +{ /* open plain data file */ + glp_data *data = NULL; + glp_file *fp; + jmp_buf jump; + fp = glp_open(fname, "r"); + if (fp == NULL) + { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + goto done; + } + data = xmalloc(sizeof(glp_data)); + data->fname = xmalloc(strlen(fname)+1); + strcpy(data->fname, fname); + data->fp = fp; + data->jump = NULL; + data->count = 0; + data->c = '\n'; + data->item[0] = '\0'; + /* read the very first character */ + if (setjmp(jump)) + { glp_sdf_close_file(data); + data = NULL; + goto done; + } + data->jump = jump; + next_char(data); + data->jump = NULL; +done: return data; +} + +void glp_sdf_set_jump(glp_data *data, void *jump) +{ /* set up error handling */ + data->jump = jump; + return; +} + +void glp_sdf_error(glp_data *data, const char *fmt, ...) +{ /* print error message */ + va_list arg; + xprintf("%s:%d: ", data->fname, data->count); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + if (data->jump == NULL) + xerror(""); + else + longjmp(data->jump, 1); + /* no return */ +} + +void glp_sdf_warning(glp_data *data, const char *fmt, ...) +{ /* print warning message */ + va_list arg; + xprintf("%s:%d: warning: ", data->fname, data->count); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + return; +} + +static void next_char(glp_data *data) +{ /* read next character */ + int c; + if (data->c == EOF) + glp_sdf_error(data, "unexpected end of file\n"); + else if (data->c == '\n') + data->count++; + c = glp_getc(data->fp); + if (c < 0) + { if (glp_ioerr(data->fp)) + glp_sdf_error(data, "read error - %s\n", get_err_msg()); + else if (data->c == '\n') + c = EOF; + else + { glp_sdf_warning(data, "missing final end of line\n"); + c = '\n'; + } + } + else if (c == '\n') + ; + else if (isspace(c)) + c = ' '; + else if (iscntrl(c)) + glp_sdf_error(data, "invalid control character 0x%02X\n", c); + data->c = c; + return; +} + +static void skip_pad(glp_data *data) +{ /* skip uninteresting characters and comments */ +loop: while (data->c == ' ' || data->c == '\n') + next_char(data); + if (data->c == '/') + { next_char(data); + if (data->c != '*') + glp_sdf_error(data, "invalid use of slash\n"); + next_char(data); + for (;;) + { if (data->c == '*') + { next_char(data); + if (data->c == '/') + { next_char(data); + break; + } + } + next_char(data); + } + goto loop; + } + return; +} + +static void next_item(glp_data *data) +{ /* read next item */ + int len; + skip_pad(data); + len = 0; + while (!(data->c == ' ' || data->c == '\n')) + { data->item[len++] = (char)data->c; + if (len == sizeof(data->item)) + glp_sdf_error(data, "data item `%.31s...' too long\n", + data->item); + next_char(data); + } + data->item[len] = '\0'; + return; +} + +int glp_sdf_read_int(glp_data *data) +{ /* read integer number */ + int x; + next_item(data); + switch (str2int(data->item, &x)) + { case 0: + break; + case 1: + glp_sdf_error(data, "integer `%s' out of range\n", + data->item); + case 2: + glp_sdf_error(data, "cannot convert `%s' to integer\n", + data->item); + default: + xassert(data != data); + } + return x; +} + +double glp_sdf_read_num(glp_data *data) +{ /* read floating-point number */ + double x; + next_item(data); + switch (str2num(data->item, &x)) + { case 0: + break; + case 1: + glp_sdf_error(data, "number `%s' out of range\n", + data->item); + case 2: + glp_sdf_error(data, "cannot convert `%s' to number\n", + data->item); + default: + xassert(data != data); + } + return x; +} + +const char *glp_sdf_read_item(glp_data *data) +{ /* read data item */ + next_item(data); + return data->item; +} + +const char *glp_sdf_read_text(glp_data *data) +{ /* read text until end of line */ + int c, len = 0; + for (;;) + { c = data->c; + next_char(data); + if (c == ' ') + { /* ignore initial spaces */ + if (len == 0) continue; + /* and multiple ones */ + if (data->item[len-1] == ' ') continue; + } + else if (c == '\n') + { /* remove trailing space */ + if (len > 0 && data->item[len-1] == ' ') len--; + /* and stop reading */ + break; + } + /* add current character to the buffer */ + data->item[len++] = (char)c; + if (len == sizeof(data->item)) + glp_sdf_error(data, "line too long\n", data->item); + } + data->item[len] = '\0'; + return data->item; +} + +int glp_sdf_line(glp_data *data) +{ /* determine current line number */ + return data->count; +} + +void glp_sdf_close_file(glp_data *data) +{ /* close plain data file */ + glp_close(data->fp); + xfree(data->fname); + xfree(data); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpsdf.h b/resources/3rdparty/glpk-4.53/src/glpsdf.h new file mode 100644 index 000000000..d327a1033 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpsdf.h @@ -0,0 +1,63 @@ +/* glpsdf.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPSDF_H +#define GLPSDF_H + +typedef struct glp_data glp_data; +/* plain data file */ + +glp_data *glp_sdf_open_file(const char *fname); +/* open plain data file */ + +void glp_sdf_set_jump(glp_data *data, void *jump); +/* set up error handling */ + +void glp_sdf_error(glp_data *data, const char *fmt, ...); +/* print error message */ + +void glp_sdf_warning(glp_data *data, const char *fmt, ...); +/* print warning message */ + +int glp_sdf_read_int(glp_data *data); +/* read integer number */ + +double glp_sdf_read_num(glp_data *data); +/* read floating-point number */ + +const char *glp_sdf_read_item(glp_data *data); +/* read data item */ + +const char *glp_sdf_read_text(glp_data *data); +/* read text until end of line */ + +int glp_sdf_line(glp_data *data); +/* determine current line number */ + +void glp_sdf_close_file(glp_data *data); +/* close plain data file */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpspm.c b/resources/3rdparty/glpk-4.53/src/glpspm.c new file mode 100644 index 000000000..c05b3ac18 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpspm.c @@ -0,0 +1,847 @@ +/* glpspm.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "glphbm.h" +#include "glprgr.h" +#include "glpspm.h" +#include "env.h" + +/*********************************************************************** +* NAME +* +* spm_create_mat - create general sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_create_mat(int m, int n); +* +* DESCRIPTION +* +* The routine spm_create_mat creates a general sparse matrix having +* m rows and n columns. Being created the matrix is zero (empty), i.e. +* has no elements. +* +* RETURNS +* +* The routine returns a pointer to the matrix created. */ + +SPM *spm_create_mat(int m, int n) +{ SPM *A; + xassert(0 <= m && m < INT_MAX); + xassert(0 <= n && n < INT_MAX); + A = xmalloc(sizeof(SPM)); + A->m = m; + A->n = n; + if (m == 0 || n == 0) + { A->pool = NULL; + A->row = NULL; + A->col = NULL; + } + else + { int i, j; + A->pool = dmp_create_pool(); + A->row = xcalloc(1+m, sizeof(SPME *)); + for (i = 1; i <= m; i++) A->row[i] = NULL; + A->col = xcalloc(1+n, sizeof(SPME *)); + for (j = 1; j <= n; j++) A->col[j] = NULL; + } + return A; +} + +/*********************************************************************** +* NAME +* +* spm_new_elem - add new element to sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPME *spm_new_elem(SPM *A, int i, int j, double val); +* +* DESCRIPTION +* +* The routine spm_new_elem adds a new element to the specified sparse +* matrix. Parameters i, j, and val specify the row number, the column +* number, and a numerical value of the element, respectively. +* +* RETURNS +* +* The routine returns a pointer to the new element added. */ + +SPME *spm_new_elem(SPM *A, int i, int j, double val) +{ SPME *e; + xassert(1 <= i && i <= A->m); + xassert(1 <= j && j <= A->n); + e = dmp_get_atom(A->pool, sizeof(SPME)); + e->i = i; + e->j = j; + e->val = val; + e->r_prev = NULL; + e->r_next = A->row[i]; + if (e->r_next != NULL) e->r_next->r_prev = e; + e->c_prev = NULL; + e->c_next = A->col[j]; + if (e->c_next != NULL) e->c_next->c_prev = e; + A->row[i] = A->col[j] = e; + return e; +} + +/*********************************************************************** +* NAME +* +* spm_delete_mat - delete general sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* void spm_delete_mat(SPM *A); +* +* DESCRIPTION +* +* The routine deletes the specified general sparse matrix freeing all +* the memory allocated to this object. */ + +void spm_delete_mat(SPM *A) +{ /* delete sparse matrix */ + if (A->pool != NULL) dmp_delete_pool(A->pool); + if (A->row != NULL) xfree(A->row); + if (A->col != NULL) xfree(A->col); + xfree(A); + return; +} + +/*********************************************************************** +* NAME +* +* spm_test_mat_e - create test sparse matrix of E(n,c) class +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_test_mat_e(int n, int c); +* +* DESCRIPTION +* +* The routine spm_test_mat_e creates a test sparse matrix of E(n,c) +* class as described in the book: Ole 0sterby, Zahari Zlatev. Direct +* Methods for Sparse Matrices. Springer-Verlag, 1983. +* +* Matrix of E(n,c) class is a symmetric positive definite matrix of +* the order n. It has the number 4 on its main diagonal and the number +* -1 on its four co-diagonals, two of which are neighbour to the main +* diagonal and two others are shifted from the main diagonal on the +* distance c. +* +* It is necessary that n >= 3 and 2 <= c <= n-1. +* +* RETURNS +* +* The routine returns a pointer to the matrix created. */ + +SPM *spm_test_mat_e(int n, int c) +{ SPM *A; + int i; + xassert(n >= 3 && 2 <= c && c <= n-1); + A = spm_create_mat(n, n); + for (i = 1; i <= n; i++) + spm_new_elem(A, i, i, 4.0); + for (i = 1; i <= n-1; i++) + { spm_new_elem(A, i, i+1, -1.0); + spm_new_elem(A, i+1, i, -1.0); + } + for (i = 1; i <= n-c; i++) + { spm_new_elem(A, i, i+c, -1.0); + spm_new_elem(A, i+c, i, -1.0); + } + return A; +} + +/*********************************************************************** +* NAME +* +* spm_test_mat_d - create test sparse matrix of D(n,c) class +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_test_mat_d(int n, int c); +* +* DESCRIPTION +* +* The routine spm_test_mat_d creates a test sparse matrix of D(n,c) +* class as described in the book: Ole 0sterby, Zahari Zlatev. Direct +* Methods for Sparse Matrices. Springer-Verlag, 1983. +* +* Matrix of D(n,c) class is a non-singular matrix of the order n. It +* has unity main diagonal, three co-diagonals above the main diagonal +* on the distance c, which are cyclically continued below the main +* diagonal, and a triangle block of the size 10x10 in the upper right +* corner. +* +* It is necessary that n >= 14 and 1 <= c <= n-13. +* +* RETURNS +* +* The routine returns a pointer to the matrix created. */ + +SPM *spm_test_mat_d(int n, int c) +{ SPM *A; + int i, j; + xassert(n >= 14 && 1 <= c && c <= n-13); + A = spm_create_mat(n, n); + for (i = 1; i <= n; i++) + spm_new_elem(A, i, i, 1.0); + for (i = 1; i <= n-c; i++) + spm_new_elem(A, i, i+c, (double)(i+1)); + for (i = n-c+1; i <= n; i++) + spm_new_elem(A, i, i-n+c, (double)(i+1)); + for (i = 1; i <= n-c-1; i++) + spm_new_elem(A, i, i+c+1, (double)(-i)); + for (i = n-c; i <= n; i++) + spm_new_elem(A, i, i-n+c+1, (double)(-i)); + for (i = 1; i <= n-c-2; i++) + spm_new_elem(A, i, i+c+2, 16.0); + for (i = n-c-1; i <= n; i++) + spm_new_elem(A, i, i-n+c+2, 16.0); + for (j = 1; j <= 10; j++) + for (i = 1; i <= 11-j; i++) + spm_new_elem(A, i, n-11+i+j, 100.0 * (double)j); + return A; +} + +/*********************************************************************** +* NAME +* +* spm_show_mat - write sparse matrix pattern in BMP file format +* +* SYNOPSIS +* +* #include "glpspm.h" +* int spm_show_mat(const SPM *A, const char *fname); +* +* DESCRIPTION +* +* The routine spm_show_mat writes pattern of the specified sparse +* matrix in uncompressed BMP file format (Windows bitmap) to a binary +* file whose name is specified by the character string fname. +* +* Each pixel corresponds to one matrix element. The pixel colors have +* the following meaning: +* +* Black structurally zero element +* White positive element +* Cyan negative element +* Green zero element +* Red duplicate element +* +* RETURNS +* +* If no error occured, the routine returns zero. Otherwise, it prints +* an appropriate error message and returns non-zero. */ + +int spm_show_mat(const SPM *A, const char *fname) +{ int m = A->m; + int n = A->n; + int i, j, k, ret; + char *map; + xprintf("spm_show_mat: writing matrix pattern to `%s'...\n", + fname); + xassert(1 <= m && m <= 32767); + xassert(1 <= n && n <= 32767); + map = xmalloc(m * n); + memset(map, 0x08, m * n); + for (i = 1; i <= m; i++) + { SPME *e; + for (e = A->row[i]; e != NULL; e = e->r_next) + { j = e->j; + xassert(1 <= j && j <= n); + k = n * (i - 1) + (j - 1); + if (map[k] != 0x08) + map[k] = 0x0C; + else if (e->val > 0.0) + map[k] = 0x0F; + else if (e->val < 0.0) + map[k] = 0x0B; + else + map[k] = 0x0A; + } + } + ret = rgr_write_bmp16(fname, m, n, map); + xfree(map); + return ret; +} + +/*********************************************************************** +* NAME +* +* spm_read_hbm - read sparse matrix in Harwell-Boeing format +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_read_hbm(const char *fname); +* +* DESCRIPTION +* +* The routine spm_read_hbm reads a sparse matrix in the Harwell-Boeing +* format from a text file whose name is the character string fname. +* +* Detailed description of the Harwell-Boeing format recognised by this +* routine can be found in the following report: +* +* I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the Harwell-Boeing +* Sparse Matrix Collection (Release I), TR/PA/92/86, October 1992. +* +* NOTE +* +* The routine spm_read_hbm reads the matrix "as is", due to which zero +* and/or duplicate elements can appear in the matrix. +* +* RETURNS +* +* If no error occured, the routine returns a pointer to the matrix +* created. Otherwise, the routine prints an appropriate error message +* and returns NULL. */ + +SPM *spm_read_hbm(const char *fname) +{ SPM *A = NULL; + HBM *hbm; + int nrow, ncol, nnzero, i, j, beg, end, ptr, *colptr, *rowind; + double val, *values; + char *mxtype; + hbm = hbm_read_mat(fname); + if (hbm == NULL) + { xprintf("spm_read_hbm: unable to read matrix\n"); + goto fini; + } + mxtype = hbm->mxtype; + nrow = hbm->nrow; + ncol = hbm->ncol; + nnzero = hbm->nnzero; + colptr = hbm->colptr; + rowind = hbm->rowind; + values = hbm->values; + if (!(strcmp(mxtype, "RSA") == 0 || strcmp(mxtype, "PSA") == 0 || + strcmp(mxtype, "RUA") == 0 || strcmp(mxtype, "PUA") == 0 || + strcmp(mxtype, "RRA") == 0 || strcmp(mxtype, "PRA") == 0)) + { xprintf("spm_read_hbm: matrix type `%s' not supported\n", + mxtype); + goto fini; + } + A = spm_create_mat(nrow, ncol); + if (mxtype[1] == 'S' || mxtype[1] == 'U') + xassert(nrow == ncol); + for (j = 1; j <= ncol; j++) + { beg = colptr[j]; + end = colptr[j+1]; + xassert(1 <= beg && beg <= end && end <= nnzero + 1); + for (ptr = beg; ptr < end; ptr++) + { i = rowind[ptr]; + xassert(1 <= i && i <= nrow); + if (mxtype[0] == 'R') + val = values[ptr]; + else + val = 1.0; + spm_new_elem(A, i, j, val); + if (mxtype[1] == 'S' && i != j) + spm_new_elem(A, j, i, val); + } + } +fini: if (hbm != NULL) hbm_free_mat(hbm); + return A; +} + +/*********************************************************************** +* NAME +* +* spm_count_nnz - determine number of non-zeros in sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* int spm_count_nnz(const SPM *A); +* +* RETURNS +* +* The routine spm_count_nnz returns the number of structural non-zero +* elements in the specified sparse matrix. */ + +int spm_count_nnz(const SPM *A) +{ SPME *e; + int i, nnz = 0; + for (i = 1; i <= A->m; i++) + for (e = A->row[i]; e != NULL; e = e->r_next) nnz++; + return nnz; +} + +/*********************************************************************** +* NAME +* +* spm_drop_zeros - remove zero elements from sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* int spm_drop_zeros(SPM *A, double eps); +* +* DESCRIPTION +* +* The routine spm_drop_zeros removes all elements from the specified +* sparse matrix, whose absolute value is less than eps. +* +* If the parameter eps is 0, only zero elements are removed from the +* matrix. +* +* RETURNS +* +* The routine returns the number of elements removed. */ + +int spm_drop_zeros(SPM *A, double eps) +{ SPME *e, *next; + int i, count = 0; + for (i = 1; i <= A->m; i++) + { for (e = A->row[i]; e != NULL; e = next) + { next = e->r_next; + if (e->val == 0.0 || fabs(e->val) < eps) + { /* remove element from the row list */ + if (e->r_prev == NULL) + A->row[e->i] = e->r_next; + else + e->r_prev->r_next = e->r_next; + if (e->r_next == NULL) + ; + else + e->r_next->r_prev = e->r_prev; + /* remove element from the column list */ + if (e->c_prev == NULL) + A->col[e->j] = e->c_next; + else + e->c_prev->c_next = e->c_next; + if (e->c_next == NULL) + ; + else + e->c_next->c_prev = e->c_prev; + /* return element to the memory pool */ + dmp_free_atom(A->pool, e, sizeof(SPME)); + count++; + } + } + } + return count; +} + +/*********************************************************************** +* NAME +* +* spm_read_mat - read sparse matrix from text file +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_read_mat(const char *fname); +* +* DESCRIPTION +* +* The routine reads a sparse matrix from a text file whose name is +* specified by the parameter fname. +* +* For the file format see description of the routine spm_write_mat. +* +* RETURNS +* +* On success the routine returns a pointer to the matrix created, +* otherwise NULL. */ + +#if 1 +SPM *spm_read_mat(const char *fname) +{ xassert(fname != fname); + return NULL; +} +#else +SPM *spm_read_mat(const char *fname) +{ SPM *A = NULL; + PDS *pds; + jmp_buf jump; + int i, j, k, m, n, nnz, fail = 0; + double val; + xprintf("spm_read_mat: reading matrix from `%s'...\n", fname); + pds = pds_open_file(fname); + if (pds == NULL) + { xprintf("spm_read_mat: unable to open `%s' - %s\n", fname, + strerror(errno)); + fail = 1; + goto done; + } + if (setjmp(jump)) + { fail = 1; + goto done; + } + pds_set_jump(pds, jump); + /* number of rows, number of columns, number of non-zeros */ + m = pds_scan_int(pds); + if (m < 0) + pds_error(pds, "invalid number of rows\n"); + n = pds_scan_int(pds); + if (n < 0) + pds_error(pds, "invalid number of columns\n"); + nnz = pds_scan_int(pds); + if (nnz < 0) + pds_error(pds, "invalid number of non-zeros\n"); + /* create matrix */ + xprintf("spm_read_mat: %d rows, %d columns, %d non-zeros\n", + m, n, nnz); + A = spm_create_mat(m, n); + /* read matrix elements */ + for (k = 1; k <= nnz; k++) + { /* row index, column index, element value */ + i = pds_scan_int(pds); + if (!(1 <= i && i <= m)) + pds_error(pds, "row index out of range\n"); + j = pds_scan_int(pds); + if (!(1 <= j && j <= n)) + pds_error(pds, "column index out of range\n"); + val = pds_scan_num(pds); + /* add new element to the matrix */ + spm_new_elem(A, i, j, val); + } + xprintf("spm_read_mat: %d lines were read\n", pds->count); +done: if (pds != NULL) pds_close_file(pds); + if (fail && A != NULL) spm_delete_mat(A), A = NULL; + return A; +} +#endif + +/*********************************************************************** +* NAME +* +* spm_write_mat - write sparse matrix to text file +* +* SYNOPSIS +* +* #include "glpspm.h" +* int spm_write_mat(const SPM *A, const char *fname); +* +* DESCRIPTION +* +* The routine spm_write_mat writes the specified sparse matrix to a +* text file whose name is specified by the parameter fname. This file +* can be read back with the routine spm_read_mat. +* +* RETURNS +* +* On success the routine returns zero, otherwise non-zero. +* +* FILE FORMAT +* +* The file created by the routine spm_write_mat is a plain text file, +* which contains the following information: +* +* m n nnz +* row[1] col[1] val[1] +* row[2] col[2] val[2] +* . . . +* row[nnz] col[nnz] val[nnz] +* +* where: +* m is the number of rows; +* n is the number of columns; +* nnz is the number of non-zeros; +* row[k], k = 1,...,nnz, are row indices; +* col[k], k = 1,...,nnz, are column indices; +* val[k], k = 1,...,nnz, are element values. */ + +#if 1 +int spm_write_mat(const SPM *A, const char *fname) +{ xassert(A != A); + xassert(fname != fname); + return 0; +} +#else +int spm_write_mat(const SPM *A, const char *fname) +{ FILE *fp; + int i, nnz, ret = 0; + xprintf("spm_write_mat: writing matrix to `%s'...\n", fname); + fp = fopen(fname, "w"); + if (fp == NULL) + { xprintf("spm_write_mat: unable to create `%s' - %s\n", fname, + strerror(errno)); + ret = 1; + goto done; + } + /* number of rows, number of columns, number of non-zeros */ + nnz = spm_count_nnz(A); + fprintf(fp, "%d %d %d\n", A->m, A->n, nnz); + /* walk through rows of the matrix */ + for (i = 1; i <= A->m; i++) + { SPME *e; + /* walk through elements of i-th row */ + for (e = A->row[i]; e != NULL; e = e->r_next) + { /* row index, column index, element value */ + fprintf(fp, "%d %d %.*g\n", e->i, e->j, DBL_DIG, e->val); + } + } + fflush(fp); + if (ferror(fp)) + { xprintf("spm_write_mat: writing error on `%s' - %s\n", fname, + strerror(errno)); + ret = 1; + goto done; + } + xprintf("spm_write_mat: %d lines were written\n", 1 + nnz); +done: if (fp != NULL) fclose(fp); + return ret; +} +#endif + +/*********************************************************************** +* NAME +* +* spm_transpose - transpose sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_transpose(const SPM *A); +* +* RETURNS +* +* The routine computes and returns sparse matrix B, which is a matrix +* transposed to sparse matrix A. */ + +SPM *spm_transpose(const SPM *A) +{ SPM *B; + int i; + B = spm_create_mat(A->n, A->m); + for (i = 1; i <= A->m; i++) + { SPME *e; + for (e = A->row[i]; e != NULL; e = e->r_next) + spm_new_elem(B, e->j, i, e->val); + } + return B; +} + +SPM *spm_add_sym(const SPM *A, const SPM *B) +{ /* add two sparse matrices (symbolic phase) */ + SPM *C; + int i, j, *flag; + xassert(A->m == B->m); + xassert(A->n == B->n); + /* create resultant matrix */ + C = spm_create_mat(A->m, A->n); + /* allocate and clear the flag array */ + flag = xcalloc(1+C->n, sizeof(int)); + for (j = 1; j <= C->n; j++) + flag[j] = 0; + /* compute pattern of C = A + B */ + for (i = 1; i <= C->m; i++) + { SPME *e; + /* at the beginning i-th row of C is empty */ + /* (i-th row of C) := (i-th row of C) union (i-th row of A) */ + for (e = A->row[i]; e != NULL; e = e->r_next) + { /* (note that i-th row of A may have duplicate elements) */ + j = e->j; + if (!flag[j]) + { spm_new_elem(C, i, j, 0.0); + flag[j] = 1; + } + } + /* (i-th row of C) := (i-th row of C) union (i-th row of B) */ + for (e = B->row[i]; e != NULL; e = e->r_next) + { /* (note that i-th row of B may have duplicate elements) */ + j = e->j; + if (!flag[j]) + { spm_new_elem(C, i, j, 0.0); + flag[j] = 1; + } + } + /* reset the flag array */ + for (e = C->row[i]; e != NULL; e = e->r_next) + flag[e->j] = 0; + } + /* check and deallocate the flag array */ + for (j = 1; j <= C->n; j++) + xassert(!flag[j]); + xfree(flag); + return C; +} + +void spm_add_num(SPM *C, double alfa, const SPM *A, double beta, + const SPM *B) +{ /* add two sparse matrices (numeric phase) */ + int i, j; + double *work; + /* allocate and clear the working array */ + work = xcalloc(1+C->n, sizeof(double)); + for (j = 1; j <= C->n; j++) + work[j] = 0.0; + /* compute matrix C = alfa * A + beta * B */ + for (i = 1; i <= C->n; i++) + { SPME *e; + /* work := alfa * (i-th row of A) + beta * (i-th row of B) */ + /* (note that A and/or B may have duplicate elements) */ + for (e = A->row[i]; e != NULL; e = e->r_next) + work[e->j] += alfa * e->val; + for (e = B->row[i]; e != NULL; e = e->r_next) + work[e->j] += beta * e->val; + /* (i-th row of C) := work, work := 0 */ + for (e = C->row[i]; e != NULL; e = e->r_next) + { j = e->j; + e->val = work[j]; + work[j] = 0.0; + } + } + /* check and deallocate the working array */ + for (j = 1; j <= C->n; j++) + xassert(work[j] == 0.0); + xfree(work); + return; +} + +SPM *spm_add_mat(double alfa, const SPM *A, double beta, const SPM *B) +{ /* add two sparse matrices (driver routine) */ + SPM *C; + C = spm_add_sym(A, B); + spm_add_num(C, alfa, A, beta, B); + return C; +} + +SPM *spm_mul_sym(const SPM *A, const SPM *B) +{ /* multiply two sparse matrices (symbolic phase) */ + int i, j, k, *flag; + SPM *C; + xassert(A->n == B->m); + /* create resultant matrix */ + C = spm_create_mat(A->m, B->n); + /* allocate and clear the flag array */ + flag = xcalloc(1+C->n, sizeof(int)); + for (j = 1; j <= C->n; j++) + flag[j] = 0; + /* compute pattern of C = A * B */ + for (i = 1; i <= C->m; i++) + { SPME *e, *ee; + /* compute pattern of i-th row of C */ + for (e = A->row[i]; e != NULL; e = e->r_next) + { k = e->j; + for (ee = B->row[k]; ee != NULL; ee = ee->r_next) + { j = ee->j; + /* if a[i,k] != 0 and b[k,j] != 0 then c[i,j] != 0 */ + if (!flag[j]) + { /* c[i,j] does not exist, so create it */ + spm_new_elem(C, i, j, 0.0); + flag[j] = 1; + } + } + } + /* reset the flag array */ + for (e = C->row[i]; e != NULL; e = e->r_next) + flag[e->j] = 0; + } + /* check and deallocate the flag array */ + for (j = 1; j <= C->n; j++) + xassert(!flag[j]); + xfree(flag); + return C; +} + +void spm_mul_num(SPM *C, const SPM *A, const SPM *B) +{ /* multiply two sparse matrices (numeric phase) */ + int i, j; + double *work; + /* allocate and clear the working array */ + work = xcalloc(1+A->n, sizeof(double)); + for (j = 1; j <= A->n; j++) + work[j] = 0.0; + /* compute matrix C = A * B */ + for (i = 1; i <= C->m; i++) + { SPME *e, *ee; + double temp; + /* work := (i-th row of A) */ + /* (note that A may have duplicate elements) */ + for (e = A->row[i]; e != NULL; e = e->r_next) + work[e->j] += e->val; + /* compute i-th row of C */ + for (e = C->row[i]; e != NULL; e = e->r_next) + { j = e->j; + /* c[i,j] := work * (j-th column of B) */ + temp = 0.0; + for (ee = B->col[j]; ee != NULL; ee = ee->c_next) + temp += work[ee->i] * ee->val; + e->val = temp; + } + /* reset the working array */ + for (e = A->row[i]; e != NULL; e = e->r_next) + work[e->j] = 0.0; + } + /* check and deallocate the working array */ + for (j = 1; j <= A->n; j++) + xassert(work[j] == 0.0); + xfree(work); + return; +} + +SPM *spm_mul_mat(const SPM *A, const SPM *B) +{ /* multiply two sparse matrices (driver routine) */ + SPM *C; + C = spm_mul_sym(A, B); + spm_mul_num(C, A, B); + return C; +} + +PER *spm_create_per(int n) +{ /* create permutation matrix */ + PER *P; + int k; + xassert(n >= 0); + P = xmalloc(sizeof(PER)); + P->n = n; + P->row = xcalloc(1+n, sizeof(int)); + P->col = xcalloc(1+n, sizeof(int)); + /* initially it is identity matrix */ + for (k = 1; k <= n; k++) + P->row[k] = P->col[k] = k; + return P; +} + +void spm_check_per(PER *P) +{ /* check permutation matrix for correctness */ + int i, j; + xassert(P->n >= 0); + for (i = 1; i <= P->n; i++) + { j = P->row[i]; + xassert(1 <= j && j <= P->n); + xassert(P->col[j] == i); + } + return; +} + +void spm_delete_per(PER *P) +{ /* delete permutation matrix */ + xfree(P->row); + xfree(P->col); + xfree(P); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpspm.h b/resources/3rdparty/glpk-4.53/src/glpspm.h new file mode 100644 index 000000000..eda9f98f2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpspm.h @@ -0,0 +1,165 @@ +/* glpspm.h (general sparse matrix) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPSPM_H +#define GLPSPM_H + +#include "dmp.h" + +typedef struct SPM SPM; +typedef struct SPME SPME; + +struct SPM +{ /* general sparse matrix */ + int m; + /* number of rows, m >= 0 */ + int n; + /* number of columns, n >= 0 */ + DMP *pool; + /* memory pool to store matrix elements */ + SPME **row; /* SPME *row[1+m]; */ + /* row[i], 1 <= i <= m, is a pointer to i-th row list */ + SPME **col; /* SPME *col[1+n]; */ + /* col[j], 1 <= j <= n, is a pointer to j-th column list */ +}; + +struct SPME +{ /* sparse matrix element */ + int i; + /* row number */ + int j; + /* column number */ + double val; + /* element value */ + SPME *r_prev; + /* pointer to previous element in the same row */ + SPME *r_next; + /* pointer to next element in the same row */ + SPME *c_prev; + /* pointer to previous element in the same column */ + SPME *c_next; + /* pointer to next element in the same column */ +}; + +typedef struct PER PER; + +struct PER +{ /* permutation matrix */ + int n; + /* matrix order, n >= 0 */ + int *row; /* int row[1+n]; */ + /* row[i] = j means p[i,j] = 1 */ + int *col; /* int col[1+n]; */ + /* col[j] = i means p[i,j] = 1 */ +}; + +#define spm_create_mat _glp_spm_create_mat +SPM *spm_create_mat(int m, int n); +/* create general sparse matrix */ + +#define spm_new_elem _glp_spm_new_elem +SPME *spm_new_elem(SPM *A, int i, int j, double val); +/* add new element to sparse matrix */ + +#define spm_delete_mat _glp_spm_delete_mat +void spm_delete_mat(SPM *A); +/* delete general sparse matrix */ + +#define spm_test_mat_e _glp_spm_test_mat_e +SPM *spm_test_mat_e(int n, int c); +/* create test sparse matrix of E(n,c) class */ + +#define spm_test_mat_d _glp_spm_test_mat_d +SPM *spm_test_mat_d(int n, int c); +/* create test sparse matrix of D(n,c) class */ + +#define spm_show_mat _glp_spm_show_mat +int spm_show_mat(const SPM *A, const char *fname); +/* write sparse matrix pattern in BMP file format */ + +#define spm_read_hbm _glp_spm_read_hbm +SPM *spm_read_hbm(const char *fname); +/* read sparse matrix in Harwell-Boeing format */ + +#define spm_count_nnz _glp_spm_count_nnz +int spm_count_nnz(const SPM *A); +/* determine number of non-zeros in sparse matrix */ + +#define spm_drop_zeros _glp_spm_drop_zeros +int spm_drop_zeros(SPM *A, double eps); +/* remove zero elements from sparse matrix */ + +#define spm_read_mat _glp_spm_read_mat +SPM *spm_read_mat(const char *fname); +/* read sparse matrix from text file */ + +#define spm_write_mat _glp_spm_write_mat +int spm_write_mat(const SPM *A, const char *fname); +/* write sparse matrix to text file */ + +#define spm_transpose _glp_spm_transpose +SPM *spm_transpose(const SPM *A); +/* transpose sparse matrix */ + +#define spm_add_sym _glp_spm_add_sym +SPM *spm_add_sym(const SPM *A, const SPM *B); +/* add two sparse matrices (symbolic phase) */ + +#define spm_add_num _glp_spm_add_num +void spm_add_num(SPM *C, double alfa, const SPM *A, double beta, + const SPM *B); +/* add two sparse matrices (numeric phase) */ + +#define spm_add_mat _glp_spm_add_mat +SPM *spm_add_mat(double alfa, const SPM *A, double beta, + const SPM *B); +/* add two sparse matrices (driver routine) */ + +#define spm_mul_sym _glp_spm_mul_sym +SPM *spm_mul_sym(const SPM *A, const SPM *B); +/* multiply two sparse matrices (symbolic phase) */ + +#define spm_mul_num _glp_spm_mul_num +void spm_mul_num(SPM *C, const SPM *A, const SPM *B); +/* multiply two sparse matrices (numeric phase) */ + +#define spm_mul_mat _glp_spm_mul_mat +SPM *spm_mul_mat(const SPM *A, const SPM *B); +/* multiply two sparse matrices (driver routine) */ + +#define spm_create_per _glp_spm_create_per +PER *spm_create_per(int n); +/* create permutation matrix */ + +#define spm_check_per _glp_spm_check_per +void spm_check_per(PER *P); +/* check permutation matrix for correctness */ + +#define spm_delete_per _glp_spm_delete_per +void spm_delete_per(PER *P); +/* delete permutation matrix */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpspx.h b/resources/3rdparty/glpk-4.53/src/glpspx.h new file mode 100644 index 000000000..e62687a6c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpspx.h @@ -0,0 +1,40 @@ +/* glpspx.h (core simplex solvers) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPSPX_H +#define GLPSPX_H + +#include "prob.h" + +#define spx_primal _glp_spx_primal +int spx_primal(glp_prob *lp, const glp_smcp *parm); +/* core LP solver based on the primal simplex method */ + +#define spx_dual _glp_spx_dual +int spx_dual(glp_prob *lp, const glp_smcp *parm); +/* core LP solver based on the dual simplex method */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpspx01.c b/resources/3rdparty/glpk-4.53/src/glpspx01.c new file mode 100644 index 000000000..eb0e4b50c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpspx01.c @@ -0,0 +1,2971 @@ +/* glpspx01.c (primal simplex method) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpspx.h" + +struct csa +{ /* common storage area */ + /*--------------------------------------------------------------*/ + /* LP data */ + int m; + /* number of rows (auxiliary variables), m > 0 */ + int n; + /* number of columns (structural variables), n > 0 */ + char *type; /* char type[1+m+n]; */ + /* type[0] is not used; + type[k], 1 <= k <= m+n, is the type of variable x[k]: + GLP_FR - free variable + GLP_LO - variable with lower bound + GLP_UP - variable with upper bound + GLP_DB - double-bounded variable + GLP_FX - fixed variable */ + double *lb; /* double lb[1+m+n]; */ + /* lb[0] is not used; + lb[k], 1 <= k <= m+n, is an lower bound of variable x[k]; + if x[k] has no lower bound, lb[k] is zero */ + double *ub; /* double ub[1+m+n]; */ + /* ub[0] is not used; + ub[k], 1 <= k <= m+n, is an upper bound of variable x[k]; + if x[k] has no upper bound, ub[k] is zero; + if x[k] is of fixed type, ub[k] is the same as lb[k] */ + double *coef; /* double coef[1+m+n]; */ + /* coef[0] is not used; + coef[k], 1 <= k <= m+n, is an objective coefficient at + variable x[k] (note that on phase I auxiliary variables also + may have non-zero objective coefficients) */ + /*--------------------------------------------------------------*/ + /* original objective function */ + double *obj; /* double obj[1+n]; */ + /* obj[0] is a constant term of the original objective function; + obj[j], 1 <= j <= n, is an original objective coefficient at + structural variable x[m+j] */ + double zeta; + /* factor used to scale original objective coefficients; its + sign defines original optimization direction: zeta > 0 means + minimization, zeta < 0 means maximization */ + /*--------------------------------------------------------------*/ + /* constraint matrix A; it has m rows and n columns and is stored + by columns */ + int *A_ptr; /* int A_ptr[1+n+1]; */ + /* A_ptr[0] is not used; + A_ptr[j], 1 <= j <= n, is starting position of j-th column in + arrays A_ind and A_val; note that A_ptr[1] is always 1; + A_ptr[n+1] indicates the position after the last element in + arrays A_ind and A_val */ + int *A_ind; /* int A_ind[A_ptr[n+1]]; */ + /* row indices */ + double *A_val; /* double A_val[A_ptr[n+1]]; */ + /* non-zero element values */ + /*--------------------------------------------------------------*/ + /* basis header */ + int *head; /* int head[1+m+n]; */ + /* head[0] is not used; + head[i], 1 <= i <= m, is the ordinal number of basic variable + xB[i]; head[i] = k means that xB[i] = x[k] and i-th column of + matrix B is k-th column of matrix (I|-A); + head[m+j], 1 <= j <= n, is the ordinal number of non-basic + variable xN[j]; head[m+j] = k means that xN[j] = x[k] and j-th + column of matrix N is k-th column of matrix (I|-A) */ + char *stat; /* char stat[1+n]; */ + /* stat[0] is not used; + stat[j], 1 <= j <= n, is the status of non-basic variable + xN[j], which defines its active bound: + GLP_NL - lower bound is active + GLP_NU - upper bound is active + GLP_NF - free variable + GLP_NS - fixed variable */ + /*--------------------------------------------------------------*/ + /* matrix B is the basis matrix; it is composed from columns of + the augmented constraint matrix (I|-A) corresponding to basic + variables and stored in a factorized (invertable) form */ + int valid; + /* factorization is valid only if this flag is set */ + BFD *bfd; /* BFD bfd[1:m,1:m]; */ + /* factorized (invertable) form of the basis matrix */ + /*--------------------------------------------------------------*/ + /* matrix N is a matrix composed from columns of the augmented + constraint matrix (I|-A) corresponding to non-basic variables + except fixed ones; it is stored by rows and changes every time + the basis changes */ + int *N_ptr; /* int N_ptr[1+m+1]; */ + /* N_ptr[0] is not used; + N_ptr[i], 1 <= i <= m, is starting position of i-th row in + arrays N_ind and N_val; note that N_ptr[1] is always 1; + N_ptr[m+1] indicates the position after the last element in + arrays N_ind and N_val */ + int *N_len; /* int N_len[1+m]; */ + /* N_len[0] is not used; + N_len[i], 1 <= i <= m, is length of i-th row (0 to n) */ + int *N_ind; /* int N_ind[N_ptr[m+1]]; */ + /* column indices */ + double *N_val; /* double N_val[N_ptr[m+1]]; */ + /* non-zero element values */ + /*--------------------------------------------------------------*/ + /* working parameters */ + int phase; + /* search phase: + 0 - not determined yet + 1 - search for primal feasible solution + 2 - search for optimal solution */ +#if 0 /* 10/VI-2013 */ + glp_long tm_beg; + /* time value at the beginning of the search */ +#else + double tm_beg; +#endif + int it_beg; + /* simplex iteration count at the beginning of the search */ + int it_cnt; + /* simplex iteration count; it increases by one every time the + basis changes (including the case when a non-basic variable + jumps to its opposite bound) */ + int it_dpy; + /* simplex iteration count at the most recent display output */ + /*--------------------------------------------------------------*/ + /* basic solution components */ + double *bbar; /* double bbar[1+m]; */ + /* bbar[0] is not used; + bbar[i], 1 <= i <= m, is primal value of basic variable xB[i] + (if xB[i] is free, its primal value is not updated) */ + double *cbar; /* double cbar[1+n]; */ + /* cbar[0] is not used; + cbar[j], 1 <= j <= n, is reduced cost of non-basic variable + xN[j] (if xN[j] is fixed, its reduced cost is not updated) */ + /*--------------------------------------------------------------*/ + /* the following pricing technique options may be used: + GLP_PT_STD - standard ("textbook") pricing; + GLP_PT_PSE - projected steepest edge; + GLP_PT_DVX - Devex pricing (not implemented yet); + in case of GLP_PT_STD the reference space is not used, and all + steepest edge coefficients are set to 1 */ + int refct; + /* this count is set to an initial value when the reference space + is defined and decreases by one every time the basis changes; + once this count reaches zero, the reference space is redefined + again */ + char *refsp; /* char refsp[1+m+n]; */ + /* refsp[0] is not used; + refsp[k], 1 <= k <= m+n, is the flag which means that variable + x[k] belongs to the current reference space */ + double *gamma; /* double gamma[1+n]; */ + /* gamma[0] is not used; + gamma[j], 1 <= j <= n, is the steepest edge coefficient for + non-basic variable xN[j]; if xN[j] is fixed, gamma[j] is not + used and just set to 1 */ + /*--------------------------------------------------------------*/ + /* non-basic variable xN[q] chosen to enter the basis */ + int q; + /* index of the non-basic variable xN[q] chosen, 1 <= q <= n; + if the set of eligible non-basic variables is empty and thus + no variable has been chosen, q is set to 0 */ + /*--------------------------------------------------------------*/ + /* pivot column of the simplex table corresponding to non-basic + variable xN[q] chosen is the following vector: + T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], + where B is the current basis matrix, N[q] is a column of the + matrix (I|-A) corresponding to xN[q] */ + int tcol_nnz; + /* number of non-zero components, 0 <= nnz <= m */ + int *tcol_ind; /* int tcol_ind[1+m]; */ + /* tcol_ind[0] is not used; + tcol_ind[t], 1 <= t <= nnz, is an index of non-zero component, + i.e. tcol_ind[t] = i means that tcol_vec[i] != 0 */ + double *tcol_vec; /* double tcol_vec[1+m]; */ + /* tcol_vec[0] is not used; + tcol_vec[i], 1 <= i <= m, is a numeric value of i-th component + of the column */ + double tcol_max; + /* infinity (maximum) norm of the column (max |tcol_vec[i]|) */ + int tcol_num; + /* number of significant non-zero components, which means that: + |tcol_vec[i]| >= eps for i in tcol_ind[1,...,num], + |tcol_vec[i]| < eps for i in tcol_ind[num+1,...,nnz], + where eps is a pivot tolerance */ + /*--------------------------------------------------------------*/ + /* basic variable xB[p] chosen to leave the basis */ + int p; + /* index of the basic variable xB[p] chosen, 1 <= p <= m; + p = 0 means that no basic variable reaches its bound; + p < 0 means that non-basic variable xN[q] reaches its opposite + bound before any basic variable */ + int p_stat; + /* new status (GLP_NL, GLP_NU, or GLP_NS) to be assigned to xB[p] + once it has left the basis */ + double teta; + /* change of non-basic variable xN[q] (see above), on which xB[p] + (or, if p < 0, xN[q] itself) reaches its bound */ + /*--------------------------------------------------------------*/ + /* pivot row of the simplex table corresponding to basic variable + xB[p] chosen is the following vector: + T' * e[p] = - N' * inv(B') * e[p] = - N' * rho, + where B' is a matrix transposed to the current basis matrix, + N' is a matrix, whose rows are columns of the matrix (I|-A) + corresponding to non-basic non-fixed variables */ + int trow_nnz; + /* number of non-zero components, 0 <= nnz <= n */ + int *trow_ind; /* int trow_ind[1+n]; */ + /* trow_ind[0] is not used; + trow_ind[t], 1 <= t <= nnz, is an index of non-zero component, + i.e. trow_ind[t] = j means that trow_vec[j] != 0 */ + double *trow_vec; /* int trow_vec[1+n]; */ + /* trow_vec[0] is not used; + trow_vec[j], 1 <= j <= n, is a numeric value of j-th component + of the row */ + /*--------------------------------------------------------------*/ + /* working arrays */ + double *work1; /* double work1[1+m]; */ + double *work2; /* double work2[1+m]; */ + double *work3; /* double work3[1+m]; */ + double *work4; /* double work4[1+m]; */ +}; + +static const double kappa = 0.10; + +/*********************************************************************** +* alloc_csa - allocate common storage area +* +* This routine allocates all arrays in the common storage area (CSA) +* and returns a pointer to the CSA. */ + +static struct csa *alloc_csa(glp_prob *lp) +{ struct csa *csa; + int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + csa = xmalloc(sizeof(struct csa)); + xassert(m > 0 && n > 0); + csa->m = m; + csa->n = n; + csa->type = xcalloc(1+m+n, sizeof(char)); + csa->lb = xcalloc(1+m+n, sizeof(double)); + csa->ub = xcalloc(1+m+n, sizeof(double)); + csa->coef = xcalloc(1+m+n, sizeof(double)); + csa->obj = xcalloc(1+n, sizeof(double)); + csa->A_ptr = xcalloc(1+n+1, sizeof(int)); + csa->A_ind = xcalloc(1+nnz, sizeof(int)); + csa->A_val = xcalloc(1+nnz, sizeof(double)); + csa->head = xcalloc(1+m+n, sizeof(int)); + csa->stat = xcalloc(1+n, sizeof(char)); + csa->N_ptr = xcalloc(1+m+1, sizeof(int)); + csa->N_len = xcalloc(1+m, sizeof(int)); + csa->N_ind = NULL; /* will be allocated later */ + csa->N_val = NULL; /* will be allocated later */ + csa->bbar = xcalloc(1+m, sizeof(double)); + csa->cbar = xcalloc(1+n, sizeof(double)); + csa->refsp = xcalloc(1+m+n, sizeof(char)); + csa->gamma = xcalloc(1+n, sizeof(double)); + csa->tcol_ind = xcalloc(1+m, sizeof(int)); + csa->tcol_vec = xcalloc(1+m, sizeof(double)); + csa->trow_ind = xcalloc(1+n, sizeof(int)); + csa->trow_vec = xcalloc(1+n, sizeof(double)); + csa->work1 = xcalloc(1+m, sizeof(double)); + csa->work2 = xcalloc(1+m, sizeof(double)); + csa->work3 = xcalloc(1+m, sizeof(double)); + csa->work4 = xcalloc(1+m, sizeof(double)); + return csa; +} + +/*********************************************************************** +* init_csa - initialize common storage area +* +* This routine initializes all data structures in the common storage +* area (CSA). */ + +static void alloc_N(struct csa *csa); +static void build_N(struct csa *csa); + +static void init_csa(struct csa *csa, glp_prob *lp) +{ int m = csa->m; + int n = csa->n; + char *type = csa->type; + double *lb = csa->lb; + double *ub = csa->ub; + double *coef = csa->coef; + double *obj = csa->obj; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + char *stat = csa->stat; + char *refsp = csa->refsp; + double *gamma = csa->gamma; + int i, j, k, loc; + double cmax; + /* auxiliary variables */ + for (i = 1; i <= m; i++) + { GLPROW *row = lp->row[i]; + type[i] = (char)row->type; + lb[i] = row->lb * row->rii; + ub[i] = row->ub * row->rii; + coef[i] = 0.0; + } + /* structural variables */ + for (j = 1; j <= n; j++) + { GLPCOL *col = lp->col[j]; + type[m+j] = (char)col->type; + lb[m+j] = col->lb / col->sjj; + ub[m+j] = col->ub / col->sjj; + coef[m+j] = col->coef * col->sjj; + } + /* original objective function */ + obj[0] = lp->c0; + memcpy(&obj[1], &coef[m+1], n * sizeof(double)); + /* factor used to scale original objective coefficients */ + cmax = 0.0; + for (j = 1; j <= n; j++) + if (cmax < fabs(obj[j])) cmax = fabs(obj[j]); + if (cmax == 0.0) cmax = 1.0; + switch (lp->dir) + { case GLP_MIN: + csa->zeta = + 1.0 / cmax; + break; + case GLP_MAX: + csa->zeta = - 1.0 / cmax; + break; + default: + xassert(lp != lp); + } +#if 1 + if (fabs(csa->zeta) < 1.0) csa->zeta *= 1000.0; +#endif + /* matrix A (by columns) */ + loc = 1; + for (j = 1; j <= n; j++) + { GLPAIJ *aij; + A_ptr[j] = loc; + for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) + { A_ind[loc] = aij->row->i; + A_val[loc] = aij->row->rii * aij->val * aij->col->sjj; + loc++; + } + } + A_ptr[n+1] = loc; + xassert(loc == lp->nnz+1); + /* basis header */ + xassert(lp->valid); + memcpy(&head[1], &lp->head[1], m * sizeof(int)); + k = 0; + for (i = 1; i <= m; i++) + { GLPROW *row = lp->row[i]; + if (row->stat != GLP_BS) + { k++; + xassert(k <= n); + head[m+k] = i; + stat[k] = (char)row->stat; + } + } + for (j = 1; j <= n; j++) + { GLPCOL *col = lp->col[j]; + if (col->stat != GLP_BS) + { k++; + xassert(k <= n); + head[m+k] = m + j; + stat[k] = (char)col->stat; + } + } + xassert(k == n); + /* factorization of matrix B */ + csa->valid = 1, lp->valid = 0; + csa->bfd = lp->bfd, lp->bfd = NULL; + /* matrix N (by rows) */ + alloc_N(csa); + build_N(csa); + /* working parameters */ + csa->phase = 0; + csa->tm_beg = xtime(); + csa->it_beg = csa->it_cnt = lp->it_cnt; + csa->it_dpy = -1; + /* reference space and steepest edge coefficients */ + csa->refct = 0; + memset(&refsp[1], 0, (m+n) * sizeof(char)); + for (j = 1; j <= n; j++) gamma[j] = 1.0; + return; +} + +/*********************************************************************** +* invert_B - compute factorization of the basis matrix +* +* This routine computes factorization of the current basis matrix B. +* +* If the operation is successful, the routine returns zero, otherwise +* non-zero. */ + +static int inv_col(void *info, int i, int ind[], double val[]) +{ /* this auxiliary routine returns row indices and numeric values + of non-zero elements of i-th column of the basis matrix */ + struct csa *csa = info; + int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + int k, len, ptr, t; +#ifdef GLP_DEBUG + xassert(1 <= i && i <= m); +#endif + k = head[i]; /* B[i] is k-th column of (I|-A) */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { /* B[i] is k-th column of submatrix I */ + len = 1; + ind[1] = k; + val[1] = 1.0; + } + else + { /* B[i] is (k-m)-th column of submatrix (-A) */ + ptr = A_ptr[k-m]; + len = A_ptr[k-m+1] - ptr; + memcpy(&ind[1], &A_ind[ptr], len * sizeof(int)); + memcpy(&val[1], &A_val[ptr], len * sizeof(double)); + for (t = 1; t <= len; t++) val[t] = - val[t]; + } + return len; +} + +static int invert_B(struct csa *csa) +{ int ret; + ret = bfd_factorize(csa->bfd, csa->m, NULL, inv_col, csa); + csa->valid = (ret == 0); + return ret; +} + +/*********************************************************************** +* update_B - update factorization of the basis matrix +* +* This routine replaces i-th column of the basis matrix B by k-th +* column of the augmented constraint matrix (I|-A) and then updates +* the factorization of B. +* +* If the factorization has been successfully updated, the routine +* returns zero, otherwise non-zero. */ + +static int update_B(struct csa *csa, int i, int k) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int ret; +#ifdef GLP_DEBUG + xassert(1 <= i && i <= m); + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { /* new i-th column of B is k-th column of I */ + int ind[1+1]; + double val[1+1]; + ind[1] = k; + val[1] = 1.0; + xassert(csa->valid); + ret = bfd_update_it(csa->bfd, i, 0, 1, ind, val); + } + else + { /* new i-th column of B is (k-m)-th column of (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + double *val = csa->work1; + int beg, end, ptr, len; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + len = 0; + for (ptr = beg; ptr < end; ptr++) + val[++len] = - A_val[ptr]; + xassert(csa->valid); + ret = bfd_update_it(csa->bfd, i, 0, len, &A_ind[beg-1], val); + } + csa->valid = (ret == 0); + return ret; +} + +/*********************************************************************** +* error_ftran - compute residual vector r = h - B * x +* +* This routine computes the residual vector r = h - B * x, where B is +* the current basis matrix, h is the vector of right-hand sides, x is +* the solution vector. */ + +static void error_ftran(struct csa *csa, double h[], double x[], + double r[]) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + int i, k, beg, end, ptr; + double temp; + /* compute the residual vector: + r = h - B * x = h - B[1] * x[1] - ... - B[m] * x[m], + where B[1], ..., B[m] are columns of matrix B */ + memcpy(&r[1], &h[1], m * sizeof(double)); + for (i = 1; i <= m; i++) + { temp = x[i]; + if (temp == 0.0) continue; + k = head[i]; /* B[i] is k-th column of (I|-A) */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { /* B[i] is k-th column of submatrix I */ + r[k] -= temp; + } + else + { /* B[i] is (k-m)-th column of submatrix (-A) */ + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + r[A_ind[ptr]] += A_val[ptr] * temp; + } + } + return; +} + +/*********************************************************************** +* refine_ftran - refine solution of B * x = h +* +* This routine performs one iteration to refine the solution of +* the system B * x = h, where B is the current basis matrix, h is the +* vector of right-hand sides, x is the solution vector. */ + +static void refine_ftran(struct csa *csa, double h[], double x[]) +{ int m = csa->m; + double *r = csa->work1; + double *d = csa->work1; + int i; + /* compute the residual vector r = h - B * x */ + error_ftran(csa, h, x, r); + /* compute the correction vector d = inv(B) * r */ + xassert(csa->valid); + bfd_ftran(csa->bfd, d); + /* refine the solution vector (new x) = (old x) + d */ + for (i = 1; i <= m; i++) x[i] += d[i]; + return; +} + +/*********************************************************************** +* error_btran - compute residual vector r = h - B'* x +* +* This routine computes the residual vector r = h - B'* x, where B' +* is a matrix transposed to the current basis matrix, h is the vector +* of right-hand sides, x is the solution vector. */ + +static void error_btran(struct csa *csa, double h[], double x[], + double r[]) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + int i, k, beg, end, ptr; + double temp; + /* compute the residual vector r = b - B'* x */ + for (i = 1; i <= m; i++) + { /* r[i] := b[i] - (i-th column of B)'* x */ + k = head[i]; /* B[i] is k-th column of (I|-A) */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + temp = h[i]; + if (k <= m) + { /* B[i] is k-th column of submatrix I */ + temp -= x[k]; + } + else + { /* B[i] is (k-m)-th column of submatrix (-A) */ + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + temp += A_val[ptr] * x[A_ind[ptr]]; + } + r[i] = temp; + } + return; +} + +/*********************************************************************** +* refine_btran - refine solution of B'* x = h +* +* This routine performs one iteration to refine the solution of the +* system B'* x = h, where B' is a matrix transposed to the current +* basis matrix, h is the vector of right-hand sides, x is the solution +* vector. */ + +static void refine_btran(struct csa *csa, double h[], double x[]) +{ int m = csa->m; + double *r = csa->work1; + double *d = csa->work1; + int i; + /* compute the residual vector r = h - B'* x */ + error_btran(csa, h, x, r); + /* compute the correction vector d = inv(B') * r */ + xassert(csa->valid); + bfd_btran(csa->bfd, d); + /* refine the solution vector (new x) = (old x) + d */ + for (i = 1; i <= m; i++) x[i] += d[i]; + return; +} + +/*********************************************************************** +* alloc_N - allocate matrix N +* +* This routine determines maximal row lengths of matrix N, sets its +* row pointers, and then allocates arrays N_ind and N_val. +* +* Note that some fixed structural variables may temporarily become +* double-bounded, so corresponding columns of matrix A should not be +* ignored on calculating maximal row lengths of matrix N. */ + +static void alloc_N(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + int *N_ptr = csa->N_ptr; + int *N_len = csa->N_len; + int i, j, beg, end, ptr; + /* determine number of non-zeros in each row of the augmented + constraint matrix (I|-A) */ + for (i = 1; i <= m; i++) + N_len[i] = 1; + for (j = 1; j <= n; j++) + { beg = A_ptr[j]; + end = A_ptr[j+1]; + for (ptr = beg; ptr < end; ptr++) + N_len[A_ind[ptr]]++; + } + /* determine maximal row lengths of matrix N and set its row + pointers */ + N_ptr[1] = 1; + for (i = 1; i <= m; i++) + { /* row of matrix N cannot have more than n non-zeros */ + if (N_len[i] > n) N_len[i] = n; + N_ptr[i+1] = N_ptr[i] + N_len[i]; + } + /* now maximal number of non-zeros in matrix N is known */ + csa->N_ind = xcalloc(N_ptr[m+1], sizeof(int)); + csa->N_val = xcalloc(N_ptr[m+1], sizeof(double)); + return; +} + +/*********************************************************************** +* add_N_col - add column of matrix (I|-A) to matrix N +* +* This routine adds j-th column to matrix N which is k-th column of +* the augmented constraint matrix (I|-A). (It is assumed that old j-th +* column was previously removed from matrix N.) */ + +static void add_N_col(struct csa *csa, int j, int k) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *N_ptr = csa->N_ptr; + int *N_len = csa->N_len; + int *N_ind = csa->N_ind; + double *N_val = csa->N_val; + int pos; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { /* N[j] is k-th column of submatrix I */ + pos = N_ptr[k] + (N_len[k]++); +#ifdef GLP_DEBUG + xassert(pos < N_ptr[k+1]); +#endif + N_ind[pos] = j; + N_val[pos] = 1.0; + } + else + { /* N[j] is (k-m)-th column of submatrix (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int i, beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + { i = A_ind[ptr]; /* row number */ + pos = N_ptr[i] + (N_len[i]++); +#ifdef GLP_DEBUG + xassert(pos < N_ptr[i+1]); +#endif + N_ind[pos] = j; + N_val[pos] = - A_val[ptr]; + } + } + return; +} + +/*********************************************************************** +* del_N_col - remove column of matrix (I|-A) from matrix N +* +* This routine removes j-th column from matrix N which is k-th column +* of the augmented constraint matrix (I|-A). */ + +static void del_N_col(struct csa *csa, int j, int k) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *N_ptr = csa->N_ptr; + int *N_len = csa->N_len; + int *N_ind = csa->N_ind; + double *N_val = csa->N_val; + int pos, head, tail; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { /* N[j] is k-th column of submatrix I */ + /* find element in k-th row of N */ + head = N_ptr[k]; + for (pos = head; N_ind[pos] != j; pos++) /* nop */; + /* and remove it from the row list */ + tail = head + (--N_len[k]); +#ifdef GLP_DEBUG + xassert(pos <= tail); +#endif + N_ind[pos] = N_ind[tail]; + N_val[pos] = N_val[tail]; + } + else + { /* N[j] is (k-m)-th column of submatrix (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + int i, beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + { i = A_ind[ptr]; /* row number */ + /* find element in i-th row of N */ + head = N_ptr[i]; + for (pos = head; N_ind[pos] != j; pos++) /* nop */; + /* and remove it from the row list */ + tail = head + (--N_len[i]); +#ifdef GLP_DEBUG + xassert(pos <= tail); +#endif + N_ind[pos] = N_ind[tail]; + N_val[pos] = N_val[tail]; + } + } + return; +} + +/*********************************************************************** +* build_N - build matrix N for current basis +* +* This routine builds matrix N for the current basis from columns +* of the augmented constraint matrix (I|-A) corresponding to non-basic +* non-fixed variables. */ + +static void build_N(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + int *head = csa->head; + char *stat = csa->stat; + int *N_len = csa->N_len; + int j, k; + /* N := empty matrix */ + memset(&N_len[1], 0, m * sizeof(int)); + /* go through non-basic columns of matrix (I|-A) */ + for (j = 1; j <= n; j++) + { if (stat[j] != GLP_NS) + { /* xN[j] is non-fixed; add j-th column to matrix N which is + k-th column of matrix (I|-A) */ + k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + add_N_col(csa, j, k); + } + } + return; +} + +/*********************************************************************** +* get_xN - determine current value of non-basic variable xN[j] +* +* This routine returns the current value of non-basic variable xN[j], +* which is a value of its active bound. */ + +static double get_xN(struct csa *csa, int j) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + double *lb = csa->lb; + double *ub = csa->ub; + int *head = csa->head; + char *stat = csa->stat; + int k; + double xN; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); +#endif + k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + switch (stat[j]) + { case GLP_NL: + /* x[k] is on its lower bound */ + xN = lb[k]; break; + case GLP_NU: + /* x[k] is on its upper bound */ + xN = ub[k]; break; + case GLP_NF: + /* x[k] is free non-basic variable */ + xN = 0.0; break; + case GLP_NS: + /* x[k] is fixed non-basic variable */ + xN = lb[k]; break; + default: + xassert(stat != stat); + } + return xN; +} + +/*********************************************************************** +* eval_beta - compute primal values of basic variables +* +* This routine computes current primal values of all basic variables: +* +* beta = - inv(B) * N * xN, +* +* where B is the current basis matrix, N is a matrix built of columns +* of matrix (I|-A) corresponding to non-basic variables, and xN is the +* vector of current values of non-basic variables. */ + +static void eval_beta(struct csa *csa, double beta[]) +{ int m = csa->m; + int n = csa->n; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + double *h = csa->work2; + int i, j, k, beg, end, ptr; + double xN; + /* compute the right-hand side vector: + h := - N * xN = - N[1] * xN[1] - ... - N[n] * xN[n], + where N[1], ..., N[n] are columns of matrix N */ + for (i = 1; i <= m; i++) + h[i] = 0.0; + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + /* determine current value of xN[j] */ + xN = get_xN(csa, j); + if (xN == 0.0) continue; + if (k <= m) + { /* N[j] is k-th column of submatrix I */ + h[k] -= xN; + } + else + { /* N[j] is (k-m)-th column of submatrix (-A) */ + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + h[A_ind[ptr]] += xN * A_val[ptr]; + } + } + /* solve system B * beta = h */ + memcpy(&beta[1], &h[1], m * sizeof(double)); + xassert(csa->valid); + bfd_ftran(csa->bfd, beta); + /* and refine the solution */ + refine_ftran(csa, h, beta); + return; +} + +/*********************************************************************** +* eval_pi - compute vector of simplex multipliers +* +* This routine computes the vector of current simplex multipliers: +* +* pi = inv(B') * cB, +* +* where B' is a matrix transposed to the current basis matrix, cB is +* a subvector of objective coefficients at basic variables. */ + +static void eval_pi(struct csa *csa, double pi[]) +{ int m = csa->m; + double *c = csa->coef; + int *head = csa->head; + double *cB = csa->work2; + int i; + /* construct the right-hand side vector cB */ + for (i = 1; i <= m; i++) + cB[i] = c[head[i]]; + /* solve system B'* pi = cB */ + memcpy(&pi[1], &cB[1], m * sizeof(double)); + xassert(csa->valid); + bfd_btran(csa->bfd, pi); + /* and refine the solution */ + refine_btran(csa, cB, pi); + return; +} + +/*********************************************************************** +* eval_cost - compute reduced cost of non-basic variable xN[j] +* +* This routine computes the current reduced cost of non-basic variable +* xN[j]: +* +* d[j] = cN[j] - N'[j] * pi, +* +* where cN[j] is the objective coefficient at variable xN[j], N[j] is +* a column of the augmented constraint matrix (I|-A) corresponding to +* xN[j], pi is the vector of simplex multipliers. */ + +static double eval_cost(struct csa *csa, double pi[], int j) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + double *coef = csa->coef; + int *head = csa->head; + int k; + double dj; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); +#endif + k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + dj = coef[k]; + if (k <= m) + { /* N[j] is k-th column of submatrix I */ + dj -= pi[k]; + } + else + { /* N[j] is (k-m)-th column of submatrix (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + dj += A_val[ptr] * pi[A_ind[ptr]]; + } + return dj; +} + +/*********************************************************************** +* eval_bbar - compute and store primal values of basic variables +* +* This routine computes primal values of all basic variables and then +* stores them in the solution array. */ + +static void eval_bbar(struct csa *csa) +{ eval_beta(csa, csa->bbar); + return; +} + +/*********************************************************************** +* eval_cbar - compute and store reduced costs of non-basic variables +* +* This routine computes reduced costs of all non-basic variables and +* then stores them in the solution array. */ + +static void eval_cbar(struct csa *csa) +{ +#ifdef GLP_DEBUG + int m = csa->m; +#endif + int n = csa->n; +#ifdef GLP_DEBUG + int *head = csa->head; +#endif + double *cbar = csa->cbar; + double *pi = csa->work3; + int j; +#ifdef GLP_DEBUG + int k; +#endif + /* compute simplex multipliers */ + eval_pi(csa, pi); + /* compute and store reduced costs */ + for (j = 1; j <= n; j++) + { +#ifdef GLP_DEBUG + k = head[m+j]; /* x[k] = xN[j] */ + xassert(1 <= k && k <= m+n); +#endif + cbar[j] = eval_cost(csa, pi, j); + } + return; +} + +/*********************************************************************** +* reset_refsp - reset the reference space +* +* This routine resets (redefines) the reference space used in the +* projected steepest edge pricing algorithm. */ + +static void reset_refsp(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + int *head = csa->head; + char *refsp = csa->refsp; + double *gamma = csa->gamma; + int j, k; + xassert(csa->refct == 0); + csa->refct = 1000; + memset(&refsp[1], 0, (m+n) * sizeof(char)); + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + refsp[k] = 1; + gamma[j] = 1.0; + } + return; +} + +/*********************************************************************** +* eval_gamma - compute steepest edge coefficient +* +* This routine computes the steepest edge coefficient for non-basic +* variable xN[j] using its direct definition: +* +* gamma[j] = delta[j] + sum alfa[i,j]^2, +* i in R +* +* where delta[j] = 1, if xN[j] is in the current reference space, +* and 0 otherwise; R is a set of basic variables xB[i], which are in +* the current reference space; alfa[i,j] are elements of the current +* simplex table. +* +* NOTE: The routine is intended only for debugginig purposes. */ + +static double eval_gamma(struct csa *csa, int j) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *head = csa->head; + char *refsp = csa->refsp; + double *alfa = csa->work3; + double *h = csa->work3; + int i, k; + double gamma; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); +#endif + k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + /* construct the right-hand side vector h = - N[j] */ + for (i = 1; i <= m; i++) + h[i] = 0.0; + if (k <= m) + { /* N[j] is k-th column of submatrix I */ + h[k] = -1.0; + } + else + { /* N[j] is (k-m)-th column of submatrix (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + h[A_ind[ptr]] = A_val[ptr]; + } + /* solve system B * alfa = h */ + xassert(csa->valid); + bfd_ftran(csa->bfd, alfa); + /* compute gamma */ + gamma = (refsp[k] ? 1.0 : 0.0); + for (i = 1; i <= m; i++) + { k = head[i]; +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (refsp[k]) gamma += alfa[i] * alfa[i]; + } + return gamma; +} + +/*********************************************************************** +* chuzc - choose non-basic variable (column of the simplex table) +* +* This routine chooses non-basic variable xN[q], which has largest +* weighted reduced cost: +* +* |d[q]| / sqrt(gamma[q]) = max |d[j]| / sqrt(gamma[j]), +* j in J +* +* where J is a subset of eligible non-basic variables xN[j], d[j] is +* reduced cost of xN[j], gamma[j] is the steepest edge coefficient. +* +* The working objective function is always minimized, so the sign of +* d[q] determines direction, in which xN[q] has to change: +* +* if d[q] < 0, xN[q] has to increase; +* +* if d[q] > 0, xN[q] has to decrease. +* +* If |d[j]| <= tol_dj, where tol_dj is a specified tolerance, xN[j] +* is not included in J and therefore ignored. (It is assumed that the +* working objective row is appropriately scaled, i.e. max|c[k]| = 1.) +* +* If J is empty and no variable has been chosen, q is set to 0. */ + +static void chuzc(struct csa *csa, double tol_dj) +{ int n = csa->n; + char *stat = csa->stat; + double *cbar = csa->cbar; + double *gamma = csa->gamma; + int j, q; + double dj, best, temp; + /* nothing is chosen so far */ + q = 0, best = 0.0; + /* look through the list of non-basic variables */ + for (j = 1; j <= n; j++) + { dj = cbar[j]; + switch (stat[j]) + { case GLP_NL: + /* xN[j] can increase */ + if (dj >= - tol_dj) continue; + break; + case GLP_NU: + /* xN[j] can decrease */ + if (dj <= + tol_dj) continue; + break; + case GLP_NF: + /* xN[j] can change in any direction */ + if (- tol_dj <= dj && dj <= + tol_dj) continue; + break; + case GLP_NS: + /* xN[j] cannot change at all */ + continue; + default: + xassert(stat != stat); + } + /* xN[j] is eligible non-basic variable; choose one which has + largest weighted reduced cost */ +#ifdef GLP_DEBUG + xassert(gamma[j] > 0.0); +#endif + temp = (dj * dj) / gamma[j]; + if (best < temp) + q = j, best = temp; + } + /* store the index of non-basic variable xN[q] chosen */ + csa->q = q; + return; +} + +/*********************************************************************** +* eval_tcol - compute pivot column of the simplex table +* +* This routine computes the pivot column of the simplex table, which +* corresponds to non-basic variable xN[q] chosen. +* +* The pivot column is the following vector: +* +* tcol = T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], +* +* where B is the current basis matrix, N[q] is a column of the matrix +* (I|-A) corresponding to variable xN[q]. */ + +static void eval_tcol(struct csa *csa) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *head = csa->head; + int q = csa->q; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + double *h = csa->tcol_vec; + int i, k, nnz; +#ifdef GLP_DEBUG + xassert(1 <= q && q <= n); +#endif + k = head[m+q]; /* x[k] = xN[q] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + /* construct the right-hand side vector h = - N[q] */ + for (i = 1; i <= m; i++) + h[i] = 0.0; + if (k <= m) + { /* N[q] is k-th column of submatrix I */ + h[k] = -1.0; + } + else + { /* N[q] is (k-m)-th column of submatrix (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + h[A_ind[ptr]] = A_val[ptr]; + } + /* solve system B * tcol = h */ + xassert(csa->valid); + bfd_ftran(csa->bfd, tcol_vec); + /* construct sparse pattern of the pivot column */ + nnz = 0; + for (i = 1; i <= m; i++) + { if (tcol_vec[i] != 0.0) + tcol_ind[++nnz] = i; + } + csa->tcol_nnz = nnz; + return; +} + +/*********************************************************************** +* refine_tcol - refine pivot column of the simplex table +* +* This routine refines the pivot column of the simplex table assuming +* that it was previously computed by the routine eval_tcol. */ + +static void refine_tcol(struct csa *csa) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *head = csa->head; + int q = csa->q; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + double *h = csa->work3; + int i, k, nnz; +#ifdef GLP_DEBUG + xassert(1 <= q && q <= n); +#endif + k = head[m+q]; /* x[k] = xN[q] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + /* construct the right-hand side vector h = - N[q] */ + for (i = 1; i <= m; i++) + h[i] = 0.0; + if (k <= m) + { /* N[q] is k-th column of submatrix I */ + h[k] = -1.0; + } + else + { /* N[q] is (k-m)-th column of submatrix (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + h[A_ind[ptr]] = A_val[ptr]; + } + /* refine solution of B * tcol = h */ + refine_ftran(csa, h, tcol_vec); + /* construct sparse pattern of the pivot column */ + nnz = 0; + for (i = 1; i <= m; i++) + { if (tcol_vec[i] != 0.0) + tcol_ind[++nnz] = i; + } + csa->tcol_nnz = nnz; + return; +} + +/*********************************************************************** +* sort_tcol - sort pivot column of the simplex table +* +* This routine reorders the list of non-zero elements of the pivot +* column to put significant elements, whose magnitude is not less than +* a specified tolerance, in front of the list, and stores the number +* of significant elements in tcol_num. */ + +static void sort_tcol(struct csa *csa, double tol_piv) +{ +#ifdef GLP_DEBUG + int m = csa->m; +#endif + int nnz = csa->tcol_nnz; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + int i, num, pos; + double big, eps, temp; + /* compute infinity (maximum) norm of the column */ + big = 0.0; + for (pos = 1; pos <= nnz; pos++) + { +#ifdef GLP_DEBUG + i = tcol_ind[pos]; + xassert(1 <= i && i <= m); +#endif + temp = fabs(tcol_vec[tcol_ind[pos]]); + if (big < temp) big = temp; + } + csa->tcol_max = big; + /* determine absolute pivot tolerance */ + eps = tol_piv * (1.0 + 0.01 * big); + /* move significant column components to front of the list */ + for (num = 0; num < nnz; ) + { i = tcol_ind[nnz]; + if (fabs(tcol_vec[i]) < eps) + nnz--; + else + { num++; + tcol_ind[nnz] = tcol_ind[num]; + tcol_ind[num] = i; + } + } + csa->tcol_num = num; + return; +} + +/*********************************************************************** +* chuzr - choose basic variable (row of the simplex table) +* +* This routine chooses basic variable xB[p], which reaches its bound +* first on changing non-basic variable xN[q] in valid direction. +* +* The parameter rtol is a relative tolerance used to relax bounds of +* basic variables. If rtol = 0, the routine implements the standard +* ratio test. Otherwise, if rtol > 0, the routine implements Harris' +* two-pass ratio test. In the latter case rtol should be about three +* times less than a tolerance used to check primal feasibility. */ + +static void chuzr(struct csa *csa, double rtol) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + char *type = csa->type; + double *lb = csa->lb; + double *ub = csa->ub; + double *coef = csa->coef; + int *head = csa->head; + int phase = csa->phase; + double *bbar = csa->bbar; + double *cbar = csa->cbar; + int q = csa->q; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + int tcol_num = csa->tcol_num; + int i, i_stat, k, p, p_stat, pos; + double alfa, big, delta, s, t, teta, tmax; +#ifdef GLP_DEBUG + xassert(1 <= q && q <= n); +#endif + /* s := - sign(d[q]), where d[q] is reduced cost of xN[q] */ +#ifdef GLP_DEBUG + xassert(cbar[q] != 0.0); +#endif + s = (cbar[q] > 0.0 ? -1.0 : +1.0); + /*** FIRST PASS ***/ + k = head[m+q]; /* x[k] = xN[q] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (type[k] == GLP_DB) + { /* xN[q] has both lower and upper bounds */ + p = -1, p_stat = 0, teta = ub[k] - lb[k], big = 1.0; + } + else + { /* xN[q] has no opposite bound */ + p = 0, p_stat = 0, teta = DBL_MAX, big = 0.0; + } + /* walk through significant elements of the pivot column */ + for (pos = 1; pos <= tcol_num; pos++) + { i = tcol_ind[pos]; +#ifdef GLP_DEBUG + xassert(1 <= i && i <= m); +#endif + k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + alfa = s * tcol_vec[i]; +#ifdef GLP_DEBUG + xassert(alfa != 0.0); +#endif + /* xB[i] = ... + alfa * xN[q] + ..., and due to s we need to + consider the only case when xN[q] is increasing */ + if (alfa > 0.0) + { /* xB[i] is increasing */ + if (phase == 1 && coef[k] < 0.0) + { /* xB[i] violates its lower bound, which plays the role + of an upper bound on phase I */ + delta = rtol * (1.0 + kappa * fabs(lb[k])); + t = ((lb[k] + delta) - bbar[i]) / alfa; + i_stat = GLP_NL; + } + else if (phase == 1 && coef[k] > 0.0) + { /* xB[i] violates its upper bound, which plays the role + of an lower bound on phase I */ + continue; + } + else if (type[k] == GLP_UP || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* xB[i] is within its bounds and has an upper bound */ + delta = rtol * (1.0 + kappa * fabs(ub[k])); + t = ((ub[k] + delta) - bbar[i]) / alfa; + i_stat = GLP_NU; + } + else + { /* xB[i] is within its bounds and has no upper bound */ + continue; + } + } + else + { /* xB[i] is decreasing */ + if (phase == 1 && coef[k] > 0.0) + { /* xB[i] violates its upper bound, which plays the role + of an lower bound on phase I */ + delta = rtol * (1.0 + kappa * fabs(ub[k])); + t = ((ub[k] - delta) - bbar[i]) / alfa; + i_stat = GLP_NU; + } + else if (phase == 1 && coef[k] < 0.0) + { /* xB[i] violates its lower bound, which plays the role + of an upper bound on phase I */ + continue; + } + else if (type[k] == GLP_LO || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* xB[i] is within its bounds and has an lower bound */ + delta = rtol * (1.0 + kappa * fabs(lb[k])); + t = ((lb[k] - delta) - bbar[i]) / alfa; + i_stat = GLP_NL; + } + else + { /* xB[i] is within its bounds and has no lower bound */ + continue; + } + } + /* t is a change of xN[q], on which xB[i] reaches its bound + (possibly relaxed); since the basic solution is assumed to + be primal feasible (or pseudo feasible on phase I), t has + to be non-negative by definition; however, it may happen + that xB[i] slightly (i.e. within a tolerance) violates its + bound, that leads to negative t; in the latter case, if + xB[i] is chosen, negative t means that xN[q] changes in + wrong direction; if pivot alfa[i,q] is close to zero, even + small bound violation of xB[i] may lead to a large change + of xN[q] in wrong direction; let, for example, xB[i] >= 0 + and in the current basis its value be -5e-9; let also xN[q] + be on its zero bound and should increase; from the ratio + test rule it follows that the pivot alfa[i,q] < 0; however, + if alfa[i,q] is, say, -1e-9, the change of xN[q] in wrong + direction is 5e-9 / (-1e-9) = -5, and using it for updating + values of other basic variables will give absolutely wrong + results; therefore, if t is negative, we should replace it + by exact zero assuming that xB[i] is exactly on its bound, + and the violation appears due to round-off errors */ + if (t < 0.0) t = 0.0; + /* apply minimal ratio test */ + if (teta > t || teta == t && big < fabs(alfa)) + p = i, p_stat = i_stat, teta = t, big = fabs(alfa); + } + /* the second pass is skipped in the following cases: */ + /* if the standard ratio test is used */ + if (rtol == 0.0) goto done; + /* if xN[q] reaches its opposite bound or if no basic variable + has been chosen on the first pass */ + if (p <= 0) goto done; + /* if xB[p] is a blocking variable, i.e. if it prevents xN[q] + from any change */ + if (teta == 0.0) goto done; + /*** SECOND PASS ***/ + /* here tmax is a maximal change of xN[q], on which the solution + remains primal feasible (or pseudo feasible on phase I) within + a tolerance */ +#if 0 + tmax = (1.0 + 10.0 * DBL_EPSILON) * teta; +#else + tmax = teta; +#endif + /* nothing is chosen so far */ + p = 0, p_stat = 0, teta = DBL_MAX, big = 0.0; + /* walk through significant elements of the pivot column */ + for (pos = 1; pos <= tcol_num; pos++) + { i = tcol_ind[pos]; +#ifdef GLP_DEBUG + xassert(1 <= i && i <= m); +#endif + k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + alfa = s * tcol_vec[i]; +#ifdef GLP_DEBUG + xassert(alfa != 0.0); +#endif + /* xB[i] = ... + alfa * xN[q] + ..., and due to s we need to + consider the only case when xN[q] is increasing */ + if (alfa > 0.0) + { /* xB[i] is increasing */ + if (phase == 1 && coef[k] < 0.0) + { /* xB[i] violates its lower bound, which plays the role + of an upper bound on phase I */ + t = (lb[k] - bbar[i]) / alfa; + i_stat = GLP_NL; + } + else if (phase == 1 && coef[k] > 0.0) + { /* xB[i] violates its upper bound, which plays the role + of an lower bound on phase I */ + continue; + } + else if (type[k] == GLP_UP || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* xB[i] is within its bounds and has an upper bound */ + t = (ub[k] - bbar[i]) / alfa; + i_stat = GLP_NU; + } + else + { /* xB[i] is within its bounds and has no upper bound */ + continue; + } + } + else + { /* xB[i] is decreasing */ + if (phase == 1 && coef[k] > 0.0) + { /* xB[i] violates its upper bound, which plays the role + of an lower bound on phase I */ + t = (ub[k] - bbar[i]) / alfa; + i_stat = GLP_NU; + } + else if (phase == 1 && coef[k] < 0.0) + { /* xB[i] violates its lower bound, which plays the role + of an upper bound on phase I */ + continue; + } + else if (type[k] == GLP_LO || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* xB[i] is within its bounds and has an lower bound */ + t = (lb[k] - bbar[i]) / alfa; + i_stat = GLP_NL; + } + else + { /* xB[i] is within its bounds and has no lower bound */ + continue; + } + } + /* (see comments for the first pass) */ + if (t < 0.0) t = 0.0; + /* t is a change of xN[q], on which xB[i] reaches its bound; + if t <= tmax, all basic variables can violate their bounds + only within relaxation tolerance delta; we can use this + freedom and choose basic variable having largest influence + coefficient to avoid possible numeric instability */ + if (t <= tmax && big < fabs(alfa)) + p = i, p_stat = i_stat, teta = t, big = fabs(alfa); + } + /* something must be chosen on the second pass */ + xassert(p != 0); +done: /* store the index and status of basic variable xB[p] chosen */ + csa->p = p; + if (p > 0 && type[head[p]] == GLP_FX) + csa->p_stat = GLP_NS; + else + csa->p_stat = p_stat; + /* store corresponding change of non-basic variable xN[q] */ +#ifdef GLP_DEBUG + xassert(teta >= 0.0); +#endif + csa->teta = s * teta; + return; +} + +/*********************************************************************** +* eval_rho - compute pivot row of the inverse +* +* This routine computes the pivot (p-th) row of the inverse inv(B), +* which corresponds to basic variable xB[p] chosen: +* +* rho = inv(B') * e[p], +* +* where B' is a matrix transposed to the current basis matrix, e[p] +* is unity vector. */ + +static void eval_rho(struct csa *csa, double rho[]) +{ int m = csa->m; + int p = csa->p; + double *e = rho; + int i; +#ifdef GLP_DEBUG + xassert(1 <= p && p <= m); +#endif + /* construct the right-hand side vector e[p] */ + for (i = 1; i <= m; i++) + e[i] = 0.0; + e[p] = 1.0; + /* solve system B'* rho = e[p] */ + xassert(csa->valid); + bfd_btran(csa->bfd, rho); + return; +} + +/*********************************************************************** +* refine_rho - refine pivot row of the inverse +* +* This routine refines the pivot row of the inverse inv(B) assuming +* that it was previously computed by the routine eval_rho. */ + +static void refine_rho(struct csa *csa, double rho[]) +{ int m = csa->m; + int p = csa->p; + double *e = csa->work3; + int i; +#ifdef GLP_DEBUG + xassert(1 <= p && p <= m); +#endif + /* construct the right-hand side vector e[p] */ + for (i = 1; i <= m; i++) + e[i] = 0.0; + e[p] = 1.0; + /* refine solution of B'* rho = e[p] */ + refine_btran(csa, e, rho); + return; +} + +/*********************************************************************** +* eval_trow - compute pivot row of the simplex table +* +* This routine computes the pivot row of the simplex table, which +* corresponds to basic variable xB[p] chosen. +* +* The pivot row is the following vector: +* +* trow = T'* e[p] = - N'* inv(B') * e[p] = - N' * rho, +* +* where rho is the pivot row of the inverse inv(B) previously computed +* by the routine eval_rho. +* +* Note that elements of the pivot row corresponding to fixed non-basic +* variables are not computed. */ + +static void eval_trow(struct csa *csa, double rho[]) +{ int m = csa->m; + int n = csa->n; +#ifdef GLP_DEBUG + char *stat = csa->stat; +#endif + int *N_ptr = csa->N_ptr; + int *N_len = csa->N_len; + int *N_ind = csa->N_ind; + double *N_val = csa->N_val; + int *trow_ind = csa->trow_ind; + double *trow_vec = csa->trow_vec; + int i, j, beg, end, ptr, nnz; + double temp; + /* clear the pivot row */ + for (j = 1; j <= n; j++) + trow_vec[j] = 0.0; + /* compute the pivot row as a linear combination of rows of the + matrix N: trow = - rho[1] * N'[1] - ... - rho[m] * N'[m] */ + for (i = 1; i <= m; i++) + { temp = rho[i]; + if (temp == 0.0) continue; + /* trow := trow - rho[i] * N'[i] */ + beg = N_ptr[i]; + end = beg + N_len[i]; + for (ptr = beg; ptr < end; ptr++) + { +#ifdef GLP_DEBUG + j = N_ind[ptr]; + xassert(1 <= j && j <= n); + xassert(stat[j] != GLP_NS); +#endif + trow_vec[N_ind[ptr]] -= temp * N_val[ptr]; + } + } + /* construct sparse pattern of the pivot row */ + nnz = 0; + for (j = 1; j <= n; j++) + { if (trow_vec[j] != 0.0) + trow_ind[++nnz] = j; + } + csa->trow_nnz = nnz; + return; +} + +/*********************************************************************** +* update_bbar - update values of basic variables +* +* This routine updates values of all basic variables for the adjacent +* basis. */ + +static void update_bbar(struct csa *csa) +{ +#ifdef GLP_DEBUG + int m = csa->m; + int n = csa->n; +#endif + double *bbar = csa->bbar; + int q = csa->q; + int tcol_nnz = csa->tcol_nnz; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + int p = csa->p; + double teta = csa->teta; + int i, pos; +#ifdef GLP_DEBUG + xassert(1 <= q && q <= n); + xassert(p < 0 || 1 <= p && p <= m); +#endif + /* if xN[q] leaves the basis, compute its value in the adjacent + basis, where it will replace xB[p] */ + if (p > 0) + bbar[p] = get_xN(csa, q) + teta; + /* update values of other basic variables (except xB[p], because + it will be replaced by xN[q]) */ + if (teta == 0.0) goto done; + for (pos = 1; pos <= tcol_nnz; pos++) + { i = tcol_ind[pos]; + /* skip xB[p] */ + if (i == p) continue; + /* (change of xB[i]) = alfa[i,q] * (change of xN[q]) */ + bbar[i] += tcol_vec[i] * teta; + } +done: return; +} + +/*********************************************************************** +* reeval_cost - recompute reduced cost of non-basic variable xN[q] +* +* This routine recomputes reduced cost of non-basic variable xN[q] for +* the current basis more accurately using its direct definition: +* +* d[q] = cN[q] - N'[q] * pi = +* +* = cN[q] - N'[q] * (inv(B') * cB) = +* +* = cN[q] - (cB' * inv(B) * N[q]) = +* +* = cN[q] + cB' * (pivot column). +* +* It is assumed that the pivot column of the simplex table is already +* computed. */ + +static double reeval_cost(struct csa *csa) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + double *coef = csa->coef; + int *head = csa->head; + int q = csa->q; + int tcol_nnz = csa->tcol_nnz; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + int i, pos; + double dq; +#ifdef GLP_DEBUG + xassert(1 <= q && q <= n); +#endif + dq = coef[head[m+q]]; + for (pos = 1; pos <= tcol_nnz; pos++) + { i = tcol_ind[pos]; +#ifdef GLP_DEBUG + xassert(1 <= i && i <= m); +#endif + dq += coef[head[i]] * tcol_vec[i]; + } + return dq; +} + +/*********************************************************************** +* update_cbar - update reduced costs of non-basic variables +* +* This routine updates reduced costs of all (except fixed) non-basic +* variables for the adjacent basis. */ + +static void update_cbar(struct csa *csa) +{ +#ifdef GLP_DEBUG + int n = csa->n; +#endif + double *cbar = csa->cbar; + int q = csa->q; + int trow_nnz = csa->trow_nnz; + int *trow_ind = csa->trow_ind; + double *trow_vec = csa->trow_vec; + int j, pos; + double new_dq; +#ifdef GLP_DEBUG + xassert(1 <= q && q <= n); +#endif + /* compute reduced cost of xB[p] in the adjacent basis, where it + will replace xN[q] */ +#ifdef GLP_DEBUG + xassert(trow_vec[q] != 0.0); +#endif + new_dq = (cbar[q] /= trow_vec[q]); + /* update reduced costs of other non-basic variables (except + xN[q], because it will be replaced by xB[p]) */ + for (pos = 1; pos <= trow_nnz; pos++) + { j = trow_ind[pos]; + /* skip xN[q] */ + if (j == q) continue; + cbar[j] -= trow_vec[j] * new_dq; + } + return; +} + +/*********************************************************************** +* update_gamma - update steepest edge coefficients +* +* This routine updates steepest-edge coefficients for the adjacent +* basis. */ + +static void update_gamma(struct csa *csa) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + char *type = csa->type; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + char *refsp = csa->refsp; + double *gamma = csa->gamma; + int q = csa->q; + int tcol_nnz = csa->tcol_nnz; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + int p = csa->p; + int trow_nnz = csa->trow_nnz; + int *trow_ind = csa->trow_ind; + double *trow_vec = csa->trow_vec; + double *u = csa->work3; + int i, j, k, pos, beg, end, ptr; + double gamma_q, delta_q, pivot, s, t, t1, t2; +#ifdef GLP_DEBUG + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); +#endif + /* the basis changes, so decrease the count */ + xassert(csa->refct > 0); + csa->refct--; + /* recompute gamma[q] for the current basis more accurately and + compute auxiliary vector u */ + gamma_q = delta_q = (refsp[head[m+q]] ? 1.0 : 0.0); + for (i = 1; i <= m; i++) u[i] = 0.0; + for (pos = 1; pos <= tcol_nnz; pos++) + { i = tcol_ind[pos]; + if (refsp[head[i]]) + { u[i] = t = tcol_vec[i]; + gamma_q += t * t; + } + else + u[i] = 0.0; + } + xassert(csa->valid); + bfd_btran(csa->bfd, u); + /* update gamma[k] for other non-basic variables (except fixed + variables and xN[q], because it will be replaced by xB[p]) */ + pivot = trow_vec[q]; +#ifdef GLP_DEBUG + xassert(pivot != 0.0); +#endif + for (pos = 1; pos <= trow_nnz; pos++) + { j = trow_ind[pos]; + /* skip xN[q] */ + if (j == q) continue; + /* compute t */ + t = trow_vec[j] / pivot; + /* compute inner product s = N'[j] * u */ + k = head[m+j]; /* x[k] = xN[j] */ + if (k <= m) + s = u[k]; + else + { s = 0.0; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + s -= A_val[ptr] * u[A_ind[ptr]]; + } + /* compute gamma[k] for the adjacent basis */ + t1 = gamma[j] + t * t * gamma_q + 2.0 * t * s; + t2 = (refsp[k] ? 1.0 : 0.0) + delta_q * t * t; + gamma[j] = (t1 >= t2 ? t1 : t2); + if (gamma[j] < DBL_EPSILON) gamma[j] = DBL_EPSILON; + } + /* compute gamma[q] for the adjacent basis */ + if (type[head[p]] == GLP_FX) + gamma[q] = 1.0; + else + { gamma[q] = gamma_q / (pivot * pivot); + if (gamma[q] < DBL_EPSILON) gamma[q] = DBL_EPSILON; + } + return; +} + +/*********************************************************************** +* err_in_bbar - compute maximal relative error in primal solution +* +* This routine returns maximal relative error: +* +* max |beta[i] - bbar[i]| / (1 + |beta[i]|), +* +* where beta and bbar are, respectively, directly computed and the +* current (updated) values of basic variables. +* +* NOTE: The routine is intended only for debugginig purposes. */ + +static double err_in_bbar(struct csa *csa) +{ int m = csa->m; + double *bbar = csa->bbar; + int i; + double e, emax, *beta; + beta = xcalloc(1+m, sizeof(double)); + eval_beta(csa, beta); + emax = 0.0; + for (i = 1; i <= m; i++) + { e = fabs(beta[i] - bbar[i]) / (1.0 + fabs(beta[i])); + if (emax < e) emax = e; + } + xfree(beta); + return emax; +} + +/*********************************************************************** +* err_in_cbar - compute maximal relative error in dual solution +* +* This routine returns maximal relative error: +* +* max |cost[j] - cbar[j]| / (1 + |cost[j]|), +* +* where cost and cbar are, respectively, directly computed and the +* current (updated) reduced costs of non-basic non-fixed variables. +* +* NOTE: The routine is intended only for debugginig purposes. */ + +static double err_in_cbar(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + char *stat = csa->stat; + double *cbar = csa->cbar; + int j; + double e, emax, cost, *pi; + pi = xcalloc(1+m, sizeof(double)); + eval_pi(csa, pi); + emax = 0.0; + for (j = 1; j <= n; j++) + { if (stat[j] == GLP_NS) continue; + cost = eval_cost(csa, pi, j); + e = fabs(cost - cbar[j]) / (1.0 + fabs(cost)); + if (emax < e) emax = e; + } + xfree(pi); + return emax; +} + +/*********************************************************************** +* err_in_gamma - compute maximal relative error in steepest edge cff. +* +* This routine returns maximal relative error: +* +* max |gamma'[j] - gamma[j]| / (1 + |gamma'[j]), +* +* where gamma'[j] and gamma[j] are, respectively, directly computed +* and the current (updated) steepest edge coefficients for non-basic +* non-fixed variable x[j]. +* +* NOTE: The routine is intended only for debugginig purposes. */ + +static double err_in_gamma(struct csa *csa) +{ int n = csa->n; + char *stat = csa->stat; + double *gamma = csa->gamma; + int j; + double e, emax, temp; + emax = 0.0; + for (j = 1; j <= n; j++) + { if (stat[j] == GLP_NS) + { xassert(gamma[j] == 1.0); + continue; + } + temp = eval_gamma(csa, j); + e = fabs(temp - gamma[j]) / (1.0 + fabs(temp)); + if (emax < e) emax = e; + } + return emax; +} + +/*********************************************************************** +* change_basis - change basis header +* +* This routine changes the basis header to make it corresponding to +* the adjacent basis. */ + +static void change_basis(struct csa *csa) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; + char *type = csa->type; +#endif + int *head = csa->head; + char *stat = csa->stat; + int q = csa->q; + int p = csa->p; + int p_stat = csa->p_stat; + int k; +#ifdef GLP_DEBUG + xassert(1 <= q && q <= n); +#endif + if (p < 0) + { /* xN[q] goes to its opposite bound */ +#ifdef GLP_DEBUG + k = head[m+q]; /* x[k] = xN[q] */ + xassert(1 <= k && k <= m+n); + xassert(type[k] == GLP_DB); +#endif + switch (stat[q]) + { case GLP_NL: + /* xN[q] increases */ + stat[q] = GLP_NU; + break; + case GLP_NU: + /* xN[q] decreases */ + stat[q] = GLP_NL; + break; + default: + xassert(stat != stat); + } + } + else + { /* xB[p] leaves the basis, xN[q] enters the basis */ +#ifdef GLP_DEBUG + xassert(1 <= p && p <= m); + k = head[p]; /* x[k] = xB[p] */ + switch (p_stat) + { case GLP_NL: + /* xB[p] goes to its lower bound */ + xassert(type[k] == GLP_LO || type[k] == GLP_DB); + break; + case GLP_NU: + /* xB[p] goes to its upper bound */ + xassert(type[k] == GLP_UP || type[k] == GLP_DB); + break; + case GLP_NS: + /* xB[p] goes to its fixed value */ + xassert(type[k] == GLP_NS); + break; + default: + xassert(p_stat != p_stat); + } +#endif + /* xB[p] <-> xN[q] */ + k = head[p], head[p] = head[m+q], head[m+q] = k; + stat[q] = (char)p_stat; + } + return; +} + +/*********************************************************************** +* set_aux_obj - construct auxiliary objective function +* +* The auxiliary objective function is a separable piecewise linear +* convex function, which is the sum of primal infeasibilities: +* +* z = t[1] + ... + t[m+n] -> minimize, +* +* where: +* +* / lb[k] - x[k], if x[k] < lb[k] +* | +* t[k] = < 0, if lb[k] <= x[k] <= ub[k] +* | +* \ x[k] - ub[k], if x[k] > ub[k] +* +* This routine computes objective coefficients for the current basis +* and returns the number of non-zero terms t[k]. */ + +static int set_aux_obj(struct csa *csa, double tol_bnd) +{ int m = csa->m; + int n = csa->n; + char *type = csa->type; + double *lb = csa->lb; + double *ub = csa->ub; + double *coef = csa->coef; + int *head = csa->head; + double *bbar = csa->bbar; + int i, k, cnt = 0; + double eps; + /* use a bit more restrictive tolerance */ + tol_bnd *= 0.90; + /* clear all objective coefficients */ + for (k = 1; k <= m+n; k++) + coef[k] = 0.0; + /* walk through the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + if (type[k] == GLP_LO || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* x[k] has lower bound */ + eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); + if (bbar[i] < lb[k] - eps) + { /* and violates it */ + coef[k] = -1.0; + cnt++; + } + } + if (type[k] == GLP_UP || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* x[k] has upper bound */ + eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); + if (bbar[i] > ub[k] + eps) + { /* and violates it */ + coef[k] = +1.0; + cnt++; + } + } + } + return cnt; +} + +/*********************************************************************** +* set_orig_obj - restore original objective function +* +* This routine assigns scaled original objective coefficients to the +* working objective function. */ + +static void set_orig_obj(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + double *coef = csa->coef; + double *obj = csa->obj; + double zeta = csa->zeta; + int i, j; + for (i = 1; i <= m; i++) + coef[i] = 0.0; + for (j = 1; j <= n; j++) + coef[m+j] = zeta * obj[j]; + return; +} + +/*********************************************************************** +* check_stab - check numerical stability of basic solution +* +* If the current basic solution is primal feasible (or pseudo feasible +* on phase I) within a tolerance, this routine returns zero, otherwise +* it returns non-zero. */ + +static int check_stab(struct csa *csa, double tol_bnd) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + char *type = csa->type; + double *lb = csa->lb; + double *ub = csa->ub; + double *coef = csa->coef; + int *head = csa->head; + int phase = csa->phase; + double *bbar = csa->bbar; + int i, k; + double eps; + /* walk through the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (phase == 1 && coef[k] < 0.0) + { /* x[k] must not be greater than its lower bound */ +#ifdef GLP_DEBUG + xassert(type[k] == GLP_LO || type[k] == GLP_DB || + type[k] == GLP_FX); +#endif + eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); + if (bbar[i] > lb[k] + eps) return 1; + } + else if (phase == 1 && coef[k] > 0.0) + { /* x[k] must not be less than its upper bound */ +#ifdef GLP_DEBUG + xassert(type[k] == GLP_UP || type[k] == GLP_DB || + type[k] == GLP_FX); +#endif + eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); + if (bbar[i] < ub[k] - eps) return 1; + } + else + { /* either phase = 1 and coef[k] = 0, or phase = 2 */ + if (type[k] == GLP_LO || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* x[k] must not be less than its lower bound */ + eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); + if (bbar[i] < lb[k] - eps) return 1; + } + if (type[k] == GLP_UP || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* x[k] must not be greater then its upper bound */ + eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); + if (bbar[i] > ub[k] + eps) return 1; + } + } + } + /* basic solution is primal feasible within a tolerance */ + return 0; +} + +/*********************************************************************** +* check_feas - check primal feasibility of basic solution +* +* If the current basic solution is primal feasible within a tolerance, +* this routine returns zero, otherwise it returns non-zero. */ + +static int check_feas(struct csa *csa, double tol_bnd) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; + char *type = csa->type; +#endif + double *lb = csa->lb; + double *ub = csa->ub; + double *coef = csa->coef; + int *head = csa->head; + double *bbar = csa->bbar; + int i, k; + double eps; + xassert(csa->phase == 1); + /* walk through the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (coef[k] < 0.0) + { /* check if x[k] still violates its lower bound */ +#ifdef GLP_DEBUG + xassert(type[k] == GLP_LO || type[k] == GLP_DB || + type[k] == GLP_FX); +#endif + eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); + if (bbar[i] < lb[k] - eps) return 1; + } + else if (coef[k] > 0.0) + { /* check if x[k] still violates its upper bound */ +#ifdef GLP_DEBUG + xassert(type[k] == GLP_UP || type[k] == GLP_DB || + type[k] == GLP_FX); +#endif + eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); + if (bbar[i] > ub[k] + eps) return 1; + } + } + /* basic solution is primal feasible within a tolerance */ + return 0; +} + +/*********************************************************************** +* eval_obj - compute original objective function +* +* This routine computes the current value of the original objective +* function. */ + +static double eval_obj(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + double *obj = csa->obj; + int *head = csa->head; + double *bbar = csa->bbar; + int i, j, k; + double sum; + sum = obj[0]; + /* walk through the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k > m) + sum += obj[k-m] * bbar[i]; + } + /* walk through the list of non-basic variables */ + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k > m) + sum += obj[k-m] * get_xN(csa, j); + } + return sum; +} + +/*********************************************************************** +* display - display the search progress +* +* This routine displays some information about the search progress +* that includes: +* +* the search phase; +* +* the number of simplex iterations performed by the solver; +* +* the original objective value; +* +* the sum of (scaled) primal infeasibilities; +* +* the number of basic fixed variables. */ + +static void display(struct csa *csa, const glp_smcp *parm, int spec) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + char *type = csa->type; + double *lb = csa->lb; + double *ub = csa->ub; + int phase = csa->phase; + int *head = csa->head; + double *bbar = csa->bbar; + int i, k, cnt; + double sum; + if (parm->msg_lev < GLP_MSG_ON) goto skip; + if (parm->out_dly > 0 && + 1000.0 * xdifftime(xtime(), csa->tm_beg) < parm->out_dly) + goto skip; + if (csa->it_cnt == csa->it_dpy) goto skip; + if (!spec && csa->it_cnt % parm->out_frq != 0) goto skip; + /* compute the sum of primal infeasibilities and determine the + number of basic fixed variables */ + sum = 0.0, cnt = 0; + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (type[k] == GLP_LO || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* x[k] has lower bound */ + if (bbar[i] < lb[k]) + sum += (lb[k] - bbar[i]); + } + if (type[k] == GLP_UP || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* x[k] has upper bound */ + if (bbar[i] > ub[k]) + sum += (bbar[i] - ub[k]); + } + if (type[k] == GLP_FX) cnt++; + } + xprintf("%c%6d: obj = %17.9e infeas = %10.3e (%d)\n", + phase == 1 ? ' ' : '*', csa->it_cnt, eval_obj(csa), sum, cnt); + csa->it_dpy = csa->it_cnt; +skip: return; +} + +/*********************************************************************** +* store_sol - store basic solution back to the problem object +* +* This routine stores basic solution components back to the problem +* object. */ + +static void store_sol(struct csa *csa, glp_prob *lp, int p_stat, + int d_stat, int ray) +{ int m = csa->m; + int n = csa->n; + double zeta = csa->zeta; + int *head = csa->head; + char *stat = csa->stat; + double *bbar = csa->bbar; + double *cbar = csa->cbar; + int i, j, k; +#ifdef GLP_DEBUG + xassert(lp->m == m); + xassert(lp->n == n); +#endif + /* basis factorization */ +#ifdef GLP_DEBUG + xassert(!lp->valid && lp->bfd == NULL); + xassert(csa->valid && csa->bfd != NULL); +#endif + lp->valid = 1, csa->valid = 0; + lp->bfd = csa->bfd, csa->bfd = NULL; + memcpy(&lp->head[1], &head[1], m * sizeof(int)); + /* basic solution status */ + lp->pbs_stat = p_stat; + lp->dbs_stat = d_stat; + /* objective function value */ + lp->obj_val = eval_obj(csa); + /* simplex iteration count */ + lp->it_cnt = csa->it_cnt; + /* unbounded ray */ + lp->some = ray; + /* basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { GLPROW *row = lp->row[k]; + row->stat = GLP_BS; + row->bind = i; + row->prim = bbar[i] / row->rii; + row->dual = 0.0; + } + else + { GLPCOL *col = lp->col[k-m]; + col->stat = GLP_BS; + col->bind = i; + col->prim = bbar[i] * col->sjj; + col->dual = 0.0; + } + } + /* non-basic variables */ + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { GLPROW *row = lp->row[k]; + row->stat = stat[j]; + row->bind = 0; +#if 0 + row->prim = get_xN(csa, j) / row->rii; +#else + switch (stat[j]) + { case GLP_NL: + row->prim = row->lb; break; + case GLP_NU: + row->prim = row->ub; break; + case GLP_NF: + row->prim = 0.0; break; + case GLP_NS: + row->prim = row->lb; break; + default: + xassert(stat != stat); + } +#endif + row->dual = (cbar[j] * row->rii) / zeta; + } + else + { GLPCOL *col = lp->col[k-m]; + col->stat = stat[j]; + col->bind = 0; +#if 0 + col->prim = get_xN(csa, j) * col->sjj; +#else + switch (stat[j]) + { case GLP_NL: + col->prim = col->lb; break; + case GLP_NU: + col->prim = col->ub; break; + case GLP_NF: + col->prim = 0.0; break; + case GLP_NS: + col->prim = col->lb; break; + default: + xassert(stat != stat); + } +#endif + col->dual = (cbar[j] / col->sjj) / zeta; + } + } + return; +} + +/*********************************************************************** +* free_csa - deallocate common storage area +* +* This routine frees all the memory allocated to arrays in the common +* storage area (CSA). */ + +static void free_csa(struct csa *csa) +{ xfree(csa->type); + xfree(csa->lb); + xfree(csa->ub); + xfree(csa->coef); + xfree(csa->obj); + xfree(csa->A_ptr); + xfree(csa->A_ind); + xfree(csa->A_val); + xfree(csa->head); + xfree(csa->stat); + xfree(csa->N_ptr); + xfree(csa->N_len); + xfree(csa->N_ind); + xfree(csa->N_val); + xfree(csa->bbar); + xfree(csa->cbar); + xfree(csa->refsp); + xfree(csa->gamma); + xfree(csa->tcol_ind); + xfree(csa->tcol_vec); + xfree(csa->trow_ind); + xfree(csa->trow_vec); + xfree(csa->work1); + xfree(csa->work2); + xfree(csa->work3); + xfree(csa->work4); + xfree(csa); + return; +} + +/*********************************************************************** +* spx_primal - core LP solver based on the primal simplex method +* +* SYNOPSIS +* +* #include "glpspx.h" +* int spx_primal(glp_prob *lp, const glp_smcp *parm); +* +* DESCRIPTION +* +* The routine spx_primal is a core LP solver based on the two-phase +* primal simplex method. +* +* RETURNS +* +* 0 LP instance has been successfully solved. +* +* GLP_EITLIM +* Iteration limit has been exhausted. +* +* GLP_ETMLIM +* Time limit has been exhausted. +* +* GLP_EFAIL +* The solver failed to solve LP instance. */ + +int spx_primal(glp_prob *lp, const glp_smcp *parm) +{ struct csa *csa; + int binv_st = 2; + /* status of basis matrix factorization: + 0 - invalid; 1 - just computed; 2 - updated */ + int bbar_st = 0; + /* status of primal values of basic variables: + 0 - invalid; 1 - just computed; 2 - updated */ + int cbar_st = 0; + /* status of reduced costs of non-basic variables: + 0 - invalid; 1 - just computed; 2 - updated */ + int rigorous = 0; + /* rigorous mode flag; this flag is used to enable iterative + refinement on computing pivot rows and columns of the simplex + table */ + int check = 0; + int p_stat, d_stat, ret; + /* allocate and initialize the common storage area */ + csa = alloc_csa(lp); + init_csa(csa, lp); + if (parm->msg_lev >= GLP_MSG_DBG) + xprintf("Objective scale factor = %g\n", csa->zeta); +loop: /* main loop starts here */ + /* compute factorization of the basis matrix */ + if (binv_st == 0) + { ret = invert_B(csa); + if (ret != 0) + { if (parm->msg_lev >= GLP_MSG_ERR) + { xprintf("Error: unable to factorize the basis matrix (%d" + ")\n", ret); + xprintf("Sorry, basis recovery procedure not implemented" + " yet\n"); + } + xassert(!lp->valid && lp->bfd == NULL); + lp->bfd = csa->bfd, csa->bfd = NULL; + lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; + lp->obj_val = 0.0; + lp->it_cnt = csa->it_cnt; + lp->some = 0; + ret = GLP_EFAIL; + goto done; + } + csa->valid = 1; + binv_st = 1; /* just computed */ + /* invalidate basic solution components */ + bbar_st = cbar_st = 0; + } + /* compute primal values of basic variables */ + if (bbar_st == 0) + { eval_bbar(csa); + bbar_st = 1; /* just computed */ + /* determine the search phase, if not determined yet */ + if (csa->phase == 0) + { if (set_aux_obj(csa, parm->tol_bnd) > 0) + { /* current basic solution is primal infeasible */ + /* start to minimize the sum of infeasibilities */ + csa->phase = 1; + } + else + { /* current basic solution is primal feasible */ + /* start to minimize the original objective function */ + set_orig_obj(csa); + csa->phase = 2; + } + xassert(check_stab(csa, parm->tol_bnd) == 0); + /* working objective coefficients have been changed, so + invalidate reduced costs */ + cbar_st = 0; + display(csa, parm, 1); + } + /* make sure that the current basic solution remains primal + feasible (or pseudo feasible on phase I) */ + if (check_stab(csa, parm->tol_bnd)) + { /* there are excessive bound violations due to round-off + errors */ + if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: numerical instability (primal simplex," + " phase %s)\n", csa->phase == 1 ? "I" : "II"); + /* restart the search */ + csa->phase = 0; + binv_st = 0; + rigorous = 5; + goto loop; + } + } + xassert(csa->phase == 1 || csa->phase == 2); + /* on phase I we do not need to wait until the current basic + solution becomes dual feasible; it is sufficient to make sure + that no basic variable violates its bounds */ + if (csa->phase == 1 && !check_feas(csa, parm->tol_bnd)) + { /* the current basis is primal feasible; switch to phase II */ + csa->phase = 2; + set_orig_obj(csa); + cbar_st = 0; + display(csa, parm, 1); + } + /* compute reduced costs of non-basic variables */ + if (cbar_st == 0) + { eval_cbar(csa); + cbar_st = 1; /* just computed */ + } + /* redefine the reference space, if required */ + switch (parm->pricing) + { case GLP_PT_STD: + break; + case GLP_PT_PSE: + if (csa->refct == 0) reset_refsp(csa); + break; + default: + xassert(parm != parm); + } + /* at this point the basis factorization and all basic solution + components are valid */ + xassert(binv_st && bbar_st && cbar_st); + /* check accuracy of current basic solution components (only for + debugging) */ + if (check) + { double e_bbar = err_in_bbar(csa); + double e_cbar = err_in_cbar(csa); + double e_gamma = + (parm->pricing == GLP_PT_PSE ? err_in_gamma(csa) : 0.0); + xprintf("e_bbar = %10.3e; e_cbar = %10.3e; e_gamma = %10.3e\n", + e_bbar, e_cbar, e_gamma); + xassert(e_bbar <= 1e-5 && e_cbar <= 1e-5 && e_gamma <= 1e-3); + } + /* check if the iteration limit has been exhausted */ + if (parm->it_lim < INT_MAX && + csa->it_cnt - csa->it_beg >= parm->it_lim) + { if (bbar_st != 1 || csa->phase == 2 && cbar_st != 1) + { if (bbar_st != 1) bbar_st = 0; + if (csa->phase == 2 && cbar_st != 1) cbar_st = 0; + goto loop; + } + display(csa, parm, 1); + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); + switch (csa->phase) + { case 1: + p_stat = GLP_INFEAS; + set_orig_obj(csa); + eval_cbar(csa); + break; + case 2: + p_stat = GLP_FEAS; + break; + default: + xassert(csa != csa); + } + chuzc(csa, parm->tol_dj); + d_stat = (csa->q == 0 ? GLP_FEAS : GLP_INFEAS); + store_sol(csa, lp, p_stat, d_stat, 0); + ret = GLP_EITLIM; + goto done; + } + /* check if the time limit has been exhausted */ + if (parm->tm_lim < INT_MAX && + 1000.0 * xdifftime(xtime(), csa->tm_beg) >= parm->tm_lim) + { if (bbar_st != 1 || csa->phase == 2 && cbar_st != 1) + { if (bbar_st != 1) bbar_st = 0; + if (csa->phase == 2 && cbar_st != 1) cbar_st = 0; + goto loop; + } + display(csa, parm, 1); + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + switch (csa->phase) + { case 1: + p_stat = GLP_INFEAS; + set_orig_obj(csa); + eval_cbar(csa); + break; + case 2: + p_stat = GLP_FEAS; + break; + default: + xassert(csa != csa); + } + chuzc(csa, parm->tol_dj); + d_stat = (csa->q == 0 ? GLP_FEAS : GLP_INFEAS); + store_sol(csa, lp, p_stat, d_stat, 0); + ret = GLP_ETMLIM; + goto done; + } + /* display the search progress */ + display(csa, parm, 0); + /* choose non-basic variable xN[q] */ + chuzc(csa, parm->tol_dj); + if (csa->q == 0) + { if (bbar_st != 1 || cbar_st != 1) + { if (bbar_st != 1) bbar_st = 0; + if (cbar_st != 1) cbar_st = 0; + goto loop; + } + display(csa, parm, 1); + switch (csa->phase) + { case 1: + if (parm->msg_lev >= GLP_MSG_ALL) +#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ + xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); +#else + xprintf("LP HAS NO PRIMAL FEASIBLE SOLUTION\n"); +#endif + p_stat = GLP_NOFEAS; + set_orig_obj(csa); + eval_cbar(csa); + chuzc(csa, parm->tol_dj); + d_stat = (csa->q == 0 ? GLP_FEAS : GLP_INFEAS); + break; + case 2: + if (parm->msg_lev >= GLP_MSG_ALL) +#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ + xprintf("OPTIMAL SOLUTION FOUND\n"); +#else + xprintf("OPTIMAL LP SOLUTION FOUND\n"); +#endif + p_stat = d_stat = GLP_FEAS; + break; + default: + xassert(csa != csa); + } + store_sol(csa, lp, p_stat, d_stat, 0); + ret = 0; + goto done; + } + /* compute pivot column of the simplex table */ + eval_tcol(csa); + if (rigorous) refine_tcol(csa); + sort_tcol(csa, parm->tol_piv); + /* check accuracy of the reduced cost of xN[q] */ + { double d1 = csa->cbar[csa->q]; /* less accurate */ + double d2 = reeval_cost(csa); /* more accurate */ + xassert(d1 != 0.0); + if (fabs(d1 - d2) > 1e-5 * (1.0 + fabs(d2)) || + !(d1 < 0.0 && d2 < 0.0 || d1 > 0.0 && d2 > 0.0)) + { if (parm->msg_lev >= GLP_MSG_DBG) + xprintf("d1 = %.12g; d2 = %.12g\n", d1, d2); + if (cbar_st != 1 || !rigorous) + { if (cbar_st != 1) cbar_st = 0; + rigorous = 5; + goto loop; + } + } + /* replace cbar[q] by more accurate value keeping its sign */ + if (d1 > 0.0) + csa->cbar[csa->q] = (d2 > 0.0 ? d2 : +DBL_EPSILON); + else + csa->cbar[csa->q] = (d2 < 0.0 ? d2 : -DBL_EPSILON); + } + /* choose basic variable xB[p] */ + switch (parm->r_test) + { case GLP_RT_STD: + chuzr(csa, 0.0); + break; + case GLP_RT_HAR: + chuzr(csa, 0.30 * parm->tol_bnd); + break; + default: + xassert(parm != parm); + } + if (csa->p == 0) + { if (bbar_st != 1 || cbar_st != 1 || !rigorous) + { if (bbar_st != 1) bbar_st = 0; + if (cbar_st != 1) cbar_st = 0; + rigorous = 1; + goto loop; + } + display(csa, parm, 1); + switch (csa->phase) + { case 1: + if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("Error: unable to choose basic variable on ph" + "ase I\n"); + xassert(!lp->valid && lp->bfd == NULL); + lp->bfd = csa->bfd, csa->bfd = NULL; + lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; + lp->obj_val = 0.0; + lp->it_cnt = csa->it_cnt; + lp->some = 0; + ret = GLP_EFAIL; + break; + case 2: + if (parm->msg_lev >= GLP_MSG_ALL) +#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ + xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n"); +#else + xprintf("LP HAS UNBOUNDED PRIMAL SOLUTION\n"); +#endif + store_sol(csa, lp, GLP_FEAS, GLP_NOFEAS, + csa->head[csa->m+csa->q]); + ret = 0; + break; + default: + xassert(csa != csa); + } + goto done; + } + /* check if the pivot element is acceptable */ + if (csa->p > 0) + { double piv = csa->tcol_vec[csa->p]; + double eps = 1e-5 * (1.0 + 0.01 * csa->tcol_max); + if (fabs(piv) < eps) + { if (parm->msg_lev >= GLP_MSG_DBG) + xprintf("piv = %.12g; eps = %g\n", piv, eps); + if (!rigorous) + { rigorous = 5; + goto loop; + } + } + } + /* now xN[q] and xB[p] have been chosen anyhow */ + /* compute pivot row of the simplex table */ + if (csa->p > 0) + { double *rho = csa->work4; + eval_rho(csa, rho); + if (rigorous) refine_rho(csa, rho); + eval_trow(csa, rho); + } + /* accuracy check based on the pivot element */ + if (csa->p > 0) + { double piv1 = csa->tcol_vec[csa->p]; /* more accurate */ + double piv2 = csa->trow_vec[csa->q]; /* less accurate */ + xassert(piv1 != 0.0); + if (fabs(piv1 - piv2) > 1e-8 * (1.0 + fabs(piv1)) || + !(piv1 > 0.0 && piv2 > 0.0 || piv1 < 0.0 && piv2 < 0.0)) + { if (parm->msg_lev >= GLP_MSG_DBG) + xprintf("piv1 = %.12g; piv2 = %.12g\n", piv1, piv2); + if (binv_st != 1 || !rigorous) + { if (binv_st != 1) binv_st = 0; + rigorous = 5; + goto loop; + } + /* use more accurate version in the pivot row */ + if (csa->trow_vec[csa->q] == 0.0) + { csa->trow_nnz++; + xassert(csa->trow_nnz <= csa->n); + csa->trow_ind[csa->trow_nnz] = csa->q; + } + csa->trow_vec[csa->q] = piv1; + } + } + /* update primal values of basic variables */ + update_bbar(csa); + bbar_st = 2; /* updated */ + /* update reduced costs of non-basic variables */ + if (csa->p > 0) + { update_cbar(csa); + cbar_st = 2; /* updated */ + /* on phase I objective coefficient of xB[p] in the adjacent + basis becomes zero */ + if (csa->phase == 1) + { int k = csa->head[csa->p]; /* x[k] = xB[p] -> xN[q] */ + csa->cbar[csa->q] -= csa->coef[k]; + csa->coef[k] = 0.0; + } + } + /* update steepest edge coefficients */ + if (csa->p > 0) + { switch (parm->pricing) + { case GLP_PT_STD: + break; + case GLP_PT_PSE: + if (csa->refct > 0) update_gamma(csa); + break; + default: + xassert(parm != parm); + } + } + /* update factorization of the basis matrix */ + if (csa->p > 0) + { ret = update_B(csa, csa->p, csa->head[csa->m+csa->q]); + if (ret == 0) + binv_st = 2; /* updated */ + else + { csa->valid = 0; + binv_st = 0; /* invalid */ + } + } + /* update matrix N */ + if (csa->p > 0) + { del_N_col(csa, csa->q, csa->head[csa->m+csa->q]); + if (csa->type[csa->head[csa->p]] != GLP_FX) + add_N_col(csa, csa->q, csa->head[csa->p]); + } + /* change the basis header */ + change_basis(csa); + /* iteration complete */ + csa->it_cnt++; + if (rigorous > 0) rigorous--; + goto loop; +done: /* deallocate the common storage area */ + free_csa(csa); + /* return to the calling program */ + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpspx02.c b/resources/3rdparty/glpk-4.53/src/glpspx02.c new file mode 100644 index 000000000..685c221a0 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpspx02.c @@ -0,0 +1,3118 @@ +/* glpspx02.c (dual simplex method) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpspx.h" + +#define GLP_DEBUG 1 + +#if 0 +#define GLP_LONG_STEP 1 +#endif + +struct csa +{ /* common storage area */ + /*--------------------------------------------------------------*/ + /* LP data */ + int m; + /* number of rows (auxiliary variables), m > 0 */ + int n; + /* number of columns (structural variables), n > 0 */ + char *type; /* char type[1+m+n]; */ + /* type[0] is not used; + type[k], 1 <= k <= m+n, is the type of variable x[k]: + GLP_FR - free variable + GLP_LO - variable with lower bound + GLP_UP - variable with upper bound + GLP_DB - double-bounded variable + GLP_FX - fixed variable */ + double *lb; /* double lb[1+m+n]; */ + /* lb[0] is not used; + lb[k], 1 <= k <= m+n, is an lower bound of variable x[k]; + if x[k] has no lower bound, lb[k] is zero */ + double *ub; /* double ub[1+m+n]; */ + /* ub[0] is not used; + ub[k], 1 <= k <= m+n, is an upper bound of variable x[k]; + if x[k] has no upper bound, ub[k] is zero; + if x[k] is of fixed type, ub[k] is the same as lb[k] */ + double *coef; /* double coef[1+m+n]; */ + /* coef[0] is not used; + coef[k], 1 <= k <= m+n, is an objective coefficient at + variable x[k] */ + /*--------------------------------------------------------------*/ + /* original bounds of variables */ + char *orig_type; /* char orig_type[1+m+n]; */ + double *orig_lb; /* double orig_lb[1+m+n]; */ + double *orig_ub; /* double orig_ub[1+m+n]; */ + /*--------------------------------------------------------------*/ + /* original objective function */ + double *obj; /* double obj[1+n]; */ + /* obj[0] is a constant term of the original objective function; + obj[j], 1 <= j <= n, is an original objective coefficient at + structural variable x[m+j] */ + double zeta; + /* factor used to scale original objective coefficients; its + sign defines original optimization direction: zeta > 0 means + minimization, zeta < 0 means maximization */ + /*--------------------------------------------------------------*/ + /* constraint matrix A; it has m rows and n columns and is stored + by columns */ + int *A_ptr; /* int A_ptr[1+n+1]; */ + /* A_ptr[0] is not used; + A_ptr[j], 1 <= j <= n, is starting position of j-th column in + arrays A_ind and A_val; note that A_ptr[1] is always 1; + A_ptr[n+1] indicates the position after the last element in + arrays A_ind and A_val */ + int *A_ind; /* int A_ind[A_ptr[n+1]]; */ + /* row indices */ + double *A_val; /* double A_val[A_ptr[n+1]]; */ + /* non-zero element values */ +#if 1 /* 06/IV-2009 */ + /* constraint matrix A stored by rows */ + int *AT_ptr; /* int AT_ptr[1+m+1]; */ + /* AT_ptr[0] is not used; + AT_ptr[i], 1 <= i <= m, is starting position of i-th row in + arrays AT_ind and AT_val; note that AT_ptr[1] is always 1; + AT_ptr[m+1] indicates the position after the last element in + arrays AT_ind and AT_val */ + int *AT_ind; /* int AT_ind[AT_ptr[m+1]]; */ + /* column indices */ + double *AT_val; /* double AT_val[AT_ptr[m+1]]; */ + /* non-zero element values */ +#endif + /*--------------------------------------------------------------*/ + /* basis header */ + int *head; /* int head[1+m+n]; */ + /* head[0] is not used; + head[i], 1 <= i <= m, is the ordinal number of basic variable + xB[i]; head[i] = k means that xB[i] = x[k] and i-th column of + matrix B is k-th column of matrix (I|-A); + head[m+j], 1 <= j <= n, is the ordinal number of non-basic + variable xN[j]; head[m+j] = k means that xN[j] = x[k] and j-th + column of matrix N is k-th column of matrix (I|-A) */ +#if 1 /* 06/IV-2009 */ + int *bind; /* int bind[1+m+n]; */ + /* bind[0] is not used; + bind[k], 1 <= k <= m+n, is the position of k-th column of the + matrix (I|-A) in the matrix (B|N); that is, bind[k] = k' means + that head[k'] = k */ +#endif + char *stat; /* char stat[1+n]; */ + /* stat[0] is not used; + stat[j], 1 <= j <= n, is the status of non-basic variable + xN[j], which defines its active bound: + GLP_NL - lower bound is active + GLP_NU - upper bound is active + GLP_NF - free variable + GLP_NS - fixed variable */ + /*--------------------------------------------------------------*/ + /* matrix B is the basis matrix; it is composed from columns of + the augmented constraint matrix (I|-A) corresponding to basic + variables and stored in a factorized (invertable) form */ + int valid; + /* factorization is valid only if this flag is set */ + BFD *bfd; /* BFD bfd[1:m,1:m]; */ + /* factorized (invertable) form of the basis matrix */ +#if 0 /* 06/IV-2009 */ + /*--------------------------------------------------------------*/ + /* matrix N is a matrix composed from columns of the augmented + constraint matrix (I|-A) corresponding to non-basic variables + except fixed ones; it is stored by rows and changes every time + the basis changes */ + int *N_ptr; /* int N_ptr[1+m+1]; */ + /* N_ptr[0] is not used; + N_ptr[i], 1 <= i <= m, is starting position of i-th row in + arrays N_ind and N_val; note that N_ptr[1] is always 1; + N_ptr[m+1] indicates the position after the last element in + arrays N_ind and N_val */ + int *N_len; /* int N_len[1+m]; */ + /* N_len[0] is not used; + N_len[i], 1 <= i <= m, is length of i-th row (0 to n) */ + int *N_ind; /* int N_ind[N_ptr[m+1]]; */ + /* column indices */ + double *N_val; /* double N_val[N_ptr[m+1]]; */ + /* non-zero element values */ +#endif + /*--------------------------------------------------------------*/ + /* working parameters */ + int phase; + /* search phase: + 0 - not determined yet + 1 - search for dual feasible solution + 2 - search for optimal solution */ +#if 0 /* 10/VI-2013 */ + glp_long tm_beg; +#else + double tm_beg; +#endif + /* time value at the beginning of the search */ + int it_beg; + /* simplex iteration count at the beginning of the search */ + int it_cnt; + /* simplex iteration count; it increases by one every time the + basis changes */ + int it_dpy; + /* simplex iteration count at the most recent display output */ + /*--------------------------------------------------------------*/ + /* basic solution components */ + double *bbar; /* double bbar[1+m]; */ + /* bbar[0] is not used on phase I; on phase II it is the current + value of the original objective function; + bbar[i], 1 <= i <= m, is primal value of basic variable xB[i] + (if xB[i] is free, its primal value is not updated) */ + double *cbar; /* double cbar[1+n]; */ + /* cbar[0] is not used; + cbar[j], 1 <= j <= n, is reduced cost of non-basic variable + xN[j] (if xN[j] is fixed, its reduced cost is not updated) */ + /*--------------------------------------------------------------*/ + /* the following pricing technique options may be used: + GLP_PT_STD - standard ("textbook") pricing; + GLP_PT_PSE - projected steepest edge; + GLP_PT_DVX - Devex pricing (not implemented yet); + in case of GLP_PT_STD the reference space is not used, and all + steepest edge coefficients are set to 1 */ + int refct; + /* this count is set to an initial value when the reference space + is defined and decreases by one every time the basis changes; + once this count reaches zero, the reference space is redefined + again */ + char *refsp; /* char refsp[1+m+n]; */ + /* refsp[0] is not used; + refsp[k], 1 <= k <= m+n, is the flag which means that variable + x[k] belongs to the current reference space */ + double *gamma; /* double gamma[1+m]; */ + /* gamma[0] is not used; + gamma[i], 1 <= i <= n, is the steepest edge coefficient for + basic variable xB[i]; if xB[i] is free, gamma[i] is not used + and just set to 1 */ + /*--------------------------------------------------------------*/ + /* basic variable xB[p] chosen to leave the basis */ + int p; + /* index of the basic variable xB[p] chosen, 1 <= p <= m; + if the set of eligible basic variables is empty (i.e. if the + current basic solution is primal feasible within a tolerance) + and thus no variable has been chosen, p is set to 0 */ + double delta; + /* change of xB[p] in the adjacent basis; + delta > 0 means that xB[p] violates its lower bound and will + increase to achieve it in the adjacent basis; + delta < 0 means that xB[p] violates its upper bound and will + decrease to achieve it in the adjacent basis */ + /*--------------------------------------------------------------*/ + /* pivot row of the simplex table corresponding to basic variable + xB[p] chosen is the following vector: + T' * e[p] = - N' * inv(B') * e[p] = - N' * rho, + where B' is a matrix transposed to the current basis matrix, + N' is a matrix, whose rows are columns of the matrix (I|-A) + corresponding to non-basic non-fixed variables */ + int trow_nnz; + /* number of non-zero components, 0 <= nnz <= n */ + int *trow_ind; /* int trow_ind[1+n]; */ + /* trow_ind[0] is not used; + trow_ind[t], 1 <= t <= nnz, is an index of non-zero component, + i.e. trow_ind[t] = j means that trow_vec[j] != 0 */ + double *trow_vec; /* int trow_vec[1+n]; */ + /* trow_vec[0] is not used; + trow_vec[j], 1 <= j <= n, is a numeric value of j-th component + of the row */ + double trow_max; + /* infinity (maximum) norm of the row (max |trow_vec[j]|) */ + int trow_num; + /* number of significant non-zero components, which means that: + |trow_vec[j]| >= eps for j in trow_ind[1,...,num], + |tcol_vec[j]| < eps for j in trow_ind[num+1,...,nnz], + where eps is a pivot tolerance */ + /*--------------------------------------------------------------*/ +#ifdef GLP_LONG_STEP /* 07/IV-2009 */ + int nbps; + /* number of breakpoints, 0 <= nbps <= n */ + struct bkpt + { int j; + /* index of non-basic variable xN[j], 1 <= j <= n */ + double t; + /* value of dual ray parameter at breakpoint, t >= 0 */ + double dz; + /* dz = zeta(t = t[k]) - zeta(t = 0) */ + } *bkpt; /* struct bkpt bkpt[1+n]; */ + /* bkpt[0] is not used; + bkpt[k], 1 <= k <= nbps, is k-th breakpoint of the dual + objective */ +#endif + /*--------------------------------------------------------------*/ + /* non-basic variable xN[q] chosen to enter the basis */ + int q; + /* index of the non-basic variable xN[q] chosen, 1 <= q <= n; + if no variable has been chosen, q is set to 0 */ + double new_dq; + /* reduced cost of xN[q] in the adjacent basis (it is the change + of lambdaB[p]) */ + /*--------------------------------------------------------------*/ + /* pivot column of the simplex table corresponding to non-basic + variable xN[q] chosen is the following vector: + T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], + where B is the current basis matrix, N[q] is a column of the + matrix (I|-A) corresponding to xN[q] */ + int tcol_nnz; + /* number of non-zero components, 0 <= nnz <= m */ + int *tcol_ind; /* int tcol_ind[1+m]; */ + /* tcol_ind[0] is not used; + tcol_ind[t], 1 <= t <= nnz, is an index of non-zero component, + i.e. tcol_ind[t] = i means that tcol_vec[i] != 0 */ + double *tcol_vec; /* double tcol_vec[1+m]; */ + /* tcol_vec[0] is not used; + tcol_vec[i], 1 <= i <= m, is a numeric value of i-th component + of the column */ + /*--------------------------------------------------------------*/ + /* working arrays */ + double *work1; /* double work1[1+m]; */ + double *work2; /* double work2[1+m]; */ + double *work3; /* double work3[1+m]; */ + double *work4; /* double work4[1+m]; */ +}; + +static const double kappa = 0.10; + +/*********************************************************************** +* alloc_csa - allocate common storage area +* +* This routine allocates all arrays in the common storage area (CSA) +* and returns a pointer to the CSA. */ + +static struct csa *alloc_csa(glp_prob *lp) +{ struct csa *csa; + int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + csa = xmalloc(sizeof(struct csa)); + xassert(m > 0 && n > 0); + csa->m = m; + csa->n = n; + csa->type = xcalloc(1+m+n, sizeof(char)); + csa->lb = xcalloc(1+m+n, sizeof(double)); + csa->ub = xcalloc(1+m+n, sizeof(double)); + csa->coef = xcalloc(1+m+n, sizeof(double)); + csa->orig_type = xcalloc(1+m+n, sizeof(char)); + csa->orig_lb = xcalloc(1+m+n, sizeof(double)); + csa->orig_ub = xcalloc(1+m+n, sizeof(double)); + csa->obj = xcalloc(1+n, sizeof(double)); + csa->A_ptr = xcalloc(1+n+1, sizeof(int)); + csa->A_ind = xcalloc(1+nnz, sizeof(int)); + csa->A_val = xcalloc(1+nnz, sizeof(double)); +#if 1 /* 06/IV-2009 */ + csa->AT_ptr = xcalloc(1+m+1, sizeof(int)); + csa->AT_ind = xcalloc(1+nnz, sizeof(int)); + csa->AT_val = xcalloc(1+nnz, sizeof(double)); +#endif + csa->head = xcalloc(1+m+n, sizeof(int)); +#if 1 /* 06/IV-2009 */ + csa->bind = xcalloc(1+m+n, sizeof(int)); +#endif + csa->stat = xcalloc(1+n, sizeof(char)); +#if 0 /* 06/IV-2009 */ + csa->N_ptr = xcalloc(1+m+1, sizeof(int)); + csa->N_len = xcalloc(1+m, sizeof(int)); + csa->N_ind = NULL; /* will be allocated later */ + csa->N_val = NULL; /* will be allocated later */ +#endif + csa->bbar = xcalloc(1+m, sizeof(double)); + csa->cbar = xcalloc(1+n, sizeof(double)); + csa->refsp = xcalloc(1+m+n, sizeof(char)); + csa->gamma = xcalloc(1+m, sizeof(double)); + csa->trow_ind = xcalloc(1+n, sizeof(int)); + csa->trow_vec = xcalloc(1+n, sizeof(double)); +#ifdef GLP_LONG_STEP /* 07/IV-2009 */ + csa->bkpt = xcalloc(1+n, sizeof(struct bkpt)); +#endif + csa->tcol_ind = xcalloc(1+m, sizeof(int)); + csa->tcol_vec = xcalloc(1+m, sizeof(double)); + csa->work1 = xcalloc(1+m, sizeof(double)); + csa->work2 = xcalloc(1+m, sizeof(double)); + csa->work3 = xcalloc(1+m, sizeof(double)); + csa->work4 = xcalloc(1+m, sizeof(double)); + return csa; +} + +/*********************************************************************** +* init_csa - initialize common storage area +* +* This routine initializes all data structures in the common storage +* area (CSA). */ + +static void init_csa(struct csa *csa, glp_prob *lp) +{ int m = csa->m; + int n = csa->n; + char *type = csa->type; + double *lb = csa->lb; + double *ub = csa->ub; + double *coef = csa->coef; + char *orig_type = csa->orig_type; + double *orig_lb = csa->orig_lb; + double *orig_ub = csa->orig_ub; + double *obj = csa->obj; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; +#if 1 /* 06/IV-2009 */ + int *AT_ptr = csa->AT_ptr; + int *AT_ind = csa->AT_ind; + double *AT_val = csa->AT_val; +#endif + int *head = csa->head; +#if 1 /* 06/IV-2009 */ + int *bind = csa->bind; +#endif + char *stat = csa->stat; + char *refsp = csa->refsp; + double *gamma = csa->gamma; + int i, j, k, loc; + double cmax; + /* auxiliary variables */ + for (i = 1; i <= m; i++) + { GLPROW *row = lp->row[i]; + type[i] = (char)row->type; + lb[i] = row->lb * row->rii; + ub[i] = row->ub * row->rii; + coef[i] = 0.0; + } + /* structural variables */ + for (j = 1; j <= n; j++) + { GLPCOL *col = lp->col[j]; + type[m+j] = (char)col->type; + lb[m+j] = col->lb / col->sjj; + ub[m+j] = col->ub / col->sjj; + coef[m+j] = col->coef * col->sjj; + } + /* original bounds of variables */ + memcpy(&orig_type[1], &type[1], (m+n) * sizeof(char)); + memcpy(&orig_lb[1], &lb[1], (m+n) * sizeof(double)); + memcpy(&orig_ub[1], &ub[1], (m+n) * sizeof(double)); + /* original objective function */ + obj[0] = lp->c0; + memcpy(&obj[1], &coef[m+1], n * sizeof(double)); + /* factor used to scale original objective coefficients */ + cmax = 0.0; + for (j = 1; j <= n; j++) + if (cmax < fabs(obj[j])) cmax = fabs(obj[j]); + if (cmax == 0.0) cmax = 1.0; + switch (lp->dir) + { case GLP_MIN: + csa->zeta = + 1.0 / cmax; + break; + case GLP_MAX: + csa->zeta = - 1.0 / cmax; + break; + default: + xassert(lp != lp); + } +#if 1 + if (fabs(csa->zeta) < 1.0) csa->zeta *= 1000.0; +#endif + /* scale working objective coefficients */ + for (j = 1; j <= n; j++) coef[m+j] *= csa->zeta; + /* matrix A (by columns) */ + loc = 1; + for (j = 1; j <= n; j++) + { GLPAIJ *aij; + A_ptr[j] = loc; + for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) + { A_ind[loc] = aij->row->i; + A_val[loc] = aij->row->rii * aij->val * aij->col->sjj; + loc++; + } + } + A_ptr[n+1] = loc; + xassert(loc-1 == lp->nnz); +#if 1 /* 06/IV-2009 */ + /* matrix A (by rows) */ + loc = 1; + for (i = 1; i <= m; i++) + { GLPAIJ *aij; + AT_ptr[i] = loc; + for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { AT_ind[loc] = aij->col->j; + AT_val[loc] = aij->row->rii * aij->val * aij->col->sjj; + loc++; + } + } + AT_ptr[m+1] = loc; + xassert(loc-1 == lp->nnz); +#endif + /* basis header */ + xassert(lp->valid); + memcpy(&head[1], &lp->head[1], m * sizeof(int)); + k = 0; + for (i = 1; i <= m; i++) + { GLPROW *row = lp->row[i]; + if (row->stat != GLP_BS) + { k++; + xassert(k <= n); + head[m+k] = i; + stat[k] = (char)row->stat; + } + } + for (j = 1; j <= n; j++) + { GLPCOL *col = lp->col[j]; + if (col->stat != GLP_BS) + { k++; + xassert(k <= n); + head[m+k] = m + j; + stat[k] = (char)col->stat; + } + } + xassert(k == n); +#if 1 /* 06/IV-2009 */ + for (k = 1; k <= m+n; k++) + bind[head[k]] = k; +#endif + /* factorization of matrix B */ + csa->valid = 1, lp->valid = 0; + csa->bfd = lp->bfd, lp->bfd = NULL; +#if 0 /* 06/IV-2009 */ + /* matrix N (by rows) */ + alloc_N(csa); + build_N(csa); +#endif + /* working parameters */ + csa->phase = 0; + csa->tm_beg = xtime(); + csa->it_beg = csa->it_cnt = lp->it_cnt; + csa->it_dpy = -1; + /* reference space and steepest edge coefficients */ + csa->refct = 0; + memset(&refsp[1], 0, (m+n) * sizeof(char)); + for (i = 1; i <= m; i++) gamma[i] = 1.0; + return; +} + +#if 1 /* copied from primal */ +/*********************************************************************** +* invert_B - compute factorization of the basis matrix +* +* This routine computes factorization of the current basis matrix B. +* +* If the operation is successful, the routine returns zero, otherwise +* non-zero. */ + +static int inv_col(void *info, int i, int ind[], double val[]) +{ /* this auxiliary routine returns row indices and numeric values + of non-zero elements of i-th column of the basis matrix */ + struct csa *csa = info; + int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + int k, len, ptr, t; +#ifdef GLP_DEBUG + xassert(1 <= i && i <= m); +#endif + k = head[i]; /* B[i] is k-th column of (I|-A) */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { /* B[i] is k-th column of submatrix I */ + len = 1; + ind[1] = k; + val[1] = 1.0; + } + else + { /* B[i] is (k-m)-th column of submatrix (-A) */ + ptr = A_ptr[k-m]; + len = A_ptr[k-m+1] - ptr; + memcpy(&ind[1], &A_ind[ptr], len * sizeof(int)); + memcpy(&val[1], &A_val[ptr], len * sizeof(double)); + for (t = 1; t <= len; t++) val[t] = - val[t]; + } + return len; +} + +static int invert_B(struct csa *csa) +{ int ret; + ret = bfd_factorize(csa->bfd, csa->m, NULL, inv_col, csa); + csa->valid = (ret == 0); + return ret; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* update_B - update factorization of the basis matrix +* +* This routine replaces i-th column of the basis matrix B by k-th +* column of the augmented constraint matrix (I|-A) and then updates +* the factorization of B. +* +* If the factorization has been successfully updated, the routine +* returns zero, otherwise non-zero. */ + +static int update_B(struct csa *csa, int i, int k) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int ret; +#ifdef GLP_DEBUG + xassert(1 <= i && i <= m); + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { /* new i-th column of B is k-th column of I */ + int ind[1+1]; + double val[1+1]; + ind[1] = k; + val[1] = 1.0; + xassert(csa->valid); + ret = bfd_update_it(csa->bfd, i, 0, 1, ind, val); + } + else + { /* new i-th column of B is (k-m)-th column of (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + double *val = csa->work1; + int beg, end, ptr, len; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + len = 0; + for (ptr = beg; ptr < end; ptr++) + val[++len] = - A_val[ptr]; + xassert(csa->valid); + ret = bfd_update_it(csa->bfd, i, 0, len, &A_ind[beg-1], val); + } + csa->valid = (ret == 0); + return ret; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* error_ftran - compute residual vector r = h - B * x +* +* This routine computes the residual vector r = h - B * x, where B is +* the current basis matrix, h is the vector of right-hand sides, x is +* the solution vector. */ + +static void error_ftran(struct csa *csa, double h[], double x[], + double r[]) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + int i, k, beg, end, ptr; + double temp; + /* compute the residual vector: + r = h - B * x = h - B[1] * x[1] - ... - B[m] * x[m], + where B[1], ..., B[m] are columns of matrix B */ + memcpy(&r[1], &h[1], m * sizeof(double)); + for (i = 1; i <= m; i++) + { temp = x[i]; + if (temp == 0.0) continue; + k = head[i]; /* B[i] is k-th column of (I|-A) */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { /* B[i] is k-th column of submatrix I */ + r[k] -= temp; + } + else + { /* B[i] is (k-m)-th column of submatrix (-A) */ + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + r[A_ind[ptr]] += A_val[ptr] * temp; + } + } + return; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* refine_ftran - refine solution of B * x = h +* +* This routine performs one iteration to refine the solution of +* the system B * x = h, where B is the current basis matrix, h is the +* vector of right-hand sides, x is the solution vector. */ + +static void refine_ftran(struct csa *csa, double h[], double x[]) +{ int m = csa->m; + double *r = csa->work1; + double *d = csa->work1; + int i; + /* compute the residual vector r = h - B * x */ + error_ftran(csa, h, x, r); + /* compute the correction vector d = inv(B) * r */ + xassert(csa->valid); + bfd_ftran(csa->bfd, d); + /* refine the solution vector (new x) = (old x) + d */ + for (i = 1; i <= m; i++) x[i] += d[i]; + return; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* error_btran - compute residual vector r = h - B'* x +* +* This routine computes the residual vector r = h - B'* x, where B' +* is a matrix transposed to the current basis matrix, h is the vector +* of right-hand sides, x is the solution vector. */ + +static void error_btran(struct csa *csa, double h[], double x[], + double r[]) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + int i, k, beg, end, ptr; + double temp; + /* compute the residual vector r = b - B'* x */ + for (i = 1; i <= m; i++) + { /* r[i] := b[i] - (i-th column of B)'* x */ + k = head[i]; /* B[i] is k-th column of (I|-A) */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + temp = h[i]; + if (k <= m) + { /* B[i] is k-th column of submatrix I */ + temp -= x[k]; + } + else + { /* B[i] is (k-m)-th column of submatrix (-A) */ + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + temp += A_val[ptr] * x[A_ind[ptr]]; + } + r[i] = temp; + } + return; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* refine_btran - refine solution of B'* x = h +* +* This routine performs one iteration to refine the solution of the +* system B'* x = h, where B' is a matrix transposed to the current +* basis matrix, h is the vector of right-hand sides, x is the solution +* vector. */ + +static void refine_btran(struct csa *csa, double h[], double x[]) +{ int m = csa->m; + double *r = csa->work1; + double *d = csa->work1; + int i; + /* compute the residual vector r = h - B'* x */ + error_btran(csa, h, x, r); + /* compute the correction vector d = inv(B') * r */ + xassert(csa->valid); + bfd_btran(csa->bfd, d); + /* refine the solution vector (new x) = (old x) + d */ + for (i = 1; i <= m; i++) x[i] += d[i]; + return; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* get_xN - determine current value of non-basic variable xN[j] +* +* This routine returns the current value of non-basic variable xN[j], +* which is a value of its active bound. */ + +static double get_xN(struct csa *csa, int j) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + double *lb = csa->lb; + double *ub = csa->ub; + int *head = csa->head; + char *stat = csa->stat; + int k; + double xN; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); +#endif + k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + switch (stat[j]) + { case GLP_NL: + /* x[k] is on its lower bound */ + xN = lb[k]; break; + case GLP_NU: + /* x[k] is on its upper bound */ + xN = ub[k]; break; + case GLP_NF: + /* x[k] is free non-basic variable */ + xN = 0.0; break; + case GLP_NS: + /* x[k] is fixed non-basic variable */ + xN = lb[k]; break; + default: + xassert(stat != stat); + } + return xN; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* eval_beta - compute primal values of basic variables +* +* This routine computes current primal values of all basic variables: +* +* beta = - inv(B) * N * xN, +* +* where B is the current basis matrix, N is a matrix built of columns +* of matrix (I|-A) corresponding to non-basic variables, and xN is the +* vector of current values of non-basic variables. */ + +static void eval_beta(struct csa *csa, double beta[]) +{ int m = csa->m; + int n = csa->n; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + double *h = csa->work2; + int i, j, k, beg, end, ptr; + double xN; + /* compute the right-hand side vector: + h := - N * xN = - N[1] * xN[1] - ... - N[n] * xN[n], + where N[1], ..., N[n] are columns of matrix N */ + for (i = 1; i <= m; i++) + h[i] = 0.0; + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + /* determine current value of xN[j] */ + xN = get_xN(csa, j); + if (xN == 0.0) continue; + if (k <= m) + { /* N[j] is k-th column of submatrix I */ + h[k] -= xN; + } + else + { /* N[j] is (k-m)-th column of submatrix (-A) */ + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + h[A_ind[ptr]] += xN * A_val[ptr]; + } + } + /* solve system B * beta = h */ + memcpy(&beta[1], &h[1], m * sizeof(double)); + xassert(csa->valid); + bfd_ftran(csa->bfd, beta); + /* and refine the solution */ + refine_ftran(csa, h, beta); + return; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* eval_pi - compute vector of simplex multipliers +* +* This routine computes the vector of current simplex multipliers: +* +* pi = inv(B') * cB, +* +* where B' is a matrix transposed to the current basis matrix, cB is +* a subvector of objective coefficients at basic variables. */ + +static void eval_pi(struct csa *csa, double pi[]) +{ int m = csa->m; + double *c = csa->coef; + int *head = csa->head; + double *cB = csa->work2; + int i; + /* construct the right-hand side vector cB */ + for (i = 1; i <= m; i++) + cB[i] = c[head[i]]; + /* solve system B'* pi = cB */ + memcpy(&pi[1], &cB[1], m * sizeof(double)); + xassert(csa->valid); + bfd_btran(csa->bfd, pi); + /* and refine the solution */ + refine_btran(csa, cB, pi); + return; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* eval_cost - compute reduced cost of non-basic variable xN[j] +* +* This routine computes the current reduced cost of non-basic variable +* xN[j]: +* +* d[j] = cN[j] - N'[j] * pi, +* +* where cN[j] is the objective coefficient at variable xN[j], N[j] is +* a column of the augmented constraint matrix (I|-A) corresponding to +* xN[j], pi is the vector of simplex multipliers. */ + +static double eval_cost(struct csa *csa, double pi[], int j) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + double *coef = csa->coef; + int *head = csa->head; + int k; + double dj; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); +#endif + k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + dj = coef[k]; + if (k <= m) + { /* N[j] is k-th column of submatrix I */ + dj -= pi[k]; + } + else + { /* N[j] is (k-m)-th column of submatrix (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + dj += A_val[ptr] * pi[A_ind[ptr]]; + } + return dj; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* eval_bbar - compute and store primal values of basic variables +* +* This routine computes primal values of all basic variables and then +* stores them in the solution array. */ + +static void eval_bbar(struct csa *csa) +{ eval_beta(csa, csa->bbar); + return; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* eval_cbar - compute and store reduced costs of non-basic variables +* +* This routine computes reduced costs of all non-basic variables and +* then stores them in the solution array. */ + +static void eval_cbar(struct csa *csa) +{ +#ifdef GLP_DEBUG + int m = csa->m; +#endif + int n = csa->n; +#ifdef GLP_DEBUG + int *head = csa->head; +#endif + double *cbar = csa->cbar; + double *pi = csa->work3; + int j; +#ifdef GLP_DEBUG + int k; +#endif + /* compute simplex multipliers */ + eval_pi(csa, pi); + /* compute and store reduced costs */ + for (j = 1; j <= n; j++) + { +#ifdef GLP_DEBUG + k = head[m+j]; /* x[k] = xN[j] */ + xassert(1 <= k && k <= m+n); +#endif + cbar[j] = eval_cost(csa, pi, j); + } + return; +} +#endif + +/*********************************************************************** +* reset_refsp - reset the reference space +* +* This routine resets (redefines) the reference space used in the +* projected steepest edge pricing algorithm. */ + +static void reset_refsp(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + int *head = csa->head; + char *refsp = csa->refsp; + double *gamma = csa->gamma; + int i, k; + xassert(csa->refct == 0); + csa->refct = 1000; + memset(&refsp[1], 0, (m+n) * sizeof(char)); + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + refsp[k] = 1; + gamma[i] = 1.0; + } + return; +} + +/*********************************************************************** +* eval_gamma - compute steepest edge coefficients +* +* This routine computes the vector of steepest edge coefficients for +* all basic variables (except free ones) using its direct definition: +* +* gamma[i] = eta[i] + sum alfa[i,j]^2, i = 1,...,m, +* j in C +* +* where eta[i] = 1 means that xB[i] is in the current reference space, +* and 0 otherwise; C is a set of non-basic non-fixed variables xN[j], +* which are in the current reference space; alfa[i,j] are elements of +* the current simplex table. +* +* NOTE: The routine is intended only for debugginig purposes. */ + +static void eval_gamma(struct csa *csa, double gamma[]) +{ int m = csa->m; + int n = csa->n; + char *type = csa->type; + int *head = csa->head; + char *refsp = csa->refsp; + double *alfa = csa->work3; + double *h = csa->work3; + int i, j, k; + /* gamma[i] := eta[i] (or 1, if xB[i] is free) */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (type[k] == GLP_FR) + gamma[i] = 1.0; + else + gamma[i] = (refsp[k] ? 1.0 : 0.0); + } + /* compute columns of the current simplex table */ + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + /* skip column, if xN[j] is not in C */ + if (!refsp[k]) continue; +#ifdef GLP_DEBUG + /* set C must not contain fixed variables */ + xassert(type[k] != GLP_FX); +#endif + /* construct the right-hand side vector h = - N[j] */ + for (i = 1; i <= m; i++) + h[i] = 0.0; + if (k <= m) + { /* N[j] is k-th column of submatrix I */ + h[k] = -1.0; + } + else + { /* N[j] is (k-m)-th column of submatrix (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + h[A_ind[ptr]] = A_val[ptr]; + } + /* solve system B * alfa = h */ + xassert(csa->valid); + bfd_ftran(csa->bfd, alfa); + /* gamma[i] := gamma[i] + alfa[i,j]^2 */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + if (type[k] != GLP_FR) + gamma[i] += alfa[i] * alfa[i]; + } + } + return; +} + +/*********************************************************************** +* chuzr - choose basic variable (row of the simplex table) +* +* This routine chooses basic variable xB[p] having largest weighted +* bound violation: +* +* |r[p]| / sqrt(gamma[p]) = max |r[i]| / sqrt(gamma[i]), +* i in I +* +* / lB[i] - beta[i], if beta[i] < lB[i] +* | +* r[i] = < 0, if lB[i] <= beta[i] <= uB[i] +* | +* \ uB[i] - beta[i], if beta[i] > uB[i] +* +* where beta[i] is primal value of xB[i] in the current basis, lB[i] +* and uB[i] are lower and upper bounds of xB[i], I is a subset of +* eligible basic variables, which significantly violates their bounds, +* gamma[i] is the steepest edge coefficient. +* +* If |r[i]| is less than a specified tolerance, xB[i] is not included +* in I and therefore ignored. +* +* If I is empty and no variable has been chosen, p is set to 0. */ + +static void chuzr(struct csa *csa, double tol_bnd) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + char *type = csa->type; + double *lb = csa->lb; + double *ub = csa->ub; + int *head = csa->head; + double *bbar = csa->bbar; + double *gamma = csa->gamma; + int i, k, p; + double delta, best, eps, ri, temp; + /* nothing is chosen so far */ + p = 0, delta = 0.0, best = 0.0; + /* look through the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + /* determine bound violation ri[i] */ + ri = 0.0; + if (type[k] == GLP_LO || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* xB[i] has lower bound */ + eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); + if (bbar[i] < lb[k] - eps) + { /* and significantly violates it */ + ri = lb[k] - bbar[i]; + } + } + if (type[k] == GLP_UP || type[k] == GLP_DB || + type[k] == GLP_FX) + { /* xB[i] has upper bound */ + eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); + if (bbar[i] > ub[k] + eps) + { /* and significantly violates it */ + ri = ub[k] - bbar[i]; + } + } + /* if xB[i] is not eligible, skip it */ + if (ri == 0.0) continue; + /* xB[i] is eligible basic variable; choose one with largest + weighted bound violation */ +#ifdef GLP_DEBUG + xassert(gamma[i] >= 0.0); +#endif + temp = gamma[i]; + if (temp < DBL_EPSILON) temp = DBL_EPSILON; + temp = (ri * ri) / temp; + if (best < temp) + p = i, delta = ri, best = temp; + } + /* store the index of basic variable xB[p] chosen and its change + in the adjacent basis */ + csa->p = p; + csa->delta = delta; + return; +} + +#if 1 /* copied from primal */ +/*********************************************************************** +* eval_rho - compute pivot row of the inverse +* +* This routine computes the pivot (p-th) row of the inverse inv(B), +* which corresponds to basic variable xB[p] chosen: +* +* rho = inv(B') * e[p], +* +* where B' is a matrix transposed to the current basis matrix, e[p] +* is unity vector. */ + +static void eval_rho(struct csa *csa, double rho[]) +{ int m = csa->m; + int p = csa->p; + double *e = rho; + int i; +#ifdef GLP_DEBUG + xassert(1 <= p && p <= m); +#endif + /* construct the right-hand side vector e[p] */ + for (i = 1; i <= m; i++) + e[i] = 0.0; + e[p] = 1.0; + /* solve system B'* rho = e[p] */ + xassert(csa->valid); + bfd_btran(csa->bfd, rho); + return; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* refine_rho - refine pivot row of the inverse +* +* This routine refines the pivot row of the inverse inv(B) assuming +* that it was previously computed by the routine eval_rho. */ + +static void refine_rho(struct csa *csa, double rho[]) +{ int m = csa->m; + int p = csa->p; + double *e = csa->work3; + int i; +#ifdef GLP_DEBUG + xassert(1 <= p && p <= m); +#endif + /* construct the right-hand side vector e[p] */ + for (i = 1; i <= m; i++) + e[i] = 0.0; + e[p] = 1.0; + /* refine solution of B'* rho = e[p] */ + refine_btran(csa, e, rho); + return; +} +#endif + +#if 1 /* 06/IV-2009 */ +/*********************************************************************** +* eval_trow - compute pivot row of the simplex table +* +* This routine computes the pivot row of the simplex table, which +* corresponds to basic variable xB[p] chosen. +* +* The pivot row is the following vector: +* +* trow = T'* e[p] = - N'* inv(B') * e[p] = - N' * rho, +* +* where rho is the pivot row of the inverse inv(B) previously computed +* by the routine eval_rho. +* +* Note that elements of the pivot row corresponding to fixed non-basic +* variables are not computed. +* +* NOTES +* +* Computing pivot row of the simplex table is one of the most time +* consuming operations, and for some instances it may take more than +* 50% of the total solution time. +* +* In the current implementation there are two routines to compute the +* pivot row. The routine eval_trow1 computes elements of the pivot row +* as inner products of columns of the matrix N and the vector rho; it +* is used when the vector rho is relatively dense. The routine +* eval_trow2 computes the pivot row as a linear combination of rows of +* the matrix N; it is used when the vector rho is relatively sparse. */ + +static void eval_trow1(struct csa *csa, double rho[]) +{ int m = csa->m; + int n = csa->n; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int *head = csa->head; + char *stat = csa->stat; + int *trow_ind = csa->trow_ind; + double *trow_vec = csa->trow_vec; + int j, k, beg, end, ptr, nnz; + double temp; + /* compute the pivot row as inner products of columns of the + matrix N and vector rho: trow[j] = - rho * N[j] */ + nnz = 0; + for (j = 1; j <= n; j++) + { if (stat[j] == GLP_NS) + { /* xN[j] is fixed */ + trow_vec[j] = 0.0; + continue; + } + k = head[m+j]; /* x[k] = xN[j] */ + if (k <= m) + { /* N[j] is k-th column of submatrix I */ + temp = - rho[k]; + } + else + { /* N[j] is (k-m)-th column of submatrix (-A) */ + beg = A_ptr[k-m], end = A_ptr[k-m+1]; + temp = 0.0; + for (ptr = beg; ptr < end; ptr++) + temp += rho[A_ind[ptr]] * A_val[ptr]; + } + if (temp != 0.0) + trow_ind[++nnz] = j; + trow_vec[j] = temp; + } + csa->trow_nnz = nnz; + return; +} + +static void eval_trow2(struct csa *csa, double rho[]) +{ int m = csa->m; + int n = csa->n; + int *AT_ptr = csa->AT_ptr; + int *AT_ind = csa->AT_ind; + double *AT_val = csa->AT_val; + int *bind = csa->bind; + char *stat = csa->stat; + int *trow_ind = csa->trow_ind; + double *trow_vec = csa->trow_vec; + int i, j, beg, end, ptr, nnz; + double temp; + /* clear the pivot row */ + for (j = 1; j <= n; j++) + trow_vec[j] = 0.0; + /* compute the pivot row as a linear combination of rows of the + matrix N: trow = - rho[1] * N'[1] - ... - rho[m] * N'[m] */ + for (i = 1; i <= m; i++) + { temp = rho[i]; + if (temp == 0.0) continue; + /* trow := trow - rho[i] * N'[i] */ + j = bind[i] - m; /* x[i] = xN[j] */ + if (j >= 1 && stat[j] != GLP_NS) + trow_vec[j] -= temp; + beg = AT_ptr[i], end = AT_ptr[i+1]; + for (ptr = beg; ptr < end; ptr++) + { j = bind[m + AT_ind[ptr]] - m; /* x[k] = xN[j] */ + if (j >= 1 && stat[j] != GLP_NS) + trow_vec[j] += temp * AT_val[ptr]; + } + } + /* construct sparse pattern of the pivot row */ + nnz = 0; + for (j = 1; j <= n; j++) + { if (trow_vec[j] != 0.0) + trow_ind[++nnz] = j; + } + csa->trow_nnz = nnz; + return; +} + +static void eval_trow(struct csa *csa, double rho[]) +{ int m = csa->m; + int i, nnz; + double dens; + /* determine the density of the vector rho */ + nnz = 0; + for (i = 1; i <= m; i++) + if (rho[i] != 0.0) nnz++; + dens = (double)nnz / (double)m; + if (dens >= 0.20) + { /* rho is relatively dense */ + eval_trow1(csa, rho); + } + else + { /* rho is relatively sparse */ + eval_trow2(csa, rho); + } + return; +} +#endif + +/*********************************************************************** +* sort_trow - sort pivot row of the simplex table +* +* This routine reorders the list of non-zero elements of the pivot +* row to put significant elements, whose magnitude is not less than +* a specified tolerance, in front of the list, and stores the number +* of significant elements in trow_num. */ + +static void sort_trow(struct csa *csa, double tol_piv) +{ +#ifdef GLP_DEBUG + int n = csa->n; + char *stat = csa->stat; +#endif + int nnz = csa->trow_nnz; + int *trow_ind = csa->trow_ind; + double *trow_vec = csa->trow_vec; + int j, num, pos; + double big, eps, temp; + /* compute infinity (maximum) norm of the row */ + big = 0.0; + for (pos = 1; pos <= nnz; pos++) + { +#ifdef GLP_DEBUG + j = trow_ind[pos]; + xassert(1 <= j && j <= n); + xassert(stat[j] != GLP_NS); +#endif + temp = fabs(trow_vec[trow_ind[pos]]); + if (big < temp) big = temp; + } + csa->trow_max = big; + /* determine absolute pivot tolerance */ + eps = tol_piv * (1.0 + 0.01 * big); + /* move significant row components to the front of the list */ + for (num = 0; num < nnz; ) + { j = trow_ind[nnz]; + if (fabs(trow_vec[j]) < eps) + nnz--; + else + { num++; + trow_ind[nnz] = trow_ind[num]; + trow_ind[num] = j; + } + } + csa->trow_num = num; + return; +} + +#ifdef GLP_LONG_STEP /* 07/IV-2009 */ +static int ls_func(const void *p1_, const void *p2_) +{ const struct bkpt *p1 = p1_, *p2 = p2_; + if (p1->t < p2->t) return -1; + if (p1->t > p2->t) return +1; + return 0; +} + +static int ls_func1(const void *p1_, const void *p2_) +{ const struct bkpt *p1 = p1_, *p2 = p2_; + if (p1->dz < p2->dz) return -1; + if (p1->dz > p2->dz) return +1; + return 0; +} + +static void long_step(struct csa *csa) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + char *type = csa->type; + double *lb = csa->lb; + double *ub = csa->ub; + int *head = csa->head; + char *stat = csa->stat; + double *cbar = csa->cbar; + double delta = csa->delta; + int *trow_ind = csa->trow_ind; + double *trow_vec = csa->trow_vec; + int trow_num = csa->trow_num; + struct bkpt *bkpt = csa->bkpt; + int j, k, kk, nbps, pos; + double alfa, s, slope, dzmax; + /* delta > 0 means that xB[p] violates its lower bound, so to + increase the dual objective lambdaB[p] must increase; + delta < 0 means that xB[p] violates its upper bound, so to + increase the dual objective lambdaB[p] must decrease */ + /* s := sign(delta) */ + s = (delta > 0.0 ? +1.0 : -1.0); + /* determine breakpoints of the dual objective */ + nbps = 0; + for (pos = 1; pos <= trow_num; pos++) + { j = trow_ind[pos]; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); + xassert(stat[j] != GLP_NS); +#endif + /* if there is free non-basic variable, switch to the standard + ratio test */ + if (stat[j] == GLP_NF) + { nbps = 0; + goto done; + } + /* lambdaN[j] = ... - alfa * t - ..., where t = s * lambdaB[i] + is the dual ray parameter, t >= 0 */ + alfa = s * trow_vec[j]; +#ifdef GLP_DEBUG + xassert(alfa != 0.0); + xassert(stat[j] == GLP_NL || stat[j] == GLP_NU); +#endif + if (alfa > 0.0 && stat[j] == GLP_NL || + alfa < 0.0 && stat[j] == GLP_NU) + { /* either lambdaN[j] >= 0 (if stat = GLP_NL) and decreases + or lambdaN[j] <= 0 (if stat = GLP_NU) and increases; in + both cases we have a breakpoint */ + nbps++; +#ifdef GLP_DEBUG + xassert(nbps <= n); +#endif + bkpt[nbps].j = j; + bkpt[nbps].t = cbar[j] / alfa; +/* +if (stat[j] == GLP_NL && cbar[j] < 0.0 || + stat[j] == GLP_NU && cbar[j] > 0.0) +xprintf("%d %g\n", stat[j], cbar[j]); +*/ + /* if t is negative, replace it by exact zero (see comments + in the routine chuzc) */ + if (bkpt[nbps].t < 0.0) bkpt[nbps].t = 0.0; + } + } + /* if there are less than two breakpoints, switch to the standard + ratio test */ + if (nbps < 2) + { nbps = 0; + goto done; + } + /* sort breakpoints by ascending the dual ray parameter, t */ + qsort(&bkpt[1], nbps, sizeof(struct bkpt), ls_func); + /* determine last breakpoint, at which the dual objective still + greater than at t = 0 */ + dzmax = 0.0; + slope = fabs(delta); /* initial slope */ + for (kk = 1; kk <= nbps; kk++) + { if (kk == 1) + bkpt[kk].dz = + 0.0 + slope * (bkpt[kk].t - 0.0); + else + bkpt[kk].dz = + bkpt[kk-1].dz + slope * (bkpt[kk].t - bkpt[kk-1].t); + if (dzmax < bkpt[kk].dz) + dzmax = bkpt[kk].dz; + else if (bkpt[kk].dz < 0.05 * (1.0 + dzmax)) + { nbps = kk - 1; + break; + } + j = bkpt[kk].j; + k = head[m+j]; /* x[k] = xN[j] */ + if (type[k] == GLP_DB) + slope -= fabs(trow_vec[j]) * (ub[k] - lb[k]); + else + { nbps = kk; + break; + } + } + /* if there are less than two breakpoints, switch to the standard + ratio test */ + if (nbps < 2) + { nbps = 0; + goto done; + } + /* sort breakpoints by ascending the dual change, dz */ + qsort(&bkpt[1], nbps, sizeof(struct bkpt), ls_func1); +/* +for (kk = 1; kk <= nbps; kk++) +xprintf("%d; t = %g; dz = %g\n", kk, bkpt[kk].t, bkpt[kk].dz); +*/ +done: csa->nbps = nbps; + return; +} +#endif + +/*********************************************************************** +* chuzc - choose non-basic variable (column of the simplex table) +* +* This routine chooses non-basic variable xN[q], which being entered +* in the basis keeps dual feasibility of the basic solution. +* +* The parameter rtol is a relative tolerance used to relax zero bounds +* of reduced costs of non-basic variables. If rtol = 0, the routine +* implements the standard ratio test. Otherwise, if rtol > 0, the +* routine implements Harris' two-pass ratio test. In the latter case +* rtol should be about three times less than a tolerance used to check +* dual feasibility. */ + +static void chuzc(struct csa *csa, double rtol) +{ +#ifdef GLP_DEBUG + int m = csa->m; + int n = csa->n; +#endif + char *stat = csa->stat; + double *cbar = csa->cbar; +#ifdef GLP_DEBUG + int p = csa->p; +#endif + double delta = csa->delta; + int *trow_ind = csa->trow_ind; + double *trow_vec = csa->trow_vec; + int trow_num = csa->trow_num; + int j, pos, q; + double alfa, big, s, t, teta, tmax; +#ifdef GLP_DEBUG + xassert(1 <= p && p <= m); +#endif + /* delta > 0 means that xB[p] violates its lower bound and goes + to it in the adjacent basis, so lambdaB[p] is increasing from + its lower zero bound; + delta < 0 means that xB[p] violates its upper bound and goes + to it in the adjacent basis, so lambdaB[p] is decreasing from + its upper zero bound */ +#ifdef GLP_DEBUG + xassert(delta != 0.0); +#endif + /* s := sign(delta) */ + s = (delta > 0.0 ? +1.0 : -1.0); + /*** FIRST PASS ***/ + /* nothing is chosen so far */ + q = 0, teta = DBL_MAX, big = 0.0; + /* walk through significant elements of the pivot row */ + for (pos = 1; pos <= trow_num; pos++) + { j = trow_ind[pos]; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); +#endif + alfa = s * trow_vec[j]; +#ifdef GLP_DEBUG + xassert(alfa != 0.0); +#endif + /* lambdaN[j] = ... - alfa * lambdaB[p] - ..., and due to s we + need to consider only increasing lambdaB[p] */ + if (alfa > 0.0) + { /* lambdaN[j] is decreasing */ + if (stat[j] == GLP_NL || stat[j] == GLP_NF) + { /* lambdaN[j] has zero lower bound */ + t = (cbar[j] + rtol) / alfa; + } + else + { /* lambdaN[j] has no lower bound */ + continue; + } + } + else + { /* lambdaN[j] is increasing */ + if (stat[j] == GLP_NU || stat[j] == GLP_NF) + { /* lambdaN[j] has zero upper bound */ + t = (cbar[j] - rtol) / alfa; + } + else + { /* lambdaN[j] has no upper bound */ + continue; + } + } + /* t is a change of lambdaB[p], on which lambdaN[j] reaches + its zero bound (possibly relaxed); since the basic solution + is assumed to be dual feasible, t has to be non-negative by + definition; however, it may happen that lambdaN[j] slightly + (i.e. within a tolerance) violates its zero bound, that + leads to negative t; in the latter case, if xN[j] is chosen, + negative t means that lambdaB[p] changes in wrong direction + that may cause wrong results on updating reduced costs; + thus, if t is negative, we should replace it by exact zero + assuming that lambdaN[j] is exactly on its zero bound, and + violation appears due to round-off errors */ + if (t < 0.0) t = 0.0; + /* apply minimal ratio test */ + if (teta > t || teta == t && big < fabs(alfa)) + q = j, teta = t, big = fabs(alfa); + } + /* the second pass is skipped in the following cases: */ + /* if the standard ratio test is used */ + if (rtol == 0.0) goto done; + /* if no non-basic variable has been chosen on the first pass */ + if (q == 0) goto done; + /* if lambdaN[q] prevents lambdaB[p] from any change */ + if (teta == 0.0) goto done; + /*** SECOND PASS ***/ + /* here tmax is a maximal change of lambdaB[p], on which the + solution remains dual feasible within a tolerance */ +#if 0 + tmax = (1.0 + 10.0 * DBL_EPSILON) * teta; +#else + tmax = teta; +#endif + /* nothing is chosen so far */ + q = 0, teta = DBL_MAX, big = 0.0; + /* walk through significant elements of the pivot row */ + for (pos = 1; pos <= trow_num; pos++) + { j = trow_ind[pos]; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); +#endif + alfa = s * trow_vec[j]; +#ifdef GLP_DEBUG + xassert(alfa != 0.0); +#endif + /* lambdaN[j] = ... - alfa * lambdaB[p] - ..., and due to s we + need to consider only increasing lambdaB[p] */ + if (alfa > 0.0) + { /* lambdaN[j] is decreasing */ + if (stat[j] == GLP_NL || stat[j] == GLP_NF) + { /* lambdaN[j] has zero lower bound */ + t = cbar[j] / alfa; + } + else + { /* lambdaN[j] has no lower bound */ + continue; + } + } + else + { /* lambdaN[j] is increasing */ + if (stat[j] == GLP_NU || stat[j] == GLP_NF) + { /* lambdaN[j] has zero upper bound */ + t = cbar[j] / alfa; + } + else + { /* lambdaN[j] has no upper bound */ + continue; + } + } + /* (see comments for the first pass) */ + if (t < 0.0) t = 0.0; + /* t is a change of lambdaB[p], on which lambdaN[j] reaches + its zero (lower or upper) bound; if t <= tmax, all reduced + costs can violate their zero bounds only within relaxation + tolerance rtol, so we can choose non-basic variable having + largest influence coefficient to avoid possible numerical + instability */ + if (t <= tmax && big < fabs(alfa)) + q = j, teta = t, big = fabs(alfa); + } + /* something must be chosen on the second pass */ + xassert(q != 0); +done: /* store the index of non-basic variable xN[q] chosen */ + csa->q = q; + /* store reduced cost of xN[q] in the adjacent basis */ + csa->new_dq = s * teta; + return; +} + +#if 1 /* copied from primal */ +/*********************************************************************** +* eval_tcol - compute pivot column of the simplex table +* +* This routine computes the pivot column of the simplex table, which +* corresponds to non-basic variable xN[q] chosen. +* +* The pivot column is the following vector: +* +* tcol = T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], +* +* where B is the current basis matrix, N[q] is a column of the matrix +* (I|-A) corresponding to variable xN[q]. */ + +static void eval_tcol(struct csa *csa) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *head = csa->head; + int q = csa->q; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + double *h = csa->tcol_vec; + int i, k, nnz; +#ifdef GLP_DEBUG + xassert(1 <= q && q <= n); +#endif + k = head[m+q]; /* x[k] = xN[q] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + /* construct the right-hand side vector h = - N[q] */ + for (i = 1; i <= m; i++) + h[i] = 0.0; + if (k <= m) + { /* N[q] is k-th column of submatrix I */ + h[k] = -1.0; + } + else + { /* N[q] is (k-m)-th column of submatrix (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + h[A_ind[ptr]] = A_val[ptr]; + } + /* solve system B * tcol = h */ + xassert(csa->valid); + bfd_ftran(csa->bfd, tcol_vec); + /* construct sparse pattern of the pivot column */ + nnz = 0; + for (i = 1; i <= m; i++) + { if (tcol_vec[i] != 0.0) + tcol_ind[++nnz] = i; + } + csa->tcol_nnz = nnz; + return; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* refine_tcol - refine pivot column of the simplex table +* +* This routine refines the pivot column of the simplex table assuming +* that it was previously computed by the routine eval_tcol. */ + +static void refine_tcol(struct csa *csa) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + int *head = csa->head; + int q = csa->q; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + double *h = csa->work3; + int i, k, nnz; +#ifdef GLP_DEBUG + xassert(1 <= q && q <= n); +#endif + k = head[m+q]; /* x[k] = xN[q] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + /* construct the right-hand side vector h = - N[q] */ + for (i = 1; i <= m; i++) + h[i] = 0.0; + if (k <= m) + { /* N[q] is k-th column of submatrix I */ + h[k] = -1.0; + } + else + { /* N[q] is (k-m)-th column of submatrix (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + h[A_ind[ptr]] = A_val[ptr]; + } + /* refine solution of B * tcol = h */ + refine_ftran(csa, h, tcol_vec); + /* construct sparse pattern of the pivot column */ + nnz = 0; + for (i = 1; i <= m; i++) + { if (tcol_vec[i] != 0.0) + tcol_ind[++nnz] = i; + } + csa->tcol_nnz = nnz; + return; +} +#endif + +/*********************************************************************** +* update_cbar - update reduced costs of non-basic variables +* +* This routine updates reduced costs of all (except fixed) non-basic +* variables for the adjacent basis. */ + +static void update_cbar(struct csa *csa) +{ +#ifdef GLP_DEBUG + int n = csa->n; +#endif + double *cbar = csa->cbar; + int trow_nnz = csa->trow_nnz; + int *trow_ind = csa->trow_ind; + double *trow_vec = csa->trow_vec; + int q = csa->q; + double new_dq = csa->new_dq; + int j, pos; +#ifdef GLP_DEBUG + xassert(1 <= q && q <= n); +#endif + /* set new reduced cost of xN[q] */ + cbar[q] = new_dq; + /* update reduced costs of other non-basic variables */ + if (new_dq == 0.0) goto done; + for (pos = 1; pos <= trow_nnz; pos++) + { j = trow_ind[pos]; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); +#endif + if (j != q) + cbar[j] -= trow_vec[j] * new_dq; + } +done: return; +} + +/*********************************************************************** +* update_bbar - update values of basic variables +* +* This routine updates values of all basic variables for the adjacent +* basis. */ + +static void update_bbar(struct csa *csa) +{ +#ifdef GLP_DEBUG + int m = csa->m; + int n = csa->n; +#endif + double *bbar = csa->bbar; + int p = csa->p; + double delta = csa->delta; + int q = csa->q; + int tcol_nnz = csa->tcol_nnz; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + int i, pos; + double teta; +#ifdef GLP_DEBUG + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); +#endif + /* determine the change of xN[q] in the adjacent basis */ +#ifdef GLP_DEBUG + xassert(tcol_vec[p] != 0.0); +#endif + teta = delta / tcol_vec[p]; + /* set new primal value of xN[q] */ + bbar[p] = get_xN(csa, q) + teta; + /* update primal values of other basic variables */ + if (teta == 0.0) goto done; + for (pos = 1; pos <= tcol_nnz; pos++) + { i = tcol_ind[pos]; +#ifdef GLP_DEBUG + xassert(1 <= i && i <= m); +#endif + if (i != p) + bbar[i] += tcol_vec[i] * teta; + } +done: return; +} + +/*********************************************************************** +* update_gamma - update steepest edge coefficients +* +* This routine updates steepest-edge coefficients for the adjacent +* basis. */ + +static void update_gamma(struct csa *csa) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + char *type = csa->type; + int *head = csa->head; + char *refsp = csa->refsp; + double *gamma = csa->gamma; + int p = csa->p; + int trow_nnz = csa->trow_nnz; + int *trow_ind = csa->trow_ind; + double *trow_vec = csa->trow_vec; + int q = csa->q; + int tcol_nnz = csa->tcol_nnz; + int *tcol_ind = csa->tcol_ind; + double *tcol_vec = csa->tcol_vec; + double *u = csa->work3; + int i, j, k,pos; + double gamma_p, eta_p, pivot, t, t1, t2; +#ifdef GLP_DEBUG + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); +#endif + /* the basis changes, so decrease the count */ + xassert(csa->refct > 0); + csa->refct--; + /* recompute gamma[p] for the current basis more accurately and + compute auxiliary vector u */ +#ifdef GLP_DEBUG + xassert(type[head[p]] != GLP_FR); +#endif + gamma_p = eta_p = (refsp[head[p]] ? 1.0 : 0.0); + for (i = 1; i <= m; i++) u[i] = 0.0; + for (pos = 1; pos <= trow_nnz; pos++) + { j = trow_ind[pos]; +#ifdef GLP_DEBUG + xassert(1 <= j && j <= n); +#endif + k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); + xassert(type[k] != GLP_FX); +#endif + if (!refsp[k]) continue; + t = trow_vec[j]; + gamma_p += t * t; + /* u := u + N[j] * delta[j] * trow[j] */ + if (k <= m) + { /* N[k] = k-j stolbec submatrix I */ + u[k] += t; + } + else + { /* N[k] = k-m-k stolbec (-A) */ + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int beg, end, ptr; + beg = A_ptr[k-m]; + end = A_ptr[k-m+1]; + for (ptr = beg; ptr < end; ptr++) + u[A_ind[ptr]] -= t * A_val[ptr]; + } + } + xassert(csa->valid); + bfd_ftran(csa->bfd, u); + /* update gamma[i] for other basic variables (except xB[p] and + free variables) */ + pivot = tcol_vec[p]; +#ifdef GLP_DEBUG + xassert(pivot != 0.0); +#endif + for (pos = 1; pos <= tcol_nnz; pos++) + { i = tcol_ind[pos]; +#ifdef GLP_DEBUG + xassert(1 <= i && i <= m); +#endif + k = head[i]; +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + /* skip xB[p] */ + if (i == p) continue; + /* skip free basic variable */ + if (type[head[i]] == GLP_FR) + { +#ifdef GLP_DEBUG + xassert(gamma[i] == 1.0); +#endif + continue; + } + /* compute gamma[i] for the adjacent basis */ + t = tcol_vec[i] / pivot; + t1 = gamma[i] + t * t * gamma_p + 2.0 * t * u[i]; + t2 = (refsp[k] ? 1.0 : 0.0) + eta_p * t * t; + gamma[i] = (t1 >= t2 ? t1 : t2); + /* (though gamma[i] can be exact zero, because the reference + space does not include non-basic fixed variables) */ + if (gamma[i] < DBL_EPSILON) gamma[i] = DBL_EPSILON; + } + /* compute gamma[p] for the adjacent basis */ + if (type[head[m+q]] == GLP_FR) + gamma[p] = 1.0; + else + { gamma[p] = gamma_p / (pivot * pivot); + if (gamma[p] < DBL_EPSILON) gamma[p] = DBL_EPSILON; + } + /* if xB[p], which becomes xN[q] in the adjacent basis, is fixed + and belongs to the reference space, remove it from there, and + change all gamma's appropriately */ + k = head[p]; + if (type[k] == GLP_FX && refsp[k]) + { refsp[k] = 0; + for (pos = 1; pos <= tcol_nnz; pos++) + { i = tcol_ind[pos]; + if (i == p) + { if (type[head[m+q]] == GLP_FR) continue; + t = 1.0 / tcol_vec[p]; + } + else + { if (type[head[i]] == GLP_FR) continue; + t = tcol_vec[i] / tcol_vec[p]; + } + gamma[i] -= t * t; + if (gamma[i] < DBL_EPSILON) gamma[i] = DBL_EPSILON; + } + } + return; +} + +#if 1 /* copied from primal */ +/*********************************************************************** +* err_in_bbar - compute maximal relative error in primal solution +* +* This routine returns maximal relative error: +* +* max |beta[i] - bbar[i]| / (1 + |beta[i]|), +* +* where beta and bbar are, respectively, directly computed and the +* current (updated) values of basic variables. +* +* NOTE: The routine is intended only for debugginig purposes. */ + +static double err_in_bbar(struct csa *csa) +{ int m = csa->m; + double *bbar = csa->bbar; + int i; + double e, emax, *beta; + beta = xcalloc(1+m, sizeof(double)); + eval_beta(csa, beta); + emax = 0.0; + for (i = 1; i <= m; i++) + { e = fabs(beta[i] - bbar[i]) / (1.0 + fabs(beta[i])); + if (emax < e) emax = e; + } + xfree(beta); + return emax; +} +#endif + +#if 1 /* copied from primal */ +/*********************************************************************** +* err_in_cbar - compute maximal relative error in dual solution +* +* This routine returns maximal relative error: +* +* max |cost[j] - cbar[j]| / (1 + |cost[j]|), +* +* where cost and cbar are, respectively, directly computed and the +* current (updated) reduced costs of non-basic non-fixed variables. +* +* NOTE: The routine is intended only for debugginig purposes. */ + +static double err_in_cbar(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + char *stat = csa->stat; + double *cbar = csa->cbar; + int j; + double e, emax, cost, *pi; + pi = xcalloc(1+m, sizeof(double)); + eval_pi(csa, pi); + emax = 0.0; + for (j = 1; j <= n; j++) + { if (stat[j] == GLP_NS) continue; + cost = eval_cost(csa, pi, j); + e = fabs(cost - cbar[j]) / (1.0 + fabs(cost)); + if (emax < e) emax = e; + } + xfree(pi); + return emax; +} +#endif + +/*********************************************************************** +* err_in_gamma - compute maximal relative error in steepest edge cff. +* +* This routine returns maximal relative error: +* +* max |gamma'[j] - gamma[j]| / (1 + |gamma'[j]), +* +* where gamma'[j] and gamma[j] are, respectively, directly computed +* and the current (updated) steepest edge coefficients for non-basic +* non-fixed variable x[j]. +* +* NOTE: The routine is intended only for debugginig purposes. */ + +static double err_in_gamma(struct csa *csa) +{ int m = csa->m; + char *type = csa->type; + int *head = csa->head; + double *gamma = csa->gamma; + double *exact = csa->work4; + int i; + double e, emax, temp; + eval_gamma(csa, exact); + emax = 0.0; + for (i = 1; i <= m; i++) + { if (type[head[i]] == GLP_FR) + { xassert(gamma[i] == 1.0); + xassert(exact[i] == 1.0); + continue; + } + temp = exact[i]; + e = fabs(temp - gamma[i]) / (1.0 + fabs(temp)); + if (emax < e) emax = e; + } + return emax; +} + +/*********************************************************************** +* change_basis - change basis header +* +* This routine changes the basis header to make it corresponding to +* the adjacent basis. */ + +static void change_basis(struct csa *csa) +{ int m = csa->m; +#ifdef GLP_DEBUG + int n = csa->n; +#endif + char *type = csa->type; + int *head = csa->head; +#if 1 /* 06/IV-2009 */ + int *bind = csa->bind; +#endif + char *stat = csa->stat; + int p = csa->p; + double delta = csa->delta; + int q = csa->q; + int k; + /* xB[p] leaves the basis, xN[q] enters the basis */ +#ifdef GLP_DEBUG + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); +#endif + /* xB[p] <-> xN[q] */ + k = head[p], head[p] = head[m+q], head[m+q] = k; +#if 1 /* 06/IV-2009 */ + bind[head[p]] = p, bind[head[m+q]] = m + q; +#endif + if (type[k] == GLP_FX) + stat[q] = GLP_NS; + else if (delta > 0.0) + { +#ifdef GLP_DEBUG + xassert(type[k] == GLP_LO || type[k] == GLP_DB); +#endif + stat[q] = GLP_NL; + } + else /* delta < 0.0 */ + { +#ifdef GLP_DEBUG + xassert(type[k] == GLP_UP || type[k] == GLP_DB); +#endif + stat[q] = GLP_NU; + } + return; +} + +/*********************************************************************** +* check_feas - check dual feasibility of basic solution +* +* If the current basic solution is dual feasible within a tolerance, +* this routine returns zero, otherwise it returns non-zero. */ + +static int check_feas(struct csa *csa, double tol_dj) +{ int m = csa->m; + int n = csa->n; + char *orig_type = csa->orig_type; + int *head = csa->head; + double *cbar = csa->cbar; + int j, k; + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (cbar[j] < - tol_dj) + if (orig_type[k] == GLP_LO || orig_type[k] == GLP_FR) + return 1; + if (cbar[j] > + tol_dj) + if (orig_type[k] == GLP_UP || orig_type[k] == GLP_FR) + return 1; + } + return 0; +} + +/*********************************************************************** +* set_aux_bnds - assign auxiliary bounds to variables +* +* This routine assigns auxiliary bounds to variables to construct an +* LP problem solved on phase I. */ + +static void set_aux_bnds(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + char *type = csa->type; + double *lb = csa->lb; + double *ub = csa->ub; + char *orig_type = csa->orig_type; + int *head = csa->head; + char *stat = csa->stat; + double *cbar = csa->cbar; + int j, k; + for (k = 1; k <= m+n; k++) + { switch (orig_type[k]) + { case GLP_FR: +#if 0 + type[k] = GLP_DB, lb[k] = -1.0, ub[k] = +1.0; +#else + /* to force free variables to enter the basis */ + type[k] = GLP_DB, lb[k] = -1e3, ub[k] = +1e3; +#endif + break; + case GLP_LO: + type[k] = GLP_DB, lb[k] = 0.0, ub[k] = +1.0; + break; + case GLP_UP: + type[k] = GLP_DB, lb[k] = -1.0, ub[k] = 0.0; + break; + case GLP_DB: + case GLP_FX: + type[k] = GLP_FX, lb[k] = ub[k] = 0.0; + break; + default: + xassert(orig_type != orig_type); + } + } + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (type[k] == GLP_FX) + stat[j] = GLP_NS; + else if (cbar[j] >= 0.0) + stat[j] = GLP_NL; + else + stat[j] = GLP_NU; + } + return; +} + +/*********************************************************************** +* set_orig_bnds - restore original bounds of variables +* +* This routine restores original types and bounds of variables and +* determines statuses of non-basic variables assuming that the current +* basis is dual feasible. */ + +static void set_orig_bnds(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + char *type = csa->type; + double *lb = csa->lb; + double *ub = csa->ub; + char *orig_type = csa->orig_type; + double *orig_lb = csa->orig_lb; + double *orig_ub = csa->orig_ub; + int *head = csa->head; + char *stat = csa->stat; + double *cbar = csa->cbar; + int j, k; + memcpy(&type[1], &orig_type[1], (m+n) * sizeof(char)); + memcpy(&lb[1], &orig_lb[1], (m+n) * sizeof(double)); + memcpy(&ub[1], &orig_ub[1], (m+n) * sizeof(double)); + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + switch (type[k]) + { case GLP_FR: + stat[j] = GLP_NF; + break; + case GLP_LO: + stat[j] = GLP_NL; + break; + case GLP_UP: + stat[j] = GLP_NU; + break; + case GLP_DB: + if (cbar[j] >= +DBL_EPSILON) + stat[j] = GLP_NL; + else if (cbar[j] <= -DBL_EPSILON) + stat[j] = GLP_NU; + else if (fabs(lb[k]) <= fabs(ub[k])) + stat[j] = GLP_NL; + else + stat[j] = GLP_NU; + break; + case GLP_FX: + stat[j] = GLP_NS; + break; + default: + xassert(type != type); + } + } + return; +} + +/*********************************************************************** +* check_stab - check numerical stability of basic solution +* +* If the current basic solution is dual feasible within a tolerance, +* this routine returns zero, otherwise it returns non-zero. */ + +static int check_stab(struct csa *csa, double tol_dj) +{ int n = csa->n; + char *stat = csa->stat; + double *cbar = csa->cbar; + int j; + for (j = 1; j <= n; j++) + { if (cbar[j] < - tol_dj) + if (stat[j] == GLP_NL || stat[j] == GLP_NF) return 1; + if (cbar[j] > + tol_dj) + if (stat[j] == GLP_NU || stat[j] == GLP_NF) return 1; + } + return 0; +} + +#if 1 /* copied from primal */ +/*********************************************************************** +* eval_obj - compute original objective function +* +* This routine computes the current value of the original objective +* function. */ + +static double eval_obj(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + double *obj = csa->obj; + int *head = csa->head; + double *bbar = csa->bbar; + int i, j, k; + double sum; + sum = obj[0]; + /* walk through the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k > m) + sum += obj[k-m] * bbar[i]; + } + /* walk through the list of non-basic variables */ + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k > m) + sum += obj[k-m] * get_xN(csa, j); + } + return sum; +} +#endif + +/*********************************************************************** +* display - display the search progress +* +* This routine displays some information about the search progress. */ + +static void display(struct csa *csa, const glp_smcp *parm, int spec) +{ int m = csa->m; + int n = csa->n; + double *coef = csa->coef; + char *orig_type = csa->orig_type; + int *head = csa->head; + char *stat = csa->stat; + int phase = csa->phase; + double *bbar = csa->bbar; + double *cbar = csa->cbar; + int i, j, cnt; + double sum; + if (parm->msg_lev < GLP_MSG_ON) goto skip; + if (parm->out_dly > 0 && + 1000.0 * xdifftime(xtime(), csa->tm_beg) < parm->out_dly) + goto skip; + if (csa->it_cnt == csa->it_dpy) goto skip; + if (!spec && csa->it_cnt % parm->out_frq != 0) goto skip; + /* compute the sum of dual infeasibilities */ + sum = 0.0; + if (phase == 1) + { for (i = 1; i <= m; i++) + sum -= coef[head[i]] * bbar[i]; + for (j = 1; j <= n; j++) + sum -= coef[head[m+j]] * get_xN(csa, j); + } + else + { for (j = 1; j <= n; j++) + { if (cbar[j] < 0.0) + if (stat[j] == GLP_NL || stat[j] == GLP_NF) + sum -= cbar[j]; + if (cbar[j] > 0.0) + if (stat[j] == GLP_NU || stat[j] == GLP_NF) + sum += cbar[j]; + } + } + /* determine the number of basic fixed variables */ + cnt = 0; + for (i = 1; i <= m; i++) + if (orig_type[head[i]] == GLP_FX) cnt++; + if (csa->phase == 1) + xprintf(" %6d: %24s infeas = %10.3e (%d)\n", + csa->it_cnt, "", sum, cnt); + else + xprintf("|%6d: obj = %17.9e infeas = %10.3e (%d)\n", + csa->it_cnt, eval_obj(csa), sum, cnt); + csa->it_dpy = csa->it_cnt; +skip: return; +} + +#if 1 /* copied from primal */ +/*********************************************************************** +* store_sol - store basic solution back to the problem object +* +* This routine stores basic solution components back to the problem +* object. */ + +static void store_sol(struct csa *csa, glp_prob *lp, int p_stat, + int d_stat, int ray) +{ int m = csa->m; + int n = csa->n; + double zeta = csa->zeta; + int *head = csa->head; + char *stat = csa->stat; + double *bbar = csa->bbar; + double *cbar = csa->cbar; + int i, j, k; +#ifdef GLP_DEBUG + xassert(lp->m == m); + xassert(lp->n == n); +#endif + /* basis factorization */ +#ifdef GLP_DEBUG + xassert(!lp->valid && lp->bfd == NULL); + xassert(csa->valid && csa->bfd != NULL); +#endif + lp->valid = 1, csa->valid = 0; + lp->bfd = csa->bfd, csa->bfd = NULL; + memcpy(&lp->head[1], &head[1], m * sizeof(int)); + /* basic solution status */ + lp->pbs_stat = p_stat; + lp->dbs_stat = d_stat; + /* objective function value */ + lp->obj_val = eval_obj(csa); + /* simplex iteration count */ + lp->it_cnt = csa->it_cnt; + /* unbounded ray */ + lp->some = ray; + /* basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { GLPROW *row = lp->row[k]; + row->stat = GLP_BS; + row->bind = i; + row->prim = bbar[i] / row->rii; + row->dual = 0.0; + } + else + { GLPCOL *col = lp->col[k-m]; + col->stat = GLP_BS; + col->bind = i; + col->prim = bbar[i] * col->sjj; + col->dual = 0.0; + } + } + /* non-basic variables */ + for (j = 1; j <= n; j++) + { k = head[m+j]; /* x[k] = xN[j] */ +#ifdef GLP_DEBUG + xassert(1 <= k && k <= m+n); +#endif + if (k <= m) + { GLPROW *row = lp->row[k]; + row->stat = stat[j]; + row->bind = 0; +#if 0 + row->prim = get_xN(csa, j) / row->rii; +#else + switch (stat[j]) + { case GLP_NL: + row->prim = row->lb; break; + case GLP_NU: + row->prim = row->ub; break; + case GLP_NF: + row->prim = 0.0; break; + case GLP_NS: + row->prim = row->lb; break; + default: + xassert(stat != stat); + } +#endif + row->dual = (cbar[j] * row->rii) / zeta; + } + else + { GLPCOL *col = lp->col[k-m]; + col->stat = stat[j]; + col->bind = 0; +#if 0 + col->prim = get_xN(csa, j) * col->sjj; +#else + switch (stat[j]) + { case GLP_NL: + col->prim = col->lb; break; + case GLP_NU: + col->prim = col->ub; break; + case GLP_NF: + col->prim = 0.0; break; + case GLP_NS: + col->prim = col->lb; break; + default: + xassert(stat != stat); + } +#endif + col->dual = (cbar[j] / col->sjj) / zeta; + } + } + return; +} +#endif + +/*********************************************************************** +* free_csa - deallocate common storage area +* +* This routine frees all the memory allocated to arrays in the common +* storage area (CSA). */ + +static void free_csa(struct csa *csa) +{ xfree(csa->type); + xfree(csa->lb); + xfree(csa->ub); + xfree(csa->coef); + xfree(csa->orig_type); + xfree(csa->orig_lb); + xfree(csa->orig_ub); + xfree(csa->obj); + xfree(csa->A_ptr); + xfree(csa->A_ind); + xfree(csa->A_val); +#if 1 /* 06/IV-2009 */ + xfree(csa->AT_ptr); + xfree(csa->AT_ind); + xfree(csa->AT_val); +#endif + xfree(csa->head); +#if 1 /* 06/IV-2009 */ + xfree(csa->bind); +#endif + xfree(csa->stat); +#if 0 /* 06/IV-2009 */ + xfree(csa->N_ptr); + xfree(csa->N_len); + xfree(csa->N_ind); + xfree(csa->N_val); +#endif + xfree(csa->bbar); + xfree(csa->cbar); + xfree(csa->refsp); + xfree(csa->gamma); + xfree(csa->trow_ind); + xfree(csa->trow_vec); +#ifdef GLP_LONG_STEP /* 07/IV-2009 */ + xfree(csa->bkpt); +#endif + xfree(csa->tcol_ind); + xfree(csa->tcol_vec); + xfree(csa->work1); + xfree(csa->work2); + xfree(csa->work3); + xfree(csa->work4); + xfree(csa); + return; +} + +/*********************************************************************** +* spx_dual - core LP solver based on the dual simplex method +* +* SYNOPSIS +* +* #include "glpspx.h" +* int spx_dual(glp_prob *lp, const glp_smcp *parm); +* +* DESCRIPTION +* +* The routine spx_dual is a core LP solver based on the two-phase dual +* simplex method. +* +* RETURNS +* +* 0 LP instance has been successfully solved. +* +* GLP_EOBJLL +* Objective lower limit has been reached (maximization). +* +* GLP_EOBJUL +* Objective upper limit has been reached (minimization). +* +* GLP_EITLIM +* Iteration limit has been exhausted. +* +* GLP_ETMLIM +* Time limit has been exhausted. +* +* GLP_EFAIL +* The solver failed to solve LP instance. */ + +int spx_dual(glp_prob *lp, const glp_smcp *parm) +{ struct csa *csa; + int binv_st = 2; + /* status of basis matrix factorization: + 0 - invalid; 1 - just computed; 2 - updated */ + int bbar_st = 0; + /* status of primal values of basic variables: + 0 - invalid; 1 - just computed; 2 - updated */ + int cbar_st = 0; + /* status of reduced costs of non-basic variables: + 0 - invalid; 1 - just computed; 2 - updated */ + int rigorous = 0; + /* rigorous mode flag; this flag is used to enable iterative + refinement on computing pivot rows and columns of the simplex + table */ + int check = 0; + int p_stat, d_stat, ret; +#if 1 /* 16/VII-2013 */ + int degen = 0; + /* degenerated step count */ +#endif + /* allocate and initialize the common storage area */ + csa = alloc_csa(lp); + init_csa(csa, lp); + if (parm->msg_lev >= GLP_MSG_DBG) + xprintf("Objective scale factor = %g\n", csa->zeta); +loop: /* main loop starts here */ + /* compute factorization of the basis matrix */ + if (binv_st == 0) + { ret = invert_B(csa); + if (ret != 0) + { if (parm->msg_lev >= GLP_MSG_ERR) + { xprintf("Error: unable to factorize the basis matrix (%d" + ")\n", ret); + xprintf("Sorry, basis recovery procedure not implemented" + " yet\n"); + } + xassert(!lp->valid && lp->bfd == NULL); + lp->bfd = csa->bfd, csa->bfd = NULL; + lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; + lp->obj_val = 0.0; + lp->it_cnt = csa->it_cnt; + lp->some = 0; + ret = GLP_EFAIL; + goto done; + } + csa->valid = 1; + binv_st = 1; /* just computed */ + /* invalidate basic solution components */ + bbar_st = cbar_st = 0; + } +#if 1 /* 16/VII-2013 */ + if (degen >= 5000 && parm->meth == GLP_DUALP) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: dual degeneracy; switching to primal simp" + "lex\n"); + store_sol(csa, lp, GLP_UNDEF, GLP_UNDEF, 0); + ret = GLP_EFAIL; + goto done; + } +#endif + /* compute reduced costs of non-basic variables */ + if (cbar_st == 0) + { eval_cbar(csa); + cbar_st = 1; /* just computed */ + /* determine the search phase, if not determined yet */ + if (csa->phase == 0) + { if (check_feas(csa, 0.90 * parm->tol_dj) != 0) + { /* current basic solution is dual infeasible */ + /* start searching for dual feasible solution */ + csa->phase = 1; + set_aux_bnds(csa); + } + else + { /* current basic solution is dual feasible */ + /* start searching for optimal solution */ + csa->phase = 2; + set_orig_bnds(csa); + } + xassert(check_stab(csa, parm->tol_dj) == 0); + /* some non-basic double-bounded variables might become + fixed (on phase I) or vice versa (on phase II) */ +#if 0 /* 06/IV-2009 */ + build_N(csa); +#endif + csa->refct = 0; + /* bounds of non-basic variables have been changed, so + invalidate primal values */ + bbar_st = 0; + } + /* make sure that the current basic solution remains dual + feasible */ + if (check_stab(csa, parm->tol_dj) != 0) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: numerical instability (dual simplex, p" + "hase %s)\n", csa->phase == 1 ? "I" : "II"); +#if 1 + if (parm->meth == GLP_DUALP) + { store_sol(csa, lp, GLP_UNDEF, GLP_UNDEF, 0); + ret = GLP_EFAIL; + goto done; + } +#endif + /* restart the search */ + csa->phase = 0; + binv_st = 0; + rigorous = 5; + goto loop; + } + } + xassert(csa->phase == 1 || csa->phase == 2); + /* on phase I we do not need to wait until the current basic + solution becomes primal feasible; it is sufficient to make + sure that all reduced costs have correct signs */ + if (csa->phase == 1 && check_feas(csa, parm->tol_dj) == 0) + { /* the current basis is dual feasible; switch to phase II */ + display(csa, parm, 1); + csa->phase = 2; + if (cbar_st != 1) + { eval_cbar(csa); + cbar_st = 1; + } + set_orig_bnds(csa); +#if 0 /* 06/IV-2009 */ + build_N(csa); +#endif + csa->refct = 0; + bbar_st = 0; + } + /* compute primal values of basic variables */ + if (bbar_st == 0) + { eval_bbar(csa); + if (csa->phase == 2) + csa->bbar[0] = eval_obj(csa); + bbar_st = 1; /* just computed */ + } + /* redefine the reference space, if required */ + switch (parm->pricing) + { case GLP_PT_STD: + break; + case GLP_PT_PSE: + if (csa->refct == 0) reset_refsp(csa); + break; + default: + xassert(parm != parm); + } + /* at this point the basis factorization and all basic solution + components are valid */ + xassert(binv_st && bbar_st && cbar_st); + /* check accuracy of current basic solution components (only for + debugging) */ + if (check) + { double e_bbar = err_in_bbar(csa); + double e_cbar = err_in_cbar(csa); + double e_gamma = + (parm->pricing == GLP_PT_PSE ? err_in_gamma(csa) : 0.0); + xprintf("e_bbar = %10.3e; e_cbar = %10.3e; e_gamma = %10.3e\n", + e_bbar, e_cbar, e_gamma); + xassert(e_bbar <= 1e-5 && e_cbar <= 1e-5 && e_gamma <= 1e-3); + } + /* if the objective has to be maximized, check if it has reached + its lower limit */ + if (csa->phase == 2 && csa->zeta < 0.0 && + parm->obj_ll > -DBL_MAX && csa->bbar[0] <= parm->obj_ll) + { if (bbar_st != 1 || cbar_st != 1) + { if (bbar_st != 1) bbar_st = 0; + if (cbar_st != 1) cbar_st = 0; + goto loop; + } + display(csa, parm, 1); + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("OBJECTIVE LOWER LIMIT REACHED; SEARCH TERMINATED\n" + ); + store_sol(csa, lp, GLP_INFEAS, GLP_FEAS, 0); + ret = GLP_EOBJLL; + goto done; + } + /* if the objective has to be minimized, check if it has reached + its upper limit */ + if (csa->phase == 2 && csa->zeta > 0.0 && + parm->obj_ul < +DBL_MAX && csa->bbar[0] >= parm->obj_ul) + { if (bbar_st != 1 || cbar_st != 1) + { if (bbar_st != 1) bbar_st = 0; + if (cbar_st != 1) cbar_st = 0; + goto loop; + } + display(csa, parm, 1); + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("OBJECTIVE UPPER LIMIT REACHED; SEARCH TERMINATED\n" + ); + store_sol(csa, lp, GLP_INFEAS, GLP_FEAS, 0); + ret = GLP_EOBJUL; + goto done; + } + /* check if the iteration limit has been exhausted */ + if (parm->it_lim < INT_MAX && + csa->it_cnt - csa->it_beg >= parm->it_lim) + { if (csa->phase == 2 && bbar_st != 1 || cbar_st != 1) + { if (csa->phase == 2 && bbar_st != 1) bbar_st = 0; + if (cbar_st != 1) cbar_st = 0; + goto loop; + } + display(csa, parm, 1); + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); + switch (csa->phase) + { case 1: + d_stat = GLP_INFEAS; + set_orig_bnds(csa); + eval_bbar(csa); + break; + case 2: + d_stat = GLP_FEAS; + break; + default: + xassert(csa != csa); + } + store_sol(csa, lp, GLP_INFEAS, d_stat, 0); + ret = GLP_EITLIM; + goto done; + } + /* check if the time limit has been exhausted */ + if (parm->tm_lim < INT_MAX && + 1000.0 * xdifftime(xtime(), csa->tm_beg) >= parm->tm_lim) + { if (csa->phase == 2 && bbar_st != 1 || cbar_st != 1) + { if (csa->phase == 2 && bbar_st != 1) bbar_st = 0; + if (cbar_st != 1) cbar_st = 0; + goto loop; + } + display(csa, parm, 1); + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + switch (csa->phase) + { case 1: + d_stat = GLP_INFEAS; + set_orig_bnds(csa); + eval_bbar(csa); + break; + case 2: + d_stat = GLP_FEAS; + break; + default: + xassert(csa != csa); + } + store_sol(csa, lp, GLP_INFEAS, d_stat, 0); + ret = GLP_ETMLIM; + goto done; + } + /* display the search progress */ + display(csa, parm, 0); + /* choose basic variable xB[p] */ + chuzr(csa, parm->tol_bnd); + if (csa->p == 0) + { if (bbar_st != 1 || cbar_st != 1) + { if (bbar_st != 1) bbar_st = 0; + if (cbar_st != 1) cbar_st = 0; + goto loop; + } + display(csa, parm, 1); + switch (csa->phase) + { case 1: + if (parm->msg_lev >= GLP_MSG_ALL) +#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ + xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n"); +#else + xprintf("LP HAS NO DUAL FEASIBLE SOLUTION\n"); +#endif + set_orig_bnds(csa); + eval_bbar(csa); + p_stat = GLP_INFEAS, d_stat = GLP_NOFEAS; + break; + case 2: + if (parm->msg_lev >= GLP_MSG_ALL) +#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ + xprintf("OPTIMAL SOLUTION FOUND\n"); +#else + xprintf("OPTIMAL LP SOLUTION FOUND\n"); +#endif + p_stat = d_stat = GLP_FEAS; + break; + default: + xassert(csa != csa); + } + store_sol(csa, lp, p_stat, d_stat, 0); + ret = 0; + goto done; + } + /* compute pivot row of the simplex table */ + { double *rho = csa->work4; + eval_rho(csa, rho); + if (rigorous) refine_rho(csa, rho); + eval_trow(csa, rho); + sort_trow(csa, parm->tol_bnd); + } + /* unlike primal simplex there is no need to check accuracy of + the primal value of xB[p] (which might be computed using the + pivot row), since bbar is a result of FTRAN */ +#ifdef GLP_LONG_STEP /* 07/IV-2009 */ + long_step(csa); + if (csa->nbps > 0) + { csa->q = csa->bkpt[csa->nbps].j; + if (csa->delta > 0.0) + csa->new_dq = + csa->bkpt[csa->nbps].t; + else + csa->new_dq = - csa->bkpt[csa->nbps].t; + } + else +#endif + /* choose non-basic variable xN[q] */ + switch (parm->r_test) + { case GLP_RT_STD: + chuzc(csa, 0.0); + break; + case GLP_RT_HAR: + chuzc(csa, 0.30 * parm->tol_dj); + break; + default: + xassert(parm != parm); + } + if (csa->q == 0) + { if (bbar_st != 1 || cbar_st != 1 || !rigorous) + { if (bbar_st != 1) bbar_st = 0; + if (cbar_st != 1) cbar_st = 0; + rigorous = 1; + goto loop; + } + display(csa, parm, 1); + switch (csa->phase) + { case 1: + if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("Error: unable to choose non-basic variable o" + "n phase I\n"); + xassert(!lp->valid && lp->bfd == NULL); + lp->bfd = csa->bfd, csa->bfd = NULL; + lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; + lp->obj_val = 0.0; + lp->it_cnt = csa->it_cnt; + lp->some = 0; + ret = GLP_EFAIL; + break; + case 2: + if (parm->msg_lev >= GLP_MSG_ALL) +#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ + xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); +#else + xprintf("LP HAS UNBOUNDED DUAL SOLUTION\n"); +#endif + store_sol(csa, lp, GLP_NOFEAS, GLP_FEAS, + csa->head[csa->p]); + ret = 0; + break; + default: + xassert(csa != csa); + } + goto done; + } + /* check if the pivot element is acceptable */ + { double piv = csa->trow_vec[csa->q]; + double eps = 1e-5 * (1.0 + 0.01 * csa->trow_max); + if (fabs(piv) < eps) + { if (parm->msg_lev >= GLP_MSG_DBG) + xprintf("piv = %.12g; eps = %g\n", piv, eps); + if (!rigorous) + { rigorous = 5; + goto loop; + } + } + } + /* now xN[q] and xB[p] have been chosen anyhow */ + /* compute pivot column of the simplex table */ + eval_tcol(csa); + if (rigorous) refine_tcol(csa); + /* accuracy check based on the pivot element */ + { double piv1 = csa->tcol_vec[csa->p]; /* more accurate */ + double piv2 = csa->trow_vec[csa->q]; /* less accurate */ + xassert(piv1 != 0.0); + if (fabs(piv1 - piv2) > 1e-8 * (1.0 + fabs(piv1)) || + !(piv1 > 0.0 && piv2 > 0.0 || piv1 < 0.0 && piv2 < 0.0)) + { if (parm->msg_lev >= GLP_MSG_DBG) + xprintf("piv1 = %.12g; piv2 = %.12g\n", piv1, piv2); + if (binv_st != 1 || !rigorous) + { if (binv_st != 1) binv_st = 0; + rigorous = 5; + goto loop; + } + /* (not a good idea; should be revised later) */ + if (csa->tcol_vec[csa->p] == 0.0) + { csa->tcol_nnz++; + xassert(csa->tcol_nnz <= csa->m); + csa->tcol_ind[csa->tcol_nnz] = csa->p; + } + csa->tcol_vec[csa->p] = piv2; + } + } + /* update primal values of basic variables */ +#ifdef GLP_LONG_STEP /* 07/IV-2009 */ + if (csa->nbps > 0) + { int kk, j, k; + for (kk = 1; kk < csa->nbps; kk++) + { if (csa->bkpt[kk].t >= csa->bkpt[csa->nbps].t) continue; + j = csa->bkpt[kk].j; + k = csa->head[csa->m + j]; + xassert(csa->type[k] == GLP_DB); + if (csa->stat[j] == GLP_NL) + csa->stat[j] = GLP_NU; + else + csa->stat[j] = GLP_NL; + } + } + bbar_st = 0; +#else + update_bbar(csa); + if (csa->phase == 2) + csa->bbar[0] += (csa->cbar[csa->q] / csa->zeta) * + (csa->delta / csa->tcol_vec[csa->p]); + bbar_st = 2; /* updated */ +#endif + /* update reduced costs of non-basic variables */ + update_cbar(csa); + cbar_st = 2; /* updated */ + /* update steepest edge coefficients */ + switch (parm->pricing) + { case GLP_PT_STD: + break; + case GLP_PT_PSE: + if (csa->refct > 0) update_gamma(csa); + break; + default: + xassert(parm != parm); + } + /* update factorization of the basis matrix */ + ret = update_B(csa, csa->p, csa->head[csa->m+csa->q]); + if (ret == 0) + binv_st = 2; /* updated */ + else + { csa->valid = 0; + binv_st = 0; /* invalid */ + } +#if 0 /* 06/IV-2009 */ + /* update matrix N */ + del_N_col(csa, csa->q, csa->head[csa->m+csa->q]); + if (csa->type[csa->head[csa->p]] != GLP_FX) + add_N_col(csa, csa->q, csa->head[csa->p]); +#endif + /* change the basis header */ + change_basis(csa); + /* iteration complete */ + csa->it_cnt++; +#if 1 /* 16/VII-2013 */ + if (-1e-9 <= csa->new_dq && csa->new_dq <= +1e-9) + { /* degenerated step */ + degen++; + } + else + { /* non-degenerated step */ + degen = 0; + } +#endif + if (rigorous > 0) rigorous--; + goto loop; +done: /* deallocate the common storage area */ + free_csa(csa); + /* return to the calling program */ + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpsql.c b/resources/3rdparty/glpk-4.53/src/glpsql.c new file mode 100644 index 000000000..8cd5cd08b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpsql.c @@ -0,0 +1,1644 @@ +/* glpsql.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Author: Heinrich Schuchardt <xypron.glpk@gmx.de>. +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "glpmpl.h" +#include "glpsql.h" + +#ifdef ODBC_DLNAME +#define HAVE_ODBC +#define libodbc ODBC_DLNAME +#define h_odbc (get_env_ptr()->h_odbc) +#endif + +#ifdef MYSQL_DLNAME +#define HAVE_MYSQL +#define libmysql MYSQL_DLNAME +#define h_mysql (get_env_ptr()->h_mysql) +#endif + +static void *db_iodbc_open_int(TABDCA *dca, int mode, const char + **sqllines); +static void *db_mysql_open_int(TABDCA *dca, int mode, const char + **sqllines); + +/**********************************************************************/ + +#if defined(HAVE_ODBC) || defined(HAVE_MYSQL) + +#define SQL_FIELD_MAX 100 +/* maximal field count */ + +#define SQL_FDLEN_MAX 255 +/* maximal field length */ + +/*********************************************************************** +* NAME +* +* args_concat - concatenate arguments +* +* SYNOPSIS +* +* static char **args_concat(TABDCA *dca); +* +* DESCRIPTION +* +* The arguments passed in dca are SQL statements. A SQL statement may +* be split over multiple arguments. The last argument of a SQL +* statement will be terminated with a semilocon. Each SQL statement is +* merged into a single zero terminated string. Boundaries between +* arguments are replaced by space. +* +* RETURNS +* +* Buffer with SQL statements */ + +static char **args_concat(TABDCA *dca) +{ + const char *arg; + int i; + int j; + int j0; + int j1; + int len; + int lentot; + int narg; + int nline = 0; + void *ret; + char **sqllines = NULL; + + narg = mpl_tab_num_args(dca); + /* The SQL statements start with argument 3. */ + if (narg < 3) + return NULL; + /* Count the SQL statements */ + for (j = 3; j <= narg; j++) + { + arg = mpl_tab_get_arg(dca, j); + len = strlen(arg); + if (arg[len-1] == ';' || j == narg) + nline ++; + } + /* Allocate string buffer. */ + sqllines = (char **) xmalloc((nline+1) * sizeof(char **)); + /* Join arguments */ + sqllines[0] = NULL; + j0 = 3; + i = 0; + lentot = 0; + for (j = 3; j <= narg; j++) + { + arg = mpl_tab_get_arg(dca, j); + len = strlen(arg); + /* add length of part */ + lentot += len; + /* add length of space separating parts or 0x00 at end of SQL + statement */ + lentot++; + if (arg[len-1] == ';' || j == narg) + { /* Join arguments for a single SQL statement */ + sqllines[i] = xmalloc(lentot); + sqllines[i+1] = NULL; + sqllines[i][0] = 0x00; + for (j1 = j0; j1 <= j; j1++) + { if(j1>j0) + strcat(sqllines[i], " "); + strcat(sqllines[i], mpl_tab_get_arg(dca, j1)); + } + len = strlen(sqllines[i]); + if (sqllines[i][len-1] == ';') + sqllines[i][len-1] = 0x00; + j0 = j+1; + i++; + lentot = 0; + } + } + return sqllines; +} + +/*********************************************************************** +* NAME +* +* free_buffer - free multiline string buffer +* +* SYNOPSIS +* +* static void free_buffer(char **buf); +* +* DESCRIPTION +* +* buf is a list of strings terminated by NULL. +* The memory for the strings and for the list is released. */ + +static void free_buffer(char **buf) +{ int i; + + for(i = 0; buf[i] != NULL; i++) + xfree(buf[i]); + xfree(buf); +} + +static int db_escaped_string_length(const char* from) +/* length of escaped string */ +{ + int count; + const char *pointer; + + for (pointer = from, count = 0; *pointer != (char) '\0'; pointer++, + count++) + { + switch (*pointer) + { + case '\'': + count++; + break; + } + } + + return count; +} + +static int db_escape_string (char *to, const char *from) +/* escape string*/ +{ + const char *source = from; + char *target = to; + unsigned int remaining; + + remaining = strlen(from); + + if (to == NULL) + to = (char *) (from + remaining); + + while (remaining > 0) + { + switch (*source) + { + case '\'': + *target = '\''; + target++; + *target = '\''; + break; + + default: + *target = *source; + } + source++; + target++; + remaining--; + } + + /* Write the terminating NUL character. */ + *target = '\0'; + + return target - to; +} + +static char *db_generate_select_stmt(TABDCA *dca) +/* generate select statement */ +{ + char *arg; + char const *field; + char *query; + int j; + int narg; + int nf; + int total; + + total = 50; + nf = mpl_tab_num_flds(dca); + narg = mpl_tab_num_args(dca); + for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) + { + field = mpl_tab_get_name(dca, j); + total += strlen(field); + total += 2; + } + arg = (char *) mpl_tab_get_arg(dca, narg); + total += strlen(arg); + query = xmalloc( total * sizeof(char)); + strcpy (query, "SELECT "); + for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) + { + field = mpl_tab_get_name(dca, j); + strcat(query, field); + if ( j < nf ) + strcat(query, ", "); + } + strcat(query, " FROM "); + strcat(query, arg); + return query; +} + +static char *db_generate_insert_stmt(TABDCA *dca) +/* generate insert statement */ +{ + char *arg; + char const *field; + char *query; + int j; + int narg; + int nf; + int total; + + total = 50; + nf = mpl_tab_num_flds(dca); + narg = mpl_tab_num_args(dca); + for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) + { + field = mpl_tab_get_name(dca, j); + total += strlen(field); + total += 5; + } + arg = (char *) mpl_tab_get_arg(dca, narg); + total += strlen(arg); + query = xmalloc( (total+1) * sizeof(char)); + strcpy (query, "INSERT INTO "); + strcat(query, arg); + strcat(query, " ( "); + for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) + { + field = mpl_tab_get_name(dca, j); + strcat(query, field); + if ( j < nf ) + strcat(query, ", "); + } + strcat(query, " ) VALUES ( "); + for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) + { + strcat(query, "?"); + if ( j < nf ) + strcat(query, ", "); + } + strcat(query, " )"); + return query; +} + +#endif + +/**********************************************************************/ + +#ifndef HAVE_ODBC + +void *db_iodbc_open(TABDCA *dca, int mode) +{ xassert(dca == dca); + xassert(mode == mode); + xprintf("iODBC table driver not supported\n"); + return NULL; +} + +int db_iodbc_read(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +int db_iodbc_write(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +int db_iodbc_close(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +#else + +#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__) +#include <windows.h> +#endif + +#include <sql.h> +#include <sqlext.h> + +struct db_odbc +{ + int mode; /*'R' = Read, 'W' = Write*/ + SQLHDBC hdbc; /*connection handle*/ + SQLHENV henv; /*environment handle*/ + SQLHSTMT hstmt; /*statement handle*/ + SQLSMALLINT nresultcols; /* columns in result*/ + SQLULEN collen[SQL_FIELD_MAX+1]; + SQLLEN outlen[SQL_FIELD_MAX+1]; + SQLSMALLINT coltype[SQL_FIELD_MAX+1]; + SQLCHAR data[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1]; +#if 1 /* 12/I-2014 */ + SQLDOUBLE datanum[SQL_FIELD_MAX+1]; +#endif + SQLCHAR colname[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1]; + int isnumeric[SQL_FIELD_MAX+1]; + int nf; + /* number of fields in the csv file */ + int ref[1+SQL_FIELD_MAX]; + /* ref[k] = k', if k-th field of the csv file corresponds to + k'-th field in the table statement; if ref[k] = 0, k-th field + of the csv file is ignored */ + SQLCHAR *query; + /* query generated by db_iodbc_open */ +}; + +SQLRETURN SQL_API dl_SQLAllocHandle ( + SQLSMALLINT HandleType, + SQLHANDLE InputHandle, + SQLHANDLE *OutputHandle) +{ + typedef SQLRETURN SQL_API ep_SQLAllocHandle( + SQLSMALLINT HandleType, + SQLHANDLE InputHandle, + SQLHANDLE *OutputHandle); + + ep_SQLAllocHandle *fn; + fn = (ep_SQLAllocHandle *) xdlsym(h_odbc, "SQLAllocHandle"); + xassert(fn != NULL); + return (*fn)(HandleType, InputHandle, OutputHandle); +} + +SQLRETURN SQL_API dl_SQLBindCol ( + SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, + SQLSMALLINT TargetType, + SQLPOINTER TargetValue, + SQLLEN BufferLength, + SQLLEN *StrLen_or_Ind) +{ + typedef SQLRETURN SQL_API ep_SQLBindCol( + SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, + SQLSMALLINT TargetType, + SQLPOINTER TargetValue, + SQLLEN BufferLength, + SQLLEN *StrLen_or_Ind); + ep_SQLBindCol *fn; + fn = (ep_SQLBindCol *) xdlsym(h_odbc, "SQLBindCol"); + xassert(fn != NULL); + return (*fn)(StatementHandle, ColumnNumber, TargetType, + TargetValue, BufferLength, StrLen_or_Ind); +} + +SQLRETURN SQL_API dl_SQLCloseCursor ( + SQLHSTMT StatementHandle) +{ + typedef SQLRETURN SQL_API ep_SQLCloseCursor ( + SQLHSTMT StatementHandle); + + ep_SQLCloseCursor *fn; + fn = (ep_SQLCloseCursor *) xdlsym(h_odbc, "SQLCloseCursor"); + xassert(fn != NULL); + return (*fn)(StatementHandle); +} + + +SQLRETURN SQL_API dl_SQLDisconnect ( + SQLHDBC ConnectionHandle) +{ + typedef SQLRETURN SQL_API ep_SQLDisconnect( + SQLHDBC ConnectionHandle); + + ep_SQLDisconnect *fn; + fn = (ep_SQLDisconnect *) xdlsym(h_odbc, "SQLDisconnect"); + xassert(fn != NULL); + return (*fn)(ConnectionHandle); +} + +SQLRETURN SQL_API dl_SQLDriverConnect ( + SQLHDBC hdbc, + SQLHWND hwnd, + SQLCHAR *szConnStrIn, + SQLSMALLINT cbConnStrIn, + SQLCHAR *szConnStrOut, + SQLSMALLINT cbConnStrOutMax, + SQLSMALLINT *pcbConnStrOut, + SQLUSMALLINT fDriverCompletion) +{ + typedef SQLRETURN SQL_API ep_SQLDriverConnect( + SQLHDBC hdbc, + SQLHWND hwnd, + SQLCHAR * szConnStrIn, + SQLSMALLINT cbConnStrIn, + SQLCHAR * szConnStrOut, + SQLSMALLINT cbConnStrOutMax, + SQLSMALLINT * pcbConnStrOut, + SQLUSMALLINT fDriverCompletion); + + ep_SQLDriverConnect *fn; + fn = (ep_SQLDriverConnect *) xdlsym(h_odbc, "SQLDriverConnect"); + xassert(fn != NULL); + return (*fn)(hdbc, hwnd, szConnStrIn, cbConnStrIn, szConnStrOut, + cbConnStrOutMax, pcbConnStrOut, fDriverCompletion); +} + +SQLRETURN SQL_API dl_SQLEndTran ( + SQLSMALLINT HandleType, + SQLHANDLE Handle, + SQLSMALLINT CompletionType) +{ + typedef SQLRETURN SQL_API ep_SQLEndTran ( + SQLSMALLINT HandleType, + SQLHANDLE Handle, + SQLSMALLINT CompletionType); + + ep_SQLEndTran *fn; + fn = (ep_SQLEndTran *) xdlsym(h_odbc, "SQLEndTran"); + xassert(fn != NULL); + return (*fn)(HandleType, Handle, CompletionType); +} + +SQLRETURN SQL_API dl_SQLExecDirect ( + SQLHSTMT StatementHandle, + SQLCHAR * StatementText, + SQLINTEGER TextLength) +{ + typedef SQLRETURN SQL_API ep_SQLExecDirect ( + SQLHSTMT StatementHandle, + SQLCHAR * StatementText, + SQLINTEGER TextLength); + + ep_SQLExecDirect *fn; + fn = (ep_SQLExecDirect *) xdlsym(h_odbc, "SQLExecDirect"); + xassert(fn != NULL); + return (*fn)(StatementHandle, StatementText, TextLength); +} + +SQLRETURN SQL_API dl_SQLFetch ( + SQLHSTMT StatementHandle) +{ + typedef SQLRETURN SQL_API ep_SQLFetch ( + SQLHSTMT StatementHandle); + + ep_SQLFetch *fn; + fn = (ep_SQLFetch*) xdlsym(h_odbc, "SQLFetch"); + xassert(fn != NULL); + return (*fn)(StatementHandle); +} + +SQLRETURN SQL_API dl_SQLFreeHandle ( + SQLSMALLINT HandleType, + SQLHANDLE Handle) +{ + typedef SQLRETURN SQL_API ep_SQLFreeHandle ( + SQLSMALLINT HandleType, + SQLHANDLE Handle); + + ep_SQLFreeHandle *fn; + fn = (ep_SQLFreeHandle *) xdlsym(h_odbc, "SQLFreeHandle"); + xassert(fn != NULL); + return (*fn)(HandleType, Handle); +} + +SQLRETURN SQL_API dl_SQLDescribeCol ( + SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, + SQLCHAR * ColumnName, + SQLSMALLINT BufferLength, + SQLSMALLINT * NameLength, + SQLSMALLINT * DataType, + SQLULEN * ColumnSize, + SQLSMALLINT * DecimalDigits, + SQLSMALLINT * Nullable) +{ + typedef SQLRETURN SQL_API ep_SQLDescribeCol ( + SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, + SQLCHAR *ColumnName, + SQLSMALLINT BufferLength, + SQLSMALLINT *NameLength, + SQLSMALLINT *DataType, + SQLULEN *ColumnSize, + SQLSMALLINT *DecimalDigits, + SQLSMALLINT *Nullable); + + ep_SQLDescribeCol *fn; + fn = (ep_SQLDescribeCol *) xdlsym(h_odbc, "SQLDescribeCol"); + xassert(fn != NULL); + return (*fn)(StatementHandle, ColumnNumber, ColumnName, + BufferLength, NameLength, + DataType, ColumnSize, DecimalDigits, Nullable); +} + +SQLRETURN SQL_API dl_SQLGetDiagRec ( + SQLSMALLINT HandleType, + SQLHANDLE Handle, + SQLSMALLINT RecNumber, + SQLCHAR *Sqlstate, + SQLINTEGER *NativeError, + SQLCHAR *MessageText, + SQLSMALLINT BufferLength, + SQLSMALLINT *TextLength) +{ + typedef SQLRETURN SQL_API ep_SQLGetDiagRec ( + SQLSMALLINT HandleType, + SQLHANDLE Handle, + SQLSMALLINT RecNumber, + SQLCHAR *Sqlstate, + SQLINTEGER *NativeError, + SQLCHAR *MessageText, + SQLSMALLINT BufferLength, + SQLSMALLINT *TextLength); + + ep_SQLGetDiagRec *fn; + fn = (ep_SQLGetDiagRec *) xdlsym(h_odbc, "SQLGetDiagRec"); + xassert(fn != NULL); + return (*fn)(HandleType, Handle, RecNumber, Sqlstate, + NativeError, MessageText, BufferLength, TextLength); +} + +SQLRETURN SQL_API dl_SQLGetInfo ( + SQLHDBC ConnectionHandle, + SQLUSMALLINT InfoType, + SQLPOINTER InfoValue, + SQLSMALLINT BufferLength, + SQLSMALLINT *StringLength) +{ + typedef SQLRETURN SQL_API ep_SQLGetInfo ( + SQLHDBC ConnectionHandle, + SQLUSMALLINT InfoType, + SQLPOINTER InfoValue, + SQLSMALLINT BufferLength, + SQLSMALLINT *StringLength); + + ep_SQLGetInfo *fn; + fn = (ep_SQLGetInfo *) xdlsym(h_odbc, "SQLGetInfo"); + xassert(fn != NULL); + return (*fn)(ConnectionHandle, InfoType, InfoValue, BufferLength, + StringLength); +} + +SQLRETURN SQL_API dl_SQLNumResultCols ( + SQLHSTMT StatementHandle, + SQLSMALLINT *ColumnCount) +{ + typedef SQLRETURN SQL_API ep_SQLNumResultCols ( + SQLHSTMT StatementHandle, + SQLSMALLINT *ColumnCount); + + ep_SQLNumResultCols *fn; + fn = (ep_SQLNumResultCols *) xdlsym(h_odbc, "SQLNumResultCols"); + xassert(fn != NULL); + return (*fn)(StatementHandle, ColumnCount); +} + +SQLRETURN SQL_API dl_SQLSetConnectAttr ( + SQLHDBC ConnectionHandle, + SQLINTEGER Attribute, + SQLPOINTER Value, + SQLINTEGER StringLength) +{ + typedef SQLRETURN SQL_API ep_SQLSetConnectAttr ( + SQLHDBC ConnectionHandle, + SQLINTEGER Attribute, + SQLPOINTER Value, + SQLINTEGER StringLength); + + ep_SQLSetConnectAttr *fn; + fn = (ep_SQLSetConnectAttr *) xdlsym(h_odbc, "SQLSetConnectAttr"); + xassert(fn != NULL); + return (*fn)(ConnectionHandle, Attribute, Value, StringLength); +} + +SQLRETURN SQL_API dl_SQLSetEnvAttr ( + SQLHENV EnvironmentHandle, + SQLINTEGER Attribute, + SQLPOINTER Value, + SQLINTEGER StringLength) +{ + typedef SQLRETURN SQL_API ep_SQLSetEnvAttr ( + SQLHENV EnvironmentHandle, + SQLINTEGER Attribute, + SQLPOINTER Value, + SQLINTEGER StringLength); + + ep_SQLSetEnvAttr *fn; + fn = (ep_SQLSetEnvAttr *) xdlsym(h_odbc, "SQLSetEnvAttr"); + xassert(fn != NULL); + return (*fn)(EnvironmentHandle, Attribute, Value, StringLength); +} + +static void extract_error( + char *fn, + SQLHANDLE handle, + SQLSMALLINT type); + +static int is_numeric( + SQLSMALLINT coltype); + +/*********************************************************************** +* NAME +* +* db_iodbc_open - open connection to ODBC data base +* +* SYNOPSIS +* +* #include "glpsql.h" +* void *db_iodbc_open(TABDCA *dca, int mode); +* +* DESCRIPTION +* +* The routine db_iodbc_open opens a connection to an ODBC data base. +* It then executes the sql statements passed. +* +* In the case of table read the SELECT statement is executed. +* +* In the case of table write the INSERT statement is prepared. +* RETURNS +* +* The routine returns a pointer to data storage area created. */ +void *db_iodbc_open(TABDCA *dca, int mode) +{ void *ret; + char **sqllines; + + sqllines = args_concat(dca); + if (sqllines == NULL) + { xprintf("Missing arguments in table statement.\n" + "Please, supply table driver, dsn, and query.\n"); + return NULL; + } + ret = db_iodbc_open_int(dca, mode, (const char **) sqllines); + free_buffer(sqllines); + return ret; +} + +static void *db_iodbc_open_int(TABDCA *dca, int mode, const char + **sqllines) +{ + struct db_odbc *sql; + SQLRETURN ret; + SQLCHAR FAR *dsn; + SQLCHAR info[256]; + SQLSMALLINT colnamelen; + SQLSMALLINT nullable; + SQLSMALLINT scale; + const char *arg; + int narg; + int i, j; + int total; + + if (libodbc == NULL) + { + xprintf("No loader for shared ODBC library available\n"); + return NULL; + } + + if (h_odbc == NULL) + { + h_odbc = xdlopen(libodbc); + if (h_odbc == NULL) + { xprintf("unable to open library %s\n", libodbc); + xprintf("%s\n", get_err_msg()); + return NULL; + } + } + + sql = (struct db_odbc *) xmalloc(sizeof(struct db_odbc)); + if (sql == NULL) + return NULL; + + sql->mode = mode; + sql->hdbc = NULL; + sql->henv = NULL; + sql->hstmt = NULL; + sql->query = NULL; + narg = mpl_tab_num_args(dca); + + dsn = (SQLCHAR FAR *) mpl_tab_get_arg(dca, 2); + /* allocate an environment handle */ + ret = dl_SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, + &(sql->henv)); + /* set attribute to enable application to run as ODBC 3.0 + application */ + ret = dl_SQLSetEnvAttr(sql->henv, SQL_ATTR_ODBC_VERSION, + (void *) SQL_OV_ODBC3, 0); + /* allocate a connection handle */ + ret = dl_SQLAllocHandle(SQL_HANDLE_DBC, sql->henv, &(sql->hdbc)); + /* connect */ + ret = dl_SQLDriverConnect(sql->hdbc, NULL, dsn, SQL_NTS, NULL, 0, + NULL, SQL_DRIVER_COMPLETE); + if (SQL_SUCCEEDED(ret)) + { /* output information about data base connection */ + xprintf("Connected to "); + dl_SQLGetInfo(sql->hdbc, SQL_DBMS_NAME, (SQLPOINTER)info, + sizeof(info), NULL); + xprintf("%s ", info); + dl_SQLGetInfo(sql->hdbc, SQL_DBMS_VER, (SQLPOINTER)info, + sizeof(info), NULL); + xprintf("%s - ", info); + dl_SQLGetInfo(sql->hdbc, SQL_DATABASE_NAME, (SQLPOINTER)info, + sizeof(info), NULL); + xprintf("%s\n", info); + } + else + { /* describe error */ + xprintf("Failed to connect\n"); + extract_error("SQLDriverConnect", sql->hdbc, SQL_HANDLE_DBC); + dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); + xfree(sql); + return NULL; + } + /* set AUTOCOMMIT on*/ + ret = dl_SQLSetConnectAttr(sql->hdbc, SQL_ATTR_AUTOCOMMIT, + (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0); + /* allocate a statement handle */ + ret = dl_SQLAllocHandle(SQL_HANDLE_STMT, sql->hdbc, &(sql->hstmt)); + + /* initialization queries */ + for(j = 0; sqllines[j+1] != NULL; j++) + { + sql->query = (SQLCHAR *) sqllines[j]; + xprintf("%s\n", sql->query); + ret = dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS); + switch (ret) + { + case SQL_SUCCESS: + case SQL_SUCCESS_WITH_INFO: + case SQL_NO_DATA_FOUND: + break; + default: + xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n", + sql->query); + extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT); + dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); + dl_SQLDisconnect(sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); + xfree(sql); + return NULL; + } + /* commit statement */ + dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT); + } + + if ( sql->mode == 'R' ) + { sql->nf = mpl_tab_num_flds(dca); + for(j = 0; sqllines[j] != NULL; j++) + arg = sqllines[j]; + total = strlen(arg); + if (total > 7 && 0 == strncmp(arg, "SELECT ", 7)) + { + total = strlen(arg); + sql->query = xmalloc( (total+1) * sizeof(char)); + strcpy (sql->query, arg); + } + else + { + sql->query = db_generate_select_stmt(dca); + } + xprintf("%s\n", sql->query); + if (dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS) != + SQL_SUCCESS) + { + xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n", sql->query); + extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT); + dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); + dl_SQLDisconnect(sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); + xfree(sql->query); + xfree(sql); + return NULL; + } + xfree(sql->query); + /* determine number of result columns */ + ret = dl_SQLNumResultCols(sql->hstmt, &sql->nresultcols); + total = sql->nresultcols; + if (total > SQL_FIELD_MAX) + { xprintf("db_iodbc_open: Too many fields (> %d) in query.\n" + "\"%s\"\n", SQL_FIELD_MAX, sql->query); + dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); + dl_SQLDisconnect(sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); + xfree(sql->query); + return NULL; + } + for (i = 1; i <= total; i++) + { /* return a set of attributes for a column */ + ret = dl_SQLDescribeCol(sql->hstmt, (SQLSMALLINT) i, + sql->colname[i], SQL_FDLEN_MAX, + &colnamelen, &(sql->coltype[i]), &(sql->collen[i]), &scale, + &nullable); + sql->isnumeric[i] = is_numeric(sql->coltype[i]); + /* bind columns to program vars, converting all types to CHAR*/ + if (sql->isnumeric[i]) +#if 0 /* 12/I-2014 */ + { dl_SQLBindCol(sql->hstmt, i, SQL_DOUBLE, sql->data[i], +#else + { dl_SQLBindCol(sql->hstmt, i, SQL_DOUBLE, &sql->datanum[i], +#endif + SQL_FDLEN_MAX, &(sql->outlen[i])); + } else + { dl_SQLBindCol(sql->hstmt, i, SQL_CHAR, sql->data[i], + SQL_FDLEN_MAX, &(sql->outlen[i])); + } + for (j = sql->nf; j >= 1; j--) + { if (strcmp(mpl_tab_get_name(dca, j), sql->colname[i]) == 0) + break; + } + sql->ref[i] = j; + } + } + else if ( sql->mode == 'W' ) + { for(j = 0; sqllines[j] != NULL; j++) + arg = sqllines[j]; + if ( NULL != strchr(arg, '?') ) + { + total = strlen(arg); + sql->query = xmalloc( (total+1) * sizeof(char)); + strcpy (sql->query, arg); + } + else + { + sql->query = db_generate_insert_stmt(dca); + } + xprintf("%s\n", sql->query); + } + return sql; +} + +int db_iodbc_read(TABDCA *dca, void *link) +{ + struct db_odbc *sql; + SQLRETURN ret; + char buf[SQL_FDLEN_MAX+1]; + int i; + int len; + double num; + + sql = (struct db_odbc *) link; + + xassert(sql != NULL); + xassert(sql->mode == 'R'); + + ret=dl_SQLFetch(sql->hstmt); + if (ret== SQL_ERROR) + return -1; + if (ret== SQL_NO_DATA_FOUND) + return -1; /*EOF*/ + for (i=1; i <= sql->nresultcols; i++) + { + if (sql->ref[i] > 0) + { + len = sql->outlen[i]; + if (len != SQL_NULL_DATA) + { + if (sql->isnumeric[i]) + { mpl_tab_set_num(dca, sql->ref[i], +#if 0 /* 12/I-2014 */ + *((const double *) sql->data[i])); +#else + (const double) sql->datanum[i]); +#endif + } + else + { if (len > SQL_FDLEN_MAX) + len = SQL_FDLEN_MAX; + else if (len < 0) + len = 0; + strncpy(buf, (const char *) sql->data[i], len); + buf[len] = 0x00; + mpl_tab_set_str(dca, sql->ref[i], strtrim(buf)); + } + } + } + } + return 0; +} + +int db_iodbc_write(TABDCA *dca, void *link) +{ + struct db_odbc *sql; + char *part; + char *query; + char *template; + char num[50]; + int k; + int len; + int nf; + + sql = (struct db_odbc *) link; + xassert(sql != NULL); + xassert(sql->mode == 'W'); + + len = strlen(sql->query); + template = (char *) xmalloc( (len + 1) * sizeof(char) ); + strcpy(template, sql->query); + + nf = mpl_tab_num_flds(dca); + for (k = 1; k <= nf; k++) + { switch (mpl_tab_get_type(dca, k)) + { case 'N': + len += 20; + break; + case 'S': + len += db_escaped_string_length(mpl_tab_get_str(dca, k)); + len += 2; + break; + default: + xassert(dca != dca); + } + } + query = xmalloc( (len + 1 ) * sizeof(char) ); + query[0] = 0x00; + for (k = 1, part = strtok (template, "?"); (part != NULL); + part = strtok (NULL, "?"), k++) + { + if (k > nf) break; + strcat( query, part ); + switch (mpl_tab_get_type(dca, k)) + { case 'N': +#if 0 /* 02/XI-2010 by xypron */ + sprintf(num, "%-18g",mpl_tab_get_num(dca, k)); +#else + sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); +#endif + strcat( query, num ); + break; + case 'S': + strcat( query, "'"); + db_escape_string( query + strlen(query), + mpl_tab_get_str(dca, k) ); + strcat( query, "'"); + break; + default: + xassert(dca != dca); + } + } + if (part != NULL) + strcat(query, part); + if (dl_SQLExecDirect(sql->hstmt, (SQLCHAR *) query, SQL_NTS) + != SQL_SUCCESS) + { + xprintf("db_iodbc_write: Query\n\"%s\"\nfailed.\n", query); + extract_error("SQLExecDirect", sql->hdbc, SQL_HANDLE_DBC); + xfree(query); + xfree(template); + return 1; + } + + xfree(query); + xfree(template); + return 0; +} + +int db_iodbc_close(TABDCA *dca, void *link) +{ + struct db_odbc *sql; + + sql = (struct db_odbc *) link; + xassert(sql != NULL); + /* Commit */ + if ( sql->mode == 'W' ) + dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT); + if ( sql->mode == 'R' ) + dl_SQLCloseCursor(sql->hstmt); + + dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); + dl_SQLDisconnect(sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); + if ( sql->mode == 'W' ) + xfree(sql->query); + xfree(sql); + dca->link = NULL; + return 0; +} + +static void extract_error( + char *fn, + SQLHANDLE handle, + SQLSMALLINT type) +{ + SQLINTEGER i = 0; + SQLINTEGER native; + SQLCHAR state[ 7 ]; + SQLCHAR text[256]; + SQLSMALLINT len; + SQLRETURN ret; + + xprintf("\nThe driver reported the following diagnostics whilst " + "running %s\n", fn); + + do + { + ret = dl_SQLGetDiagRec(type, handle, ++i, state, &native, text, + sizeof(text), &len ); + if (SQL_SUCCEEDED(ret)) + xprintf("%s:%ld:%ld:%s\n", state, i, native, text); + } + while( ret == SQL_SUCCESS ); +} + +static int is_numeric(SQLSMALLINT coltype) +{ + int ret = 0; + switch (coltype) + { + case SQL_DECIMAL: + case SQL_NUMERIC: + case SQL_SMALLINT: + case SQL_INTEGER: + case SQL_REAL: + case SQL_FLOAT: + case SQL_DOUBLE: + case SQL_TINYINT: + case SQL_BIGINT: + ret = 1; + break; + } + return ret; +} + +#endif + +/**********************************************************************/ + +#ifndef HAVE_MYSQL + +void *db_mysql_open(TABDCA *dca, int mode) +{ xassert(dca == dca); + xassert(mode == mode); + xprintf("MySQL table driver not supported\n"); + return NULL; +} + +int db_mysql_read(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +int db_mysql_write(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +int db_mysql_close(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +#else + +#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__) +#include <windows.h> +#endif + +#ifdef __CYGWIN__ +#define byte_defined 1 +#endif + +#if 0 /* 12/II-2014; to fix namespace bug */ +#include <my_global.h> +#include <my_sys.h> +#endif +#include <mysql.h> + +struct db_mysql +{ + int mode; /*'R' = Read, 'W' = Write*/ + MYSQL *con; /*connection*/ + MYSQL_RES *res; /*result*/ + int nf; + /* number of fields in the csv file */ + int ref[1+SQL_FIELD_MAX]; + /* ref[k] = k', if k-th field of the csv file corresponds to + k'-th field in the table statement; if ref[k] = 0, k-th field + of the csv file is ignored */ + char *query; + /* query generated by db_mysql_open */ +}; + +void STDCALL dl_mysql_close(MYSQL *sock) +{ + typedef void STDCALL ep_mysql_close(MYSQL *sock); + + ep_mysql_close *fn; + fn = (ep_mysql_close *) xdlsym(h_mysql, "mysql_close"); + xassert(fn != NULL); + return (*fn)(sock); +} + +const char * STDCALL dl_mysql_error(MYSQL *mysql) +{ + typedef const char * STDCALL ep_mysql_error(MYSQL *mysql); + + ep_mysql_error *fn; + fn = (ep_mysql_error *) xdlsym(h_mysql, "mysql_error"); + xassert(fn != NULL); + return (*fn)(mysql); +} + +MYSQL_FIELD * STDCALL dl_mysql_fetch_fields(MYSQL_RES *res) +{ + typedef MYSQL_FIELD * STDCALL + ep_mysql_fetch_fields(MYSQL_RES *res); + + ep_mysql_fetch_fields *fn; + fn = (ep_mysql_fetch_fields *) xdlsym(h_mysql, "mysql_fetch_fields"); + xassert(fn != NULL); + return (*fn)(res); +} + +unsigned long * STDCALL dl_mysql_fetch_lengths(MYSQL_RES *result) +{ + typedef unsigned long * STDCALL + ep_mysql_fetch_lengths(MYSQL_RES *result); + + ep_mysql_fetch_lengths *fn; + fn = (ep_mysql_fetch_lengths *) xdlsym(h_mysql, + "mysql_fetch_lengths"); + xassert(fn != NULL); + return (*fn)(result); +} + +MYSQL_ROW STDCALL dl_mysql_fetch_row(MYSQL_RES *result) +{ + typedef MYSQL_ROW STDCALL ep_mysql_fetch_row(MYSQL_RES *result); + + ep_mysql_fetch_row *fn; + fn = (ep_mysql_fetch_row *) xdlsym(h_mysql, "mysql_fetch_row"); + xassert(fn != NULL); + return (*fn)(result); +} + +unsigned int STDCALL dl_mysql_field_count(MYSQL *mysql) +{ + typedef unsigned int STDCALL ep_mysql_field_count(MYSQL *mysql); + + ep_mysql_field_count *fn; + fn = (ep_mysql_field_count *) xdlsym(h_mysql, "mysql_field_count"); + xassert(fn != NULL); + return (*fn)(mysql); +} + +MYSQL * STDCALL dl_mysql_init(MYSQL *mysql) +{ + typedef MYSQL * STDCALL ep_mysql_init(MYSQL *mysql); + + ep_mysql_init *fn; + fn = (ep_mysql_init *) xdlsym(h_mysql, "mysql_init"); + xassert(fn != NULL); + return (*fn)(mysql); +} + +unsigned int STDCALL dl_mysql_num_fields(MYSQL_RES *res) +{ + typedef unsigned int STDCALL ep_mysql_num_fields(MYSQL_RES *res); + + ep_mysql_num_fields *fn; + fn = (ep_mysql_num_fields *) xdlsym(h_mysql, "mysql_num_fields"); + xassert(fn != NULL); + return (*fn)(res); +} + +int STDCALL dl_mysql_query(MYSQL *mysql, const char *q) +{ + typedef int STDCALL ep_mysql_query(MYSQL *mysql, const char *q); + + ep_mysql_query *fn; + fn = (ep_mysql_query *) xdlsym(h_mysql, "mysql_query"); + xassert(fn != NULL); + return (*fn)(mysql, q); +} + +MYSQL * STDCALL dl_mysql_real_connect(MYSQL *mysql, const char *host, + const char *user, + const char *passwd, + const char *db, + unsigned int port, + const char *unix_socket, + unsigned long clientflag) +{ + typedef MYSQL * STDCALL ep_mysql_real_connect(MYSQL *mysql, + const char *host, + const char *user, + const char *passwd, + const char *db, + unsigned int port, + const char *unix_socket, + unsigned long clientflag); + + ep_mysql_real_connect *fn; + fn = (ep_mysql_real_connect *) xdlsym(h_mysql, + "mysql_real_connect"); + xassert(fn != NULL); + return (*fn)(mysql, host, user, passwd, db, port, unix_socket, + clientflag); +} + +MYSQL_RES * STDCALL dl_mysql_use_result(MYSQL *mysql) +{ + typedef MYSQL_RES * STDCALL ep_mysql_use_result(MYSQL *mysql); + ep_mysql_use_result *fn; + fn = (ep_mysql_use_result *) xdlsym(h_mysql, "mysql_use_result"); + xassert(fn != NULL); + return (*fn)(mysql); +} + +/*********************************************************************** +* NAME +* +* db_mysql_open - open connection to ODBC data base +* +* SYNOPSIS +* +* #include "glpsql.h" +* void *db_mysql_open(TABDCA *dca, int mode); +* +* DESCRIPTION +* +* The routine db_mysql_open opens a connection to a MySQL data base. +* It then executes the sql statements passed. +* +* In the case of table read the SELECT statement is executed. +* +* In the case of table write the INSERT statement is prepared. +* RETURNS +* +* The routine returns a pointer to data storage area created. */ + +void *db_mysql_open(TABDCA *dca, int mode) +{ void *ret; + char **sqllines; + + sqllines = args_concat(dca); + if (sqllines == NULL) + { xprintf("Missing arguments in table statement.\n" + "Please, supply table driver, dsn, and query.\n"); + return NULL; + } + ret = db_mysql_open_int(dca, mode, (const char **) sqllines); + free_buffer(sqllines); + return ret; +} + +static void *db_mysql_open_int(TABDCA *dca, int mode, const char + **sqllines) +{ + struct db_mysql *sql = NULL; + char *arg = NULL; + const char *field; + MYSQL_FIELD *fields; + char *keyword; + char *value; + char *query; + char *dsn; +/* "Server=[server_name];Database=[database_name];UID=[username];*/ +/* PWD=[password];Port=[port]"*/ + char *server = NULL; /* Server */ + char *user = NULL; /* UID */ + char *password = NULL; /* PWD */ + char *database = NULL; /* Database */ + unsigned int port = 0; /* Port */ + int narg; + int i, j, total; + + if (libmysql == NULL) + { + xprintf("No loader for shared MySQL library available\n"); + return NULL; + } + + if (h_mysql == NULL) + { + h_mysql = xdlopen(libmysql); + if (h_mysql == NULL) + { xprintf("unable to open library %s\n", libmysql); + xprintf("%s\n", get_err_msg()); + return NULL; + } + } + + sql = (struct db_mysql *) xmalloc(sizeof(struct db_mysql)); + if (sql == NULL) + return NULL; + sql->mode = mode; + sql->res = NULL; + sql->query = NULL; + sql->nf = mpl_tab_num_flds(dca); + + narg = mpl_tab_num_args(dca); + if (narg < 3 ) + xprintf("MySQL driver: string list too short \n"); + + /* get connection string*/ + dsn = (char *) mpl_tab_get_arg(dca, 2); + /* copy connection string*/ + i = strlen(dsn); + i++; + arg = xmalloc(i * sizeof(char)); + strcpy(arg, dsn); + /*tokenize connection string*/ + for (i = 1, keyword = strtok (arg, "="); (keyword != NULL); + keyword = strtok (NULL, "="), i++) + { + value = strtok (NULL, ";"); + if (value==NULL) + { + xprintf("db_mysql_open: Missing value for keyword %s\n", + keyword); + xfree(arg); + xfree(sql); + return NULL; + } + if (0 == strcmp(keyword, "Server")) + server = value; + else if (0 == strcmp(keyword, "Database")) + database = value; + else if (0 == strcmp(keyword, "UID")) + user = value; + else if (0 == strcmp(keyword, "PWD")) + password = value; + else if (0 == strcmp(keyword, "Port")) + port = (unsigned int) atol(value); + } + /* Connect to database */ + sql->con = dl_mysql_init(NULL); + if (!dl_mysql_real_connect(sql->con, server, user, password, database, + port, NULL, 0)) + { + xprintf("db_mysql_open: Connect failed\n"); + xprintf("%s\n", dl_mysql_error(sql->con)); + xfree(arg); + xfree(sql); + return NULL; + } + xfree(arg); + + for(j = 0; sqllines[j+1] != NULL; j++) + { query = (char *) sqllines[j]; + xprintf("%s\n", query); + if (dl_mysql_query(sql->con, query)) + { + xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); + xprintf("%s\n",dl_mysql_error(sql->con)); + dl_mysql_close(sql->con); + xfree(sql); + return NULL; + } + } + + if ( sql->mode == 'R' ) + { sql->nf = mpl_tab_num_flds(dca); + for(j = 0; sqllines[j] != NULL; j++) + arg = (char *) sqllines[j]; + total = strlen(arg); + if (total > 7 && 0 == strncmp(arg, "SELECT ", 7)) + { + total = strlen(arg); + query = xmalloc( (total+1) * sizeof(char)); + strcpy (query, arg); + } + else + { + query = db_generate_select_stmt(dca); + } + xprintf("%s\n", query); + if (dl_mysql_query(sql->con, query)) + { + xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); + xprintf("%s\n",dl_mysql_error(sql->con)); + dl_mysql_close(sql->con); + xfree(query); + xfree(sql); + return NULL; + } + xfree(query); + sql->res = dl_mysql_use_result(sql->con); + if (sql->res) + { + /* create references between query results and table fields*/ + total = dl_mysql_num_fields(sql->res); + if (total > SQL_FIELD_MAX) + { xprintf("db_mysql_open: Too many fields (> %d) in query.\n" + "\"%s\"\n", SQL_FIELD_MAX, query); + xprintf("%s\n",dl_mysql_error(sql->con)); + dl_mysql_close(sql->con); + xfree(query); + xfree(sql); + return NULL; + } + fields = dl_mysql_fetch_fields(sql->res); + for (i = 1; i <= total; i++) + { + for (j = sql->nf; j >= 1; j--) + { + if (strcmp(mpl_tab_get_name(dca, j), fields[i-1].name) + == 0) + break; + } + sql->ref[i] = j; + } + } + else + { + if(dl_mysql_field_count(sql->con) == 0) + { + xprintf("db_mysql_open: Query was not a SELECT\n\"%s\"\n", + query); + xprintf("%s\n",dl_mysql_error(sql->con)); + xfree(query); + xfree(sql); + return NULL; + } + else + { + xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); + xprintf("%s\n",dl_mysql_error(sql->con)); + xfree(query); + xfree(sql); + return NULL; + } + } + } + else if ( sql->mode == 'W' ) + { for(j = 0; sqllines[j] != NULL; j++) + arg = (char *) sqllines[j]; + if ( NULL != strchr(arg, '?') ) + { + total = strlen(arg); + query = xmalloc( (total+1) * sizeof(char)); + strcpy (query, arg); + } + else + query = db_generate_insert_stmt(dca); + sql->query = query; + xprintf("%s\n", query); + } + return sql; +} + +int db_mysql_read(TABDCA *dca, void *link) +{ struct db_mysql *sql; + char buf[255+1]; + char **row; + unsigned long *lengths; + MYSQL_FIELD *fields; + double num; + int len; + unsigned long num_fields; + int i; + + sql = (struct db_mysql *) link; + + xassert(sql != NULL); + xassert(sql->mode == 'R'); + if (NULL == sql->res) + { + xprintf("db_mysql_read: no result set available"); + return 1; + } + if (NULL==(row = (char **)dl_mysql_fetch_row(sql->res))) { + return -1; /*EOF*/ + } + lengths = dl_mysql_fetch_lengths(sql->res); + fields = dl_mysql_fetch_fields(sql->res); + num_fields = dl_mysql_num_fields(sql->res); + for (i=1; i <= num_fields; i++) + { + if (row[i-1] != NULL) + { len = (size_t) lengths[i-1]; + if (len > 255) + len = 255; + strncpy(buf, (const char *) row[i-1], len); + buf[len] = 0x00; + if (0 != (fields[i-1].flags & NUM_FLAG)) + { strspx(buf); /* remove spaces*/ + if (str2num(buf, &num) != 0) + { xprintf("'%s' cannot be converted to a number.\n", buf); + return 1; + } + if (sql->ref[i] > 0) + mpl_tab_set_num(dca, sql->ref[i], num); + } + else + { if (sql->ref[i] > 0) + mpl_tab_set_str(dca, sql->ref[i], strtrim(buf)); + } + } + } + return 0; +} + +int db_mysql_write(TABDCA *dca, void *link) +{ + struct db_mysql *sql; + char *part; + char *query; + char *template; + char num[50]; + int k; + int len; + int nf; + + sql = (struct db_mysql *) link; + xassert(sql != NULL); + xassert(sql->mode == 'W'); + + len = strlen(sql->query); + template = (char *) xmalloc( (len + 1) * sizeof(char) ); + strcpy(template, sql->query); + + nf = mpl_tab_num_flds(dca); + for (k = 1; k <= nf; k++) + { switch (mpl_tab_get_type(dca, k)) + { case 'N': + len += 20; + break; + case 'S': + len += db_escaped_string_length(mpl_tab_get_str(dca, k)); + len += 2; + break; + default: + xassert(dca != dca); + } + } + query = xmalloc( (len + 1 ) * sizeof(char) ); + query[0] = 0x00; + for (k = 1, part = strtok (template, "?"); (part != NULL); + part = strtok (NULL, "?"), k++) + { + if (k > nf) break; + strcat( query, part ); + switch (mpl_tab_get_type(dca, k)) + { case 'N': +#if 0 /* 02/XI-2010 by xypron */ + sprintf(num, "%-18g",mpl_tab_get_num(dca, k)); +#else + sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); +#endif + strcat( query, num ); + break; + case 'S': + strcat( query, "'"); + db_escape_string( query + strlen(query), + mpl_tab_get_str(dca, k) ); + strcat( query, "'"); + break; + default: + xassert(dca != dca); + } + } + if (part != NULL) + strcat(query, part); + if (dl_mysql_query(sql->con, query)) + { + xprintf("db_mysql_write: Query\n\"%s\"\nfailed.\n", query); + xprintf("%s\n",dl_mysql_error(sql->con)); + xfree(query); + xfree(template); + return 1; + } + + xfree(query); + xfree(template); + return 0; + } + +int db_mysql_close(TABDCA *dca, void *link) +{ + struct db_mysql *sql; + + sql = (struct db_mysql *) link; + xassert(sql != NULL); + dl_mysql_close(sql->con); + if ( sql->mode == 'W' ) + xfree(sql->query); + xfree(sql); + dca->link = NULL; + return 0; +} + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpsql.h b/resources/3rdparty/glpk-4.53/src/glpsql.h new file mode 100644 index 000000000..2a1650561 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpsql.h @@ -0,0 +1,64 @@ +/* glpsql.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Author: Heinrich Schuchardt <heinrich.schuchardt@gmx.de>. +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPSQL_H +#define GLPSQL_H + +#define db_iodbc_open _glp_db_iodbc_open +void *db_iodbc_open(TABDCA *dca, int mode); +/* open iODBC database connection */ + +#define db_iodbc_read _glp_db_iodbc_read +int db_iodbc_read(TABDCA *dca, void *link); +/* read data from iODBC */ + +#define db_iodbc_write _glp_db_iodbc_write +int db_iodbc_write(TABDCA *dca, void *link); +/* write data to iODBC */ + +#define db_iodbc_close _glp_db_iodbc_close +int db_iodbc_close(TABDCA *dca, void *link); +/* close iODBC database connection */ + +#define db_mysql_open _glp_db_mysql_open +void *db_mysql_open(TABDCA *dca, int mode); +/* open MySQL database connection */ + +#define db_mysql_read _glp_db_mysql_read +int db_mysql_read(TABDCA *dca, void *link); +/* read data from MySQL */ + +#define db_mysql_write _glp_db_mysql_write +int db_mysql_write(TABDCA *dca, void *link); +/* write data to MySQL */ + +#define db_mysql_close _glp_db_mysql_close +int db_mysql_close(TABDCA *dca, void *link); +/* close MySQL database connection */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpssx.h b/resources/3rdparty/glpk-4.53/src/glpssx.h new file mode 100644 index 000000000..1b55d7a3d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpssx.h @@ -0,0 +1,426 @@ +/* glpssx.h (simplex method, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPSSX_H +#define GLPSSX_H + +#include "bfx.h" +#include "env.h" + +typedef struct SSX SSX; + +struct SSX +{ /* simplex solver workspace */ +/*---------------------------------------------------------------------- +// LP PROBLEM DATA +// +// It is assumed that LP problem has the following statement: +// +// minimize (or maximize) +// +// z = c[1]*x[1] + ... + c[m+n]*x[m+n] + c[0] (1) +// +// subject to equality constraints +// +// x[1] - a[1,1]*x[m+1] - ... - a[1,n]*x[m+n] = 0 +// +// . . . . . . . (2) +// +// x[m] - a[m,1]*x[m+1] + ... - a[m,n]*x[m+n] = 0 +// +// and bounds of variables +// +// l[1] <= x[1] <= u[1] +// +// . . . . . . . (3) +// +// l[m+n] <= x[m+n] <= u[m+n] +// +// where: +// x[1], ..., x[m] - auxiliary variables; +// x[m+1], ..., x[m+n] - structural variables; +// z - objective function; +// c[1], ..., c[m+n] - coefficients of the objective function; +// c[0] - constant term of the objective function; +// a[1,1], ..., a[m,n] - constraint coefficients; +// l[1], ..., l[m+n] - lower bounds of variables; +// u[1], ..., u[m+n] - upper bounds of variables. +// +// Bounds of variables can be finite as well as inifinite. Besides, +// lower and upper bounds can be equal to each other. So the following +// five types of variables are possible: +// +// Bounds of variable Type of variable +// ------------------------------------------------- +// -inf < x[k] < +inf Free (unbounded) variable +// l[k] <= x[k] < +inf Variable with lower bound +// -inf < x[k] <= u[k] Variable with upper bound +// l[k] <= x[k] <= u[k] Double-bounded variable +// l[k] = x[k] = u[k] Fixed variable +// +// Using vector-matrix notations the LP problem (1)-(3) can be written +// as follows: +// +// minimize (or maximize) +// +// z = c * x + c[0] (4) +// +// subject to equality constraints +// +// xR - A * xS = 0 (5) +// +// and bounds of variables +// +// l <= x <= u (6) +// +// where: +// xR - vector of auxiliary variables; +// xS - vector of structural variables; +// x = (xR, xS) - vector of all variables; +// z - objective function; +// c - vector of objective coefficients; +// c[0] - constant term of the objective function; +// A - matrix of constraint coefficients (has m rows +// and n columns); +// l - vector of lower bounds of variables; +// u - vector of upper bounds of variables. +// +// The simplex method makes no difference between auxiliary and +// structural variables, so it is convenient to think the system of +// equality constraints (5) written in a homogeneous form: +// +// (I | -A) * x = 0, (7) +// +// where (I | -A) is an augmented (m+n)xm constraint matrix, I is mxm +// unity matrix whose columns correspond to auxiliary variables, and A +// is the original mxn constraint matrix whose columns correspond to +// structural variables. Note that only the matrix A is stored. +----------------------------------------------------------------------*/ + int m; + /* number of rows (auxiliary variables), m > 0 */ + int n; + /* number of columns (structural variables), n > 0 */ + int *type; /* int type[1+m+n]; */ + /* type[0] is not used; + type[k], 1 <= k <= m+n, is the type of variable x[k]: */ +#define SSX_FR 0 /* free (unbounded) variable */ +#define SSX_LO 1 /* variable with lower bound */ +#define SSX_UP 2 /* variable with upper bound */ +#define SSX_DB 3 /* double-bounded variable */ +#define SSX_FX 4 /* fixed variable */ + mpq_t *lb; /* mpq_t lb[1+m+n]; alias: l */ + /* lb[0] is not used; + lb[k], 1 <= k <= m+n, is an lower bound of variable x[k]; + if x[k] has no lower bound, lb[k] is zero */ + mpq_t *ub; /* mpq_t ub[1+m+n]; alias: u */ + /* ub[0] is not used; + ub[k], 1 <= k <= m+n, is an upper bound of variable x[k]; + if x[k] has no upper bound, ub[k] is zero; + if x[k] is of fixed type, ub[k] is equal to lb[k] */ + int dir; + /* optimization direction (sense of the objective function): */ +#define SSX_MIN 0 /* minimization */ +#define SSX_MAX 1 /* maximization */ + mpq_t *coef; /* mpq_t coef[1+m+n]; alias: c */ + /* coef[0] is a constant term of the objective function; + coef[k], 1 <= k <= m+n, is a coefficient of the objective + function at variable x[k]; + note that auxiliary variables also may have non-zero objective + coefficients */ + int *A_ptr; /* int A_ptr[1+n+1]; */ + int *A_ind; /* int A_ind[A_ptr[n+1]]; */ + mpq_t *A_val; /* mpq_t A_val[A_ptr[n+1]]; */ + /* constraint matrix A (see (5)) in storage-by-columns format */ +/*---------------------------------------------------------------------- +// LP BASIS AND CURRENT BASIC SOLUTION +// +// The LP basis is defined by the following partition of the augmented +// constraint matrix (7): +// +// (B | N) = (I | -A) * Q, (8) +// +// where B is a mxm non-singular basis matrix whose columns correspond +// to basic variables xB, N is a mxn matrix whose columns correspond to +// non-basic variables xN, and Q is a permutation (m+n)x(m+n) matrix. +// +// From (7) and (8) it follows that +// +// (I | -A) * x = (I | -A) * Q * Q' * x = (B | N) * (xB, xN), +// +// therefore +// +// (xB, xN) = Q' * x, (9) +// +// where x is the vector of all variables in the original order, xB is +// a vector of basic variables, xN is a vector of non-basic variables, +// Q' = inv(Q) is a matrix transposed to Q. +// +// Current values of non-basic variables xN[j], j = 1, ..., n, are not +// stored; they are defined implicitly by their statuses as follows: +// +// 0, if xN[j] is free variable +// lN[j], if xN[j] is on its lower bound (10) +// uN[j], if xN[j] is on its upper bound +// lN[j] = uN[j], if xN[j] is fixed variable +// +// where lN[j] and uN[j] are lower and upper bounds of xN[j]. +// +// Current values of basic variables xB[i], i = 1, ..., m, are computed +// as follows: +// +// beta = - inv(B) * N * xN, (11) +// +// where current values of xN are defined by (10). +// +// Current values of simplex multipliers pi[i], i = 1, ..., m (which +// are values of Lagrange multipliers for equality constraints (7) also +// called shadow prices) are computed as follows: +// +// pi = inv(B') * cB, (12) +// +// where B' is a matrix transposed to B, cB is a vector of objective +// coefficients at basic variables xB. +// +// Current values of reduced costs d[j], j = 1, ..., n, (which are +// values of Langrange multipliers for active inequality constraints +// corresponding to non-basic variables) are computed as follows: +// +// d = cN - N' * pi, (13) +// +// where N' is a matrix transposed to N, cN is a vector of objective +// coefficients at non-basic variables xN. +----------------------------------------------------------------------*/ + int *stat; /* int stat[1+m+n]; */ + /* stat[0] is not used; + stat[k], 1 <= k <= m+n, is the status of variable x[k]: */ +#define SSX_BS 0 /* basic variable */ +#define SSX_NL 1 /* non-basic variable on lower bound */ +#define SSX_NU 2 /* non-basic variable on upper bound */ +#define SSX_NF 3 /* non-basic free variable */ +#define SSX_NS 4 /* non-basic fixed variable */ + int *Q_row; /* int Q_row[1+m+n]; */ + /* matrix Q in row-like format; + Q_row[0] is not used; + Q_row[i] = j means that q[i,j] = 1 */ + int *Q_col; /* int Q_col[1+m+n]; */ + /* matrix Q in column-like format; + Q_col[0] is not used; + Q_col[j] = i means that q[i,j] = 1 */ + /* if k-th column of the matrix (I | A) is k'-th column of the + matrix (B | N), then Q_row[k] = k' and Q_col[k'] = k; + if x[k] is xB[i], then Q_row[k] = i and Q_col[i] = k; + if x[k] is xN[j], then Q_row[k] = m+j and Q_col[m+j] = k */ + BFX *binv; + /* invertable form of the basis matrix B */ + mpq_t *bbar; /* mpq_t bbar[1+m]; alias: beta */ + /* bbar[0] is a value of the objective function; + bbar[i], 1 <= i <= m, is a value of basic variable xB[i] */ + mpq_t *pi; /* mpq_t pi[1+m]; */ + /* pi[0] is not used; + pi[i], 1 <= i <= m, is a simplex multiplier corresponding to + i-th row (equality constraint) */ + mpq_t *cbar; /* mpq_t cbar[1+n]; alias: d */ + /* cbar[0] is not used; + cbar[j], 1 <= j <= n, is a reduced cost of non-basic variable + xN[j] */ +/*---------------------------------------------------------------------- +// SIMPLEX TABLE +// +// Due to (8) and (9) the system of equality constraints (7) for the +// current basis can be written as follows: +// +// xB = A~ * xN, (14) +// +// where +// +// A~ = - inv(B) * N (15) +// +// is a mxn matrix called the simplex table. +// +// The revised simplex method uses only two components of A~, namely, +// pivot column corresponding to non-basic variable xN[q] chosen to +// enter the basis, and pivot row corresponding to basic variable xB[p] +// chosen to leave the basis. +// +// Pivot column alfa_q is q-th column of A~, so +// +// alfa_q = A~ * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], (16) +// +// where N[q] is q-th column of the matrix N. +// +// Pivot row alfa_p is p-th row of A~ or, equivalently, p-th column of +// A~', a matrix transposed to A~, so +// +// alfa_p = A~' * e[p] = - N' * inv(B') * e[p] = - N' * rho_p, (17) +// +// where (*)' means transposition, and +// +// rho_p = inv(B') * e[p], (18) +// +// is p-th column of inv(B') or, that is the same, p-th row of inv(B). +----------------------------------------------------------------------*/ + int p; + /* number of basic variable xB[p], 1 <= p <= m, chosen to leave + the basis */ + mpq_t *rho; /* mpq_t rho[1+m]; */ + /* p-th row of the inverse inv(B); see (18) */ + mpq_t *ap; /* mpq_t ap[1+n]; */ + /* p-th row of the simplex table; see (17) */ + int q; + /* number of non-basic variable xN[q], 1 <= q <= n, chosen to + enter the basis */ + mpq_t *aq; /* mpq_t aq[1+m]; */ + /* q-th column of the simplex table; see (16) */ +/*--------------------------------------------------------------------*/ + int q_dir; + /* direction in which non-basic variable xN[q] should change on + moving to the adjacent vertex of the polyhedron: + +1 means that xN[q] increases + -1 means that xN[q] decreases */ + int p_stat; + /* non-basic status which should be assigned to basic variable + xB[p] when it has left the basis and become xN[q] */ + mpq_t delta; + /* actual change of xN[q] in the adjacent basis (it has the same + sign as q_dir) */ +/*--------------------------------------------------------------------*/ + int it_lim; + /* simplex iterations limit; if this value is positive, it is + decreased by one each time when one simplex iteration has been + performed, and reaching zero value signals the solver to stop + the search; negative value means no iterations limit */ + int it_cnt; + /* simplex iterations count; this count is increased by one each + time when one simplex iteration has been performed */ + double tm_lim; + /* searching time limit, in seconds; if this value is positive, + it is decreased each time when one simplex iteration has been + performed by the amount of time spent for the iteration, and + reaching zero value signals the solver to stop the search; + negative value means no time limit */ + double out_frq; + /* output frequency, in seconds; this parameter specifies how + frequently the solver sends information about the progress of + the search to the standard output */ +#if 0 /* 10/VI-2013 */ + glp_long tm_beg; +#else + double tm_beg; +#endif + /* starting time of the search, in seconds; the total time of the + search is the difference between xtime() and tm_beg */ +#if 0 /* 10/VI-2013 */ + glp_long tm_lag; +#else + double tm_lag; +#endif + /* the most recent time, in seconds, at which the progress of the + the search was displayed */ +}; + +#define ssx_create _glp_ssx_create +#define ssx_factorize _glp_ssx_factorize +#define ssx_get_xNj _glp_ssx_get_xNj +#define ssx_eval_bbar _glp_ssx_eval_bbar +#define ssx_eval_pi _glp_ssx_eval_pi +#define ssx_eval_dj _glp_ssx_eval_dj +#define ssx_eval_cbar _glp_ssx_eval_cbar +#define ssx_eval_rho _glp_ssx_eval_rho +#define ssx_eval_row _glp_ssx_eval_row +#define ssx_eval_col _glp_ssx_eval_col +#define ssx_chuzc _glp_ssx_chuzc +#define ssx_chuzr _glp_ssx_chuzr +#define ssx_update_bbar _glp_ssx_update_bbar +#define ssx_update_pi _glp_ssx_update_pi +#define ssx_update_cbar _glp_ssx_update_cbar +#define ssx_change_basis _glp_ssx_change_basis +#define ssx_delete _glp_ssx_delete + +#define ssx_phase_I _glp_ssx_phase_I +#define ssx_phase_II _glp_ssx_phase_II +#define ssx_driver _glp_ssx_driver + +SSX *ssx_create(int m, int n, int nnz); +/* create simplex solver workspace */ + +int ssx_factorize(SSX *ssx); +/* factorize the current basis matrix */ + +void ssx_get_xNj(SSX *ssx, int j, mpq_t x); +/* determine value of non-basic variable */ + +void ssx_eval_bbar(SSX *ssx); +/* compute values of basic variables */ + +void ssx_eval_pi(SSX *ssx); +/* compute values of simplex multipliers */ + +void ssx_eval_dj(SSX *ssx, int j, mpq_t dj); +/* compute reduced cost of non-basic variable */ + +void ssx_eval_cbar(SSX *ssx); +/* compute reduced costs of all non-basic variables */ + +void ssx_eval_rho(SSX *ssx); +/* compute p-th row of the inverse */ + +void ssx_eval_row(SSX *ssx); +/* compute pivot row of the simplex table */ + +void ssx_eval_col(SSX *ssx); +/* compute pivot column of the simplex table */ + +void ssx_chuzc(SSX *ssx); +/* choose pivot column */ + +void ssx_chuzr(SSX *ssx); +/* choose pivot row */ + +void ssx_update_bbar(SSX *ssx); +/* update values of basic variables */ + +void ssx_update_pi(SSX *ssx); +/* update simplex multipliers */ + +void ssx_update_cbar(SSX *ssx); +/* update reduced costs of non-basic variables */ + +void ssx_change_basis(SSX *ssx); +/* change current basis to adjacent one */ + +void ssx_delete(SSX *ssx); +/* delete simplex solver workspace */ + +int ssx_phase_I(SSX *ssx); +/* find primal feasible solution */ + +int ssx_phase_II(SSX *ssx); +/* find optimal solution */ + +int ssx_driver(SSX *ssx); +/* base driver to exact simplex method */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpssx01.c b/resources/3rdparty/glpk-4.53/src/glpssx01.c new file mode 100644 index 000000000..9b70444ec --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpssx01.c @@ -0,0 +1,839 @@ +/* glpssx01.c (simplex method, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpssx.h" +#define xfault xerror + +/*---------------------------------------------------------------------- +// ssx_create - create simplex solver workspace. +// +// This routine creates the workspace used by simplex solver routines, +// and returns a pointer to it. +// +// Parameters m, n, and nnz specify, respectively, the number of rows, +// columns, and non-zero constraint coefficients. +// +// This routine only allocates the memory for the workspace components, +// so the workspace needs to be saturated by data. */ + +SSX *ssx_create(int m, int n, int nnz) +{ SSX *ssx; + int i, j, k; + if (m < 1) + xfault("ssx_create: m = %d; invalid number of rows\n", m); + if (n < 1) + xfault("ssx_create: n = %d; invalid number of columns\n", n); + if (nnz < 0) + xfault("ssx_create: nnz = %d; invalid number of non-zero const" + "raint coefficients\n", nnz); + ssx = xmalloc(sizeof(SSX)); + ssx->m = m; + ssx->n = n; + ssx->type = xcalloc(1+m+n, sizeof(int)); + ssx->lb = xcalloc(1+m+n, sizeof(mpq_t)); + for (k = 1; k <= m+n; k++) mpq_init(ssx->lb[k]); + ssx->ub = xcalloc(1+m+n, sizeof(mpq_t)); + for (k = 1; k <= m+n; k++) mpq_init(ssx->ub[k]); + ssx->coef = xcalloc(1+m+n, sizeof(mpq_t)); + for (k = 0; k <= m+n; k++) mpq_init(ssx->coef[k]); + ssx->A_ptr = xcalloc(1+n+1, sizeof(int)); + ssx->A_ptr[n+1] = nnz+1; + ssx->A_ind = xcalloc(1+nnz, sizeof(int)); + ssx->A_val = xcalloc(1+nnz, sizeof(mpq_t)); + for (k = 1; k <= nnz; k++) mpq_init(ssx->A_val[k]); + ssx->stat = xcalloc(1+m+n, sizeof(int)); + ssx->Q_row = xcalloc(1+m+n, sizeof(int)); + ssx->Q_col = xcalloc(1+m+n, sizeof(int)); + ssx->binv = bfx_create_binv(); + ssx->bbar = xcalloc(1+m, sizeof(mpq_t)); + for (i = 0; i <= m; i++) mpq_init(ssx->bbar[i]); + ssx->pi = xcalloc(1+m, sizeof(mpq_t)); + for (i = 1; i <= m; i++) mpq_init(ssx->pi[i]); + ssx->cbar = xcalloc(1+n, sizeof(mpq_t)); + for (j = 1; j <= n; j++) mpq_init(ssx->cbar[j]); + ssx->rho = xcalloc(1+m, sizeof(mpq_t)); + for (i = 1; i <= m; i++) mpq_init(ssx->rho[i]); + ssx->ap = xcalloc(1+n, sizeof(mpq_t)); + for (j = 1; j <= n; j++) mpq_init(ssx->ap[j]); + ssx->aq = xcalloc(1+m, sizeof(mpq_t)); + for (i = 1; i <= m; i++) mpq_init(ssx->aq[i]); + mpq_init(ssx->delta); + return ssx; +} + +/*---------------------------------------------------------------------- +// ssx_factorize - factorize the current basis matrix. +// +// This routine computes factorization of the current basis matrix B +// and returns the singularity flag. If the matrix B is non-singular, +// the flag is zero, otherwise non-zero. */ + +static int basis_col(void *info, int j, int ind[], mpq_t val[]) +{ /* this auxiliary routine provides row indices and numeric values + of non-zero elements in j-th column of the matrix B */ + SSX *ssx = info; + int m = ssx->m; + int n = ssx->n; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + int k, len, ptr; + xassert(1 <= j && j <= m); + k = Q_col[j]; /* x[k] = xB[j] */ + xassert(1 <= k && k <= m+n); + /* j-th column of the matrix B is k-th column of the augmented + constraint matrix (I | -A) */ + if (k <= m) + { /* it is a column of the unity matrix I */ + len = 1, ind[1] = k, mpq_set_si(val[1], 1, 1); + } + else + { /* it is a column of the original constraint matrix -A */ + len = 0; + for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) + { len++; + ind[len] = A_ind[ptr]; + mpq_neg(val[len], A_val[ptr]); + } + } + return len; +} + +int ssx_factorize(SSX *ssx) +{ int ret; + ret = bfx_factorize(ssx->binv, ssx->m, basis_col, ssx); + return ret; +} + +/*---------------------------------------------------------------------- +// ssx_get_xNj - determine value of non-basic variable. +// +// This routine determines the value of non-basic variable xN[j] in the +// current basic solution defined as follows: +// +// 0, if xN[j] is free variable +// lN[j], if xN[j] is on its lower bound +// uN[j], if xN[j] is on its upper bound +// lN[j] = uN[j], if xN[j] is fixed variable +// +// where lN[j] and uN[j] are lower and upper bounds of xN[j]. */ + +void ssx_get_xNj(SSX *ssx, int j, mpq_t x) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *lb = ssx->lb; + mpq_t *ub = ssx->ub; + int *stat = ssx->stat; + int *Q_col = ssx->Q_col; + int k; + xassert(1 <= j && j <= n); + k = Q_col[m+j]; /* x[k] = xN[j] */ + xassert(1 <= k && k <= m+n); + switch (stat[k]) + { case SSX_NL: + /* xN[j] is on its lower bound */ + mpq_set(x, lb[k]); break; + case SSX_NU: + /* xN[j] is on its upper bound */ + mpq_set(x, ub[k]); break; + case SSX_NF: + /* xN[j] is free variable */ + mpq_set_si(x, 0, 1); break; + case SSX_NS: + /* xN[j] is fixed variable */ + mpq_set(x, lb[k]); break; + default: + xassert(stat != stat); + } + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_bbar - compute values of basic variables. +// +// This routine computes values of basic variables xB in the current +// basic solution as follows: +// +// beta = - inv(B) * N * xN, +// +// where B is the basis matrix, N is the matrix of non-basic columns, +// xN is a vector of current values of non-basic variables. */ + +void ssx_eval_bbar(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *coef = ssx->coef; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + mpq_t *bbar = ssx->bbar; + int i, j, k, ptr; + mpq_t x, temp; + mpq_init(x); + mpq_init(temp); + /* bbar := 0 */ + for (i = 1; i <= m; i++) + mpq_set_si(bbar[i], 0, 1); + /* bbar := - N * xN = - N[1] * xN[1] - ... - N[n] * xN[n] */ + for (j = 1; j <= n; j++) + { ssx_get_xNj(ssx, j, x); + if (mpq_sgn(x) == 0) continue; + k = Q_col[m+j]; /* x[k] = xN[j] */ + if (k <= m) + { /* N[j] is a column of the unity matrix I */ + mpq_sub(bbar[k], bbar[k], x); + } + else + { /* N[j] is a column of the original constraint matrix -A */ + for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) + { mpq_mul(temp, A_val[ptr], x); + mpq_add(bbar[A_ind[ptr]], bbar[A_ind[ptr]], temp); + } + } + } + /* bbar := inv(B) * bbar */ + bfx_ftran(ssx->binv, bbar, 0); +#if 1 + /* compute value of the objective function */ + /* bbar[0] := c[0] */ + mpq_set(bbar[0], coef[0]); + /* bbar[0] := bbar[0] + sum{i in B} cB[i] * xB[i] */ + for (i = 1; i <= m; i++) + { k = Q_col[i]; /* x[k] = xB[i] */ + if (mpq_sgn(coef[k]) == 0) continue; + mpq_mul(temp, coef[k], bbar[i]); + mpq_add(bbar[0], bbar[0], temp); + } + /* bbar[0] := bbar[0] + sum{j in N} cN[j] * xN[j] */ + for (j = 1; j <= n; j++) + { k = Q_col[m+j]; /* x[k] = xN[j] */ + if (mpq_sgn(coef[k]) == 0) continue; + ssx_get_xNj(ssx, j, x); + mpq_mul(temp, coef[k], x); + mpq_add(bbar[0], bbar[0], temp); + } +#endif + mpq_clear(x); + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_pi - compute values of simplex multipliers. +// +// This routine computes values of simplex multipliers (shadow prices) +// pi in the current basic solution as follows: +// +// pi = inv(B') * cB, +// +// where B' is a matrix transposed to the basis matrix B, cB is a vector +// of objective coefficients at basic variables xB. */ + +void ssx_eval_pi(SSX *ssx) +{ int m = ssx->m; + mpq_t *coef = ssx->coef; + int *Q_col = ssx->Q_col; + mpq_t *pi = ssx->pi; + int i; + /* pi := cB */ + for (i = 1; i <= m; i++) mpq_set(pi[i], coef[Q_col[i]]); + /* pi := inv(B') * cB */ + bfx_btran(ssx->binv, pi); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_dj - compute reduced cost of non-basic variable. +// +// This routine computes reduced cost d[j] of non-basic variable xN[j] +// in the current basic solution as follows: +// +// d[j] = cN[j] - N[j] * pi, +// +// where cN[j] is an objective coefficient at xN[j], N[j] is a column +// of the augmented constraint matrix (I | -A) corresponding to xN[j], +// pi is the vector of simplex multipliers (shadow prices). */ + +void ssx_eval_dj(SSX *ssx, int j, mpq_t dj) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *coef = ssx->coef; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + mpq_t *pi = ssx->pi; + int k, ptr, end; + mpq_t temp; + mpq_init(temp); + xassert(1 <= j && j <= n); + k = Q_col[m+j]; /* x[k] = xN[j] */ + xassert(1 <= k && k <= m+n); + /* j-th column of the matrix N is k-th column of the augmented + constraint matrix (I | -A) */ + if (k <= m) + { /* it is a column of the unity matrix I */ + mpq_sub(dj, coef[k], pi[k]); + } + else + { /* it is a column of the original constraint matrix -A */ + mpq_set(dj, coef[k]); + for (ptr = A_ptr[k-m], end = A_ptr[k-m+1]; ptr < end; ptr++) + { mpq_mul(temp, A_val[ptr], pi[A_ind[ptr]]); + mpq_add(dj, dj, temp); + } + } + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_cbar - compute reduced costs of all non-basic variables. +// +// This routine computes the vector of reduced costs pi in the current +// basic solution for all non-basic variables, including fixed ones. */ + +void ssx_eval_cbar(SSX *ssx) +{ int n = ssx->n; + mpq_t *cbar = ssx->cbar; + int j; + for (j = 1; j <= n; j++) + ssx_eval_dj(ssx, j, cbar[j]); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_rho - compute p-th row of the inverse. +// +// This routine computes p-th row of the matrix inv(B), where B is the +// current basis matrix. +// +// p-th row of the inverse is computed using the following formula: +// +// rho = inv(B') * e[p], +// +// where B' is a matrix transposed to B, e[p] is a unity vector, which +// contains one in p-th position. */ + +void ssx_eval_rho(SSX *ssx) +{ int m = ssx->m; + int p = ssx->p; + mpq_t *rho = ssx->rho; + int i; + xassert(1 <= p && p <= m); + /* rho := 0 */ + for (i = 1; i <= m; i++) mpq_set_si(rho[i], 0, 1); + /* rho := e[p] */ + mpq_set_si(rho[p], 1, 1); + /* rho := inv(B') * rho */ + bfx_btran(ssx->binv, rho); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_row - compute pivot row of the simplex table. +// +// This routine computes p-th (pivot) row of the current simplex table +// A~ = - inv(B) * N using the following formula: +// +// A~[p] = - N' * inv(B') * e[p] = - N' * rho[p], +// +// where N' is a matrix transposed to the matrix N, rho[p] is p-th row +// of the inverse inv(B). */ + +void ssx_eval_row(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + mpq_t *rho = ssx->rho; + mpq_t *ap = ssx->ap; + int j, k, ptr; + mpq_t temp; + mpq_init(temp); + for (j = 1; j <= n; j++) + { /* ap[j] := - N'[j] * rho (inner product) */ + k = Q_col[m+j]; /* x[k] = xN[j] */ + if (k <= m) + mpq_neg(ap[j], rho[k]); + else + { mpq_set_si(ap[j], 0, 1); + for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) + { mpq_mul(temp, A_val[ptr], rho[A_ind[ptr]]); + mpq_add(ap[j], ap[j], temp); + } + } + } + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_col - compute pivot column of the simplex table. +// +// This routine computes q-th (pivot) column of the current simplex +// table A~ = - inv(B) * N using the following formula: +// +// A~[q] = - inv(B) * N[q], +// +// where N[q] is q-th column of the matrix N corresponding to chosen +// non-basic variable xN[q]. */ + +void ssx_eval_col(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + int q = ssx->q; + mpq_t *aq = ssx->aq; + int i, k, ptr; + xassert(1 <= q && q <= n); + /* aq := 0 */ + for (i = 1; i <= m; i++) mpq_set_si(aq[i], 0, 1); + /* aq := N[q] */ + k = Q_col[m+q]; /* x[k] = xN[q] */ + if (k <= m) + { /* N[q] is a column of the unity matrix I */ + mpq_set_si(aq[k], 1, 1); + } + else + { /* N[q] is a column of the original constraint matrix -A */ + for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) + mpq_neg(aq[A_ind[ptr]], A_val[ptr]); + } + /* aq := inv(B) * aq */ + bfx_ftran(ssx->binv, aq, 1); + /* aq := - aq */ + for (i = 1; i <= m; i++) mpq_neg(aq[i], aq[i]); + return; +} + +/*---------------------------------------------------------------------- +// ssx_chuzc - choose pivot column. +// +// This routine chooses non-basic variable xN[q] whose reduced cost +// indicates possible improving of the objective function to enter it +// in the basis. +// +// Currently the standard (textbook) pricing is used, i.e. that +// non-basic variable is preferred which has greatest reduced cost (in +// magnitude). +// +// If xN[q] has been chosen, the routine stores its number q and also +// sets the flag q_dir that indicates direction in which xN[q] has to +// change (+1 means increasing, -1 means decreasing). +// +// If the choice cannot be made, because the current basic solution is +// dual feasible, the routine sets the number q to 0. */ + +void ssx_chuzc(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int dir = (ssx->dir == SSX_MIN ? +1 : -1); + int *Q_col = ssx->Q_col; + int *stat = ssx->stat; + mpq_t *cbar = ssx->cbar; + int j, k, s, q, q_dir; + double best, temp; + /* nothing is chosen so far */ + q = 0, q_dir = 0, best = 0.0; + /* look through the list of non-basic variables */ + for (j = 1; j <= n; j++) + { k = Q_col[m+j]; /* x[k] = xN[j] */ + s = dir * mpq_sgn(cbar[j]); + if ((stat[k] == SSX_NF || stat[k] == SSX_NL) && s < 0 || + (stat[k] == SSX_NF || stat[k] == SSX_NU) && s > 0) + { /* reduced cost of xN[j] indicates possible improving of + the objective function */ + temp = fabs(mpq_get_d(cbar[j])); + xassert(temp != 0.0); + if (q == 0 || best < temp) + q = j, q_dir = - s, best = temp; + } + } + ssx->q = q, ssx->q_dir = q_dir; + return; +} + +/*---------------------------------------------------------------------- +// ssx_chuzr - choose pivot row. +// +// This routine looks through elements of q-th column of the simplex +// table and chooses basic variable xB[p] which should leave the basis. +// +// The choice is based on the standard (textbook) ratio test. +// +// If xB[p] has been chosen, the routine stores its number p and also +// sets its non-basic status p_stat which should be assigned to xB[p] +// when it has left the basis and become xN[q]. +// +// Special case p < 0 means that xN[q] is double-bounded variable and +// it reaches its opposite bound before any basic variable does that, +// so the current basis remains unchanged. +// +// If the choice cannot be made, because xN[q] can infinitely change in +// the feasible direction, the routine sets the number p to 0. */ + +void ssx_chuzr(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int *type = ssx->type; + mpq_t *lb = ssx->lb; + mpq_t *ub = ssx->ub; + int *Q_col = ssx->Q_col; + mpq_t *bbar = ssx->bbar; + int q = ssx->q; + mpq_t *aq = ssx->aq; + int q_dir = ssx->q_dir; + int i, k, s, t, p, p_stat; + mpq_t teta, temp; + mpq_init(teta); + mpq_init(temp); + xassert(1 <= q && q <= n); + xassert(q_dir == +1 || q_dir == -1); + /* nothing is chosen so far */ + p = 0, p_stat = 0; + /* look through the list of basic variables */ + for (i = 1; i <= m; i++) + { s = q_dir * mpq_sgn(aq[i]); + if (s < 0) + { /* xB[i] decreases */ + k = Q_col[i]; /* x[k] = xB[i] */ + t = type[k]; + if (t == SSX_LO || t == SSX_DB || t == SSX_FX) + { /* xB[i] has finite lower bound */ + mpq_sub(temp, bbar[i], lb[k]); + mpq_div(temp, temp, aq[i]); + mpq_abs(temp, temp); + if (p == 0 || mpq_cmp(teta, temp) > 0) + { p = i; + p_stat = (t == SSX_FX ? SSX_NS : SSX_NL); + mpq_set(teta, temp); + } + } + } + else if (s > 0) + { /* xB[i] increases */ + k = Q_col[i]; /* x[k] = xB[i] */ + t = type[k]; + if (t == SSX_UP || t == SSX_DB || t == SSX_FX) + { /* xB[i] has finite upper bound */ + mpq_sub(temp, bbar[i], ub[k]); + mpq_div(temp, temp, aq[i]); + mpq_abs(temp, temp); + if (p == 0 || mpq_cmp(teta, temp) > 0) + { p = i; + p_stat = (t == SSX_FX ? SSX_NS : SSX_NU); + mpq_set(teta, temp); + } + } + } + /* if something has been chosen and the ratio test indicates + exact degeneracy, the search can be finished */ + if (p != 0 && mpq_sgn(teta) == 0) break; + } + /* if xN[q] is double-bounded, check if it can reach its opposite + bound before any basic variable */ + k = Q_col[m+q]; /* x[k] = xN[q] */ + if (type[k] == SSX_DB) + { mpq_sub(temp, ub[k], lb[k]); + if (p == 0 || mpq_cmp(teta, temp) > 0) + { p = -1; + p_stat = -1; + mpq_set(teta, temp); + } + } + ssx->p = p; + ssx->p_stat = p_stat; + /* if xB[p] has been chosen, determine its actual change in the + adjacent basis (it has the same sign as q_dir) */ + if (p != 0) + { xassert(mpq_sgn(teta) >= 0); + if (q_dir > 0) + mpq_set(ssx->delta, teta); + else + mpq_neg(ssx->delta, teta); + } + mpq_clear(teta); + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_update_bbar - update values of basic variables. +// +// This routine recomputes the current values of basic variables for +// the adjacent basis. +// +// The simplex table for the current basis is the following: +// +// xB[i] = sum{j in 1..n} alfa[i,j] * xN[q], i = 1,...,m +// +// therefore +// +// delta xB[i] = alfa[i,q] * delta xN[q], i = 1,...,m +// +// where delta xN[q] = xN.new[q] - xN[q] is the change of xN[q] in the +// adjacent basis, and delta xB[i] = xB.new[i] - xB[i] is the change of +// xB[i]. This gives formulae for recomputing values of xB[i]: +// +// xB.new[p] = xN[q] + delta xN[q] +// +// (because xN[q] becomes xB[p] in the adjacent basis), and +// +// xB.new[i] = xB[i] + alfa[i,q] * delta xN[q], i != p +// +// for other basic variables. */ + +void ssx_update_bbar(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *bbar = ssx->bbar; + mpq_t *cbar = ssx->cbar; + int p = ssx->p; + int q = ssx->q; + mpq_t *aq = ssx->aq; + int i; + mpq_t temp; + mpq_init(temp); + xassert(1 <= q && q <= n); + if (p < 0) + { /* xN[q] is double-bounded and goes to its opposite bound */ + /* nop */; + } + else + { /* xN[q] becomes xB[p] in the adjacent basis */ + /* xB.new[p] = xN[q] + delta xN[q] */ + xassert(1 <= p && p <= m); + ssx_get_xNj(ssx, q, temp); + mpq_add(bbar[p], temp, ssx->delta); + } + /* update values of other basic variables depending on xN[q] */ + for (i = 1; i <= m; i++) + { if (i == p) continue; + /* xB.new[i] = xB[i] + alfa[i,q] * delta xN[q] */ + if (mpq_sgn(aq[i]) == 0) continue; + mpq_mul(temp, aq[i], ssx->delta); + mpq_add(bbar[i], bbar[i], temp); + } +#if 1 + /* update value of the objective function */ + /* z.new = z + d[q] * delta xN[q] */ + mpq_mul(temp, cbar[q], ssx->delta); + mpq_add(bbar[0], bbar[0], temp); +#endif + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +-- ssx_update_pi - update simplex multipliers. +-- +-- This routine recomputes the vector of simplex multipliers for the +-- adjacent basis. */ + +void ssx_update_pi(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *pi = ssx->pi; + mpq_t *cbar = ssx->cbar; + int p = ssx->p; + int q = ssx->q; + mpq_t *aq = ssx->aq; + mpq_t *rho = ssx->rho; + int i; + mpq_t new_dq, temp; + mpq_init(new_dq); + mpq_init(temp); + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); + /* compute d[q] in the adjacent basis */ + mpq_div(new_dq, cbar[q], aq[p]); + /* update the vector of simplex multipliers */ + for (i = 1; i <= m; i++) + { if (mpq_sgn(rho[i]) == 0) continue; + mpq_mul(temp, new_dq, rho[i]); + mpq_sub(pi[i], pi[i], temp); + } + mpq_clear(new_dq); + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_update_cbar - update reduced costs of non-basic variables. +// +// This routine recomputes the vector of reduced costs of non-basic +// variables for the adjacent basis. */ + +void ssx_update_cbar(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *cbar = ssx->cbar; + int p = ssx->p; + int q = ssx->q; + mpq_t *ap = ssx->ap; + int j; + mpq_t temp; + mpq_init(temp); + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); + /* compute d[q] in the adjacent basis */ + /* d.new[q] = d[q] / alfa[p,q] */ + mpq_div(cbar[q], cbar[q], ap[q]); + /* update reduced costs of other non-basic variables */ + for (j = 1; j <= n; j++) + { if (j == q) continue; + /* d.new[j] = d[j] - (alfa[p,j] / alfa[p,q]) * d[q] */ + if (mpq_sgn(ap[j]) == 0) continue; + mpq_mul(temp, ap[j], cbar[q]); + mpq_sub(cbar[j], cbar[j], temp); + } + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_change_basis - change current basis to adjacent one. +// +// This routine changes the current basis to the adjacent one swapping +// basic variable xB[p] and non-basic variable xN[q]. */ + +void ssx_change_basis(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int *type = ssx->type; + int *stat = ssx->stat; + int *Q_row = ssx->Q_row; + int *Q_col = ssx->Q_col; + int p = ssx->p; + int q = ssx->q; + int p_stat = ssx->p_stat; + int k, kp, kq; + if (p < 0) + { /* special case: xN[q] goes to its opposite bound */ + xassert(1 <= q && q <= n); + k = Q_col[m+q]; /* x[k] = xN[q] */ + xassert(type[k] == SSX_DB); + switch (stat[k]) + { case SSX_NL: + stat[k] = SSX_NU; + break; + case SSX_NU: + stat[k] = SSX_NL; + break; + default: + xassert(stat != stat); + } + } + else + { /* xB[p] leaves the basis, xN[q] enters the basis */ + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); + kp = Q_col[p]; /* x[kp] = xB[p] */ + kq = Q_col[m+q]; /* x[kq] = xN[q] */ + /* check non-basic status of xB[p] which becomes xN[q] */ + switch (type[kp]) + { case SSX_FR: + xassert(p_stat == SSX_NF); + break; + case SSX_LO: + xassert(p_stat == SSX_NL); + break; + case SSX_UP: + xassert(p_stat == SSX_NU); + break; + case SSX_DB: + xassert(p_stat == SSX_NL || p_stat == SSX_NU); + break; + case SSX_FX: + xassert(p_stat == SSX_NS); + break; + default: + xassert(type != type); + } + /* swap xB[p] and xN[q] */ + stat[kp] = (char)p_stat, stat[kq] = SSX_BS; + Q_row[kp] = m+q, Q_row[kq] = p; + Q_col[p] = kq, Q_col[m+q] = kp; + /* update factorization of the basis matrix */ + if (bfx_update(ssx->binv, p)) + { if (ssx_factorize(ssx)) + xassert(("Internal error: basis matrix is singular", 0)); + } + } + return; +} + +/*---------------------------------------------------------------------- +// ssx_delete - delete simplex solver workspace. +// +// This routine deletes the simplex solver workspace freeing all the +// memory allocated to this object. */ + +void ssx_delete(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int nnz = ssx->A_ptr[n+1]-1; + int i, j, k; + xfree(ssx->type); + for (k = 1; k <= m+n; k++) mpq_clear(ssx->lb[k]); + xfree(ssx->lb); + for (k = 1; k <= m+n; k++) mpq_clear(ssx->ub[k]); + xfree(ssx->ub); + for (k = 0; k <= m+n; k++) mpq_clear(ssx->coef[k]); + xfree(ssx->coef); + xfree(ssx->A_ptr); + xfree(ssx->A_ind); + for (k = 1; k <= nnz; k++) mpq_clear(ssx->A_val[k]); + xfree(ssx->A_val); + xfree(ssx->stat); + xfree(ssx->Q_row); + xfree(ssx->Q_col); + bfx_delete_binv(ssx->binv); + for (i = 0; i <= m; i++) mpq_clear(ssx->bbar[i]); + xfree(ssx->bbar); + for (i = 1; i <= m; i++) mpq_clear(ssx->pi[i]); + xfree(ssx->pi); + for (j = 1; j <= n; j++) mpq_clear(ssx->cbar[j]); + xfree(ssx->cbar); + for (i = 1; i <= m; i++) mpq_clear(ssx->rho[i]); + xfree(ssx->rho); + for (j = 1; j <= n; j++) mpq_clear(ssx->ap[j]); + xfree(ssx->ap); + for (i = 1; i <= m; i++) mpq_clear(ssx->aq[i]); + xfree(ssx->aq); + mpq_clear(ssx->delta); + xfree(ssx); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpssx02.c b/resources/3rdparty/glpk-4.53/src/glpssx02.c new file mode 100644 index 000000000..4b3ea97d6 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glpssx02.c @@ -0,0 +1,479 @@ +/* glpssx02.c (simplex method, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glpssx.h" + +static void show_progress(SSX *ssx, int phase) +{ /* this auxiliary routine displays information about progress of + the search */ + int i, def = 0; + for (i = 1; i <= ssx->m; i++) + if (ssx->type[ssx->Q_col[i]] == SSX_FX) def++; + xprintf("%s%6d: %s = %22.15g (%d)\n", phase == 1 ? " " : "*", + ssx->it_cnt, phase == 1 ? "infsum" : "objval", + mpq_get_d(ssx->bbar[0]), def); +#if 0 + ssx->tm_lag = utime(); +#else + ssx->tm_lag = xtime(); +#endif + return; +} + +/*---------------------------------------------------------------------- +// ssx_phase_I - find primal feasible solution. +// +// This routine implements phase I of the primal simplex method. +// +// On exit the routine returns one of the following codes: +// +// 0 - feasible solution found; +// 1 - problem has no feasible solution; +// 2 - iterations limit exceeded; +// 3 - time limit exceeded. +----------------------------------------------------------------------*/ + +int ssx_phase_I(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int *type = ssx->type; + mpq_t *lb = ssx->lb; + mpq_t *ub = ssx->ub; + mpq_t *coef = ssx->coef; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + mpq_t *bbar = ssx->bbar; + mpq_t *pi = ssx->pi; + mpq_t *cbar = ssx->cbar; + int *orig_type, orig_dir; + mpq_t *orig_lb, *orig_ub, *orig_coef; + int i, k, ret; + /* save components of the original LP problem, which are changed + by the routine */ + orig_type = xcalloc(1+m+n, sizeof(int)); + orig_lb = xcalloc(1+m+n, sizeof(mpq_t)); + orig_ub = xcalloc(1+m+n, sizeof(mpq_t)); + orig_coef = xcalloc(1+m+n, sizeof(mpq_t)); + for (k = 1; k <= m+n; k++) + { orig_type[k] = type[k]; + mpq_init(orig_lb[k]); + mpq_set(orig_lb[k], lb[k]); + mpq_init(orig_ub[k]); + mpq_set(orig_ub[k], ub[k]); + } + orig_dir = ssx->dir; + for (k = 0; k <= m+n; k++) + { mpq_init(orig_coef[k]); + mpq_set(orig_coef[k], coef[k]); + } + /* build an artificial basic solution, which is primal feasible, + and also build an auxiliary objective function to minimize the + sum of infeasibilities for the original problem */ + ssx->dir = SSX_MIN; + for (k = 0; k <= m+n; k++) mpq_set_si(coef[k], 0, 1); + mpq_set_si(bbar[0], 0, 1); + for (i = 1; i <= m; i++) + { int t; + k = Q_col[i]; /* x[k] = xB[i] */ + t = type[k]; + if (t == SSX_LO || t == SSX_DB || t == SSX_FX) + { /* in the original problem x[k] has lower bound */ + if (mpq_cmp(bbar[i], lb[k]) < 0) + { /* which is violated */ + type[k] = SSX_UP; + mpq_set(ub[k], lb[k]); + mpq_set_si(lb[k], 0, 1); + mpq_set_si(coef[k], -1, 1); + mpq_add(bbar[0], bbar[0], ub[k]); + mpq_sub(bbar[0], bbar[0], bbar[i]); + } + } + if (t == SSX_UP || t == SSX_DB || t == SSX_FX) + { /* in the original problem x[k] has upper bound */ + if (mpq_cmp(bbar[i], ub[k]) > 0) + { /* which is violated */ + type[k] = SSX_LO; + mpq_set(lb[k], ub[k]); + mpq_set_si(ub[k], 0, 1); + mpq_set_si(coef[k], +1, 1); + mpq_add(bbar[0], bbar[0], bbar[i]); + mpq_sub(bbar[0], bbar[0], lb[k]); + } + } + } + /* now the initial basic solution should be primal feasible due + to changes of bounds of some basic variables, which turned to + implicit artifical variables */ + /* compute simplex multipliers and reduced costs */ + ssx_eval_pi(ssx); + ssx_eval_cbar(ssx); + /* display initial progress of the search */ + show_progress(ssx, 1); + /* main loop starts here */ + for (;;) + { /* display current progress of the search */ +#if 0 + if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001) +#else + if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001) +#endif + show_progress(ssx, 1); + /* we do not need to wait until all artificial variables have + left the basis */ + if (mpq_sgn(bbar[0]) == 0) + { /* the sum of infeasibilities is zero, therefore the current + solution is primal feasible for the original problem */ + ret = 0; + break; + } + /* check if the iterations limit has been exhausted */ + if (ssx->it_lim == 0) + { ret = 2; + break; + } + /* check if the time limit has been exhausted */ +#if 0 + if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg) +#else + if (ssx->tm_lim >= 0.0 && + ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg)) +#endif + { ret = 3; + break; + } + /* choose non-basic variable xN[q] */ + ssx_chuzc(ssx); + /* if xN[q] cannot be chosen, the sum of infeasibilities is + minimal but non-zero; therefore the original problem has no + primal feasible solution */ + if (ssx->q == 0) + { ret = 1; + break; + } + /* compute q-th column of the simplex table */ + ssx_eval_col(ssx); + /* choose basic variable xB[p] */ + ssx_chuzr(ssx); + /* the sum of infeasibilities cannot be negative, therefore + the auxiliary lp problem cannot have unbounded solution */ + xassert(ssx->p != 0); + /* update values of basic variables */ + ssx_update_bbar(ssx); + if (ssx->p > 0) + { /* compute p-th row of the inverse inv(B) */ + ssx_eval_rho(ssx); + /* compute p-th row of the simplex table */ + ssx_eval_row(ssx); + xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0); + /* update simplex multipliers */ + ssx_update_pi(ssx); + /* update reduced costs of non-basic variables */ + ssx_update_cbar(ssx); + } + /* xB[p] is leaving the basis; if it is implicit artificial + variable, the corresponding residual vanishes; therefore + bounds of this variable should be restored to the original + values */ + if (ssx->p > 0) + { k = Q_col[ssx->p]; /* x[k] = xB[p] */ + if (type[k] != orig_type[k]) + { /* x[k] is implicit artificial variable */ + type[k] = orig_type[k]; + mpq_set(lb[k], orig_lb[k]); + mpq_set(ub[k], orig_ub[k]); + xassert(ssx->p_stat == SSX_NL || ssx->p_stat == SSX_NU); + ssx->p_stat = (ssx->p_stat == SSX_NL ? SSX_NU : SSX_NL); + if (type[k] == SSX_FX) ssx->p_stat = SSX_NS; + /* nullify the objective coefficient at x[k] */ + mpq_set_si(coef[k], 0, 1); + /* since coef[k] has been changed, we need to compute + new reduced cost of x[k], which it will have in the + adjacent basis */ + /* the formula d[j] = cN[j] - pi' * N[j] is used (note + that the vector pi is not changed, because it depends + on objective coefficients at basic variables, but in + the adjacent basis, for which the vector pi has been + just recomputed, x[k] is non-basic) */ + if (k <= m) + { /* x[k] is auxiliary variable */ + mpq_neg(cbar[ssx->q], pi[k]); + } + else + { /* x[k] is structural variable */ + int ptr; + mpq_t temp; + mpq_init(temp); + mpq_set_si(cbar[ssx->q], 0, 1); + for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) + { mpq_mul(temp, pi[A_ind[ptr]], A_val[ptr]); + mpq_add(cbar[ssx->q], cbar[ssx->q], temp); + } + mpq_clear(temp); + } + } + } + /* jump to the adjacent vertex of the polyhedron */ + ssx_change_basis(ssx); + /* one simplex iteration has been performed */ + if (ssx->it_lim > 0) ssx->it_lim--; + ssx->it_cnt++; + } + /* display final progress of the search */ + show_progress(ssx, 1); + /* restore components of the original problem, which were changed + by the routine */ + for (k = 1; k <= m+n; k++) + { type[k] = orig_type[k]; + mpq_set(lb[k], orig_lb[k]); + mpq_clear(orig_lb[k]); + mpq_set(ub[k], orig_ub[k]); + mpq_clear(orig_ub[k]); + } + ssx->dir = orig_dir; + for (k = 0; k <= m+n; k++) + { mpq_set(coef[k], orig_coef[k]); + mpq_clear(orig_coef[k]); + } + xfree(orig_type); + xfree(orig_lb); + xfree(orig_ub); + xfree(orig_coef); + /* return to the calling program */ + return ret; +} + +/*---------------------------------------------------------------------- +// ssx_phase_II - find optimal solution. +// +// This routine implements phase II of the primal simplex method. +// +// On exit the routine returns one of the following codes: +// +// 0 - optimal solution found; +// 1 - problem has unbounded solution; +// 2 - iterations limit exceeded; +// 3 - time limit exceeded. +----------------------------------------------------------------------*/ + +int ssx_phase_II(SSX *ssx) +{ int ret; + /* display initial progress of the search */ + show_progress(ssx, 2); + /* main loop starts here */ + for (;;) + { /* display current progress of the search */ +#if 0 + if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001) +#else + if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001) +#endif + show_progress(ssx, 2); + /* check if the iterations limit has been exhausted */ + if (ssx->it_lim == 0) + { ret = 2; + break; + } + /* check if the time limit has been exhausted */ +#if 0 + if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg) +#else + if (ssx->tm_lim >= 0.0 && + ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg)) +#endif + { ret = 3; + break; + } + /* choose non-basic variable xN[q] */ + ssx_chuzc(ssx); + /* if xN[q] cannot be chosen, the current basic solution is + dual feasible and therefore optimal */ + if (ssx->q == 0) + { ret = 0; + break; + } + /* compute q-th column of the simplex table */ + ssx_eval_col(ssx); + /* choose basic variable xB[p] */ + ssx_chuzr(ssx); + /* if xB[p] cannot be chosen, the problem has no dual feasible + solution (i.e. unbounded) */ + if (ssx->p == 0) + { ret = 1; + break; + } + /* update values of basic variables */ + ssx_update_bbar(ssx); + if (ssx->p > 0) + { /* compute p-th row of the inverse inv(B) */ + ssx_eval_rho(ssx); + /* compute p-th row of the simplex table */ + ssx_eval_row(ssx); + xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0); +#if 0 + /* update simplex multipliers */ + ssx_update_pi(ssx); +#endif + /* update reduced costs of non-basic variables */ + ssx_update_cbar(ssx); + } + /* jump to the adjacent vertex of the polyhedron */ + ssx_change_basis(ssx); + /* one simplex iteration has been performed */ + if (ssx->it_lim > 0) ssx->it_lim--; + ssx->it_cnt++; + } + /* display final progress of the search */ + show_progress(ssx, 2); + /* return to the calling program */ + return ret; +} + +/*---------------------------------------------------------------------- +// ssx_driver - base driver to exact simplex method. +// +// This routine is a base driver to a version of the primal simplex +// method using exact (bignum) arithmetic. +// +// On exit the routine returns one of the following codes: +// +// 0 - optimal solution found; +// 1 - problem has no feasible solution; +// 2 - problem has unbounded solution; +// 3 - iterations limit exceeded (phase I); +// 4 - iterations limit exceeded (phase II); +// 5 - time limit exceeded (phase I); +// 6 - time limit exceeded (phase II); +// 7 - initial basis matrix is exactly singular. +----------------------------------------------------------------------*/ + +int ssx_driver(SSX *ssx) +{ int m = ssx->m; + int *type = ssx->type; + mpq_t *lb = ssx->lb; + mpq_t *ub = ssx->ub; + int *Q_col = ssx->Q_col; + mpq_t *bbar = ssx->bbar; + int i, k, ret; + ssx->tm_beg = xtime(); + /* factorize the initial basis matrix */ + if (ssx_factorize(ssx)) + { xprintf("Initial basis matrix is singular\n"); + ret = 7; + goto done; + } + /* compute values of basic variables */ + ssx_eval_bbar(ssx); + /* check if the initial basic solution is primal feasible */ + for (i = 1; i <= m; i++) + { int t; + k = Q_col[i]; /* x[k] = xB[i] */ + t = type[k]; + if (t == SSX_LO || t == SSX_DB || t == SSX_FX) + { /* x[k] has lower bound */ + if (mpq_cmp(bbar[i], lb[k]) < 0) + { /* which is violated */ + break; + } + } + if (t == SSX_UP || t == SSX_DB || t == SSX_FX) + { /* x[k] has upper bound */ + if (mpq_cmp(bbar[i], ub[k]) > 0) + { /* which is violated */ + break; + } + } + } + if (i > m) + { /* no basic variable violates its bounds */ + ret = 0; + goto skip; + } + /* phase I: find primal feasible solution */ + ret = ssx_phase_I(ssx); + switch (ret) + { case 0: + ret = 0; + break; + case 1: + xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); + ret = 1; + break; + case 2: + xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n"); + ret = 3; + break; + case 3: + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + ret = 5; + break; + default: + xassert(ret != ret); + } + /* compute values of basic variables (actually only the objective + value needs to be computed) */ + ssx_eval_bbar(ssx); +skip: /* compute simplex multipliers */ + ssx_eval_pi(ssx); + /* compute reduced costs of non-basic variables */ + ssx_eval_cbar(ssx); + /* if phase I failed, do not start phase II */ + if (ret != 0) goto done; + /* phase II: find optimal solution */ + ret = ssx_phase_II(ssx); + switch (ret) + { case 0: + xprintf("OPTIMAL SOLUTION FOUND\n"); + ret = 0; + break; + case 1: + xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n"); + ret = 2; + break; + case 2: + xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n"); + ret = 4; + break; + case 3: + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + ret = 6; + break; + default: + xassert(ret != ret); + } +done: /* decrease the time limit by the spent amount of time */ + if (ssx->tm_lim >= 0.0) +#if 0 + { ssx->tm_lim -= utime() - ssx->tm_beg; +#else + { ssx->tm_lim -= xdifftime(xtime(), ssx->tm_beg); +#endif + if (ssx->tm_lim < 0.0) ssx->tm_lim = 0.0; + } + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glptsp.c b/resources/3rdparty/glpk-4.53/src/glptsp.c new file mode 100644 index 000000000..ceb569584 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glptsp.c @@ -0,0 +1,667 @@ +/* glptsp.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "glptsp.h" +#include "misc.h" + +#define xfault xerror + +/*---------------------------------------------------------------------- +-- tsp_read_data - read TSP instance data. +-- +-- *Synopsis* +-- +-- #include "glptsp.h" +-- TSP *tsp_read_data(char *fname); +-- +-- *Description* +-- +-- The routine tsp_read_data reads a TSP (or related problem) instance +-- data from the text file, whose name is the character string fname. +-- +-- For detailed description of the format recognized by the routine see +-- the report: G.Reinelt, TSPLIB 95. +-- +-- *Returns* +-- +-- If no error occurred, the routine tsp_read_data returns a pointer to +-- the TSP instance data block, which contains loaded data. In the case +-- of error the routine prints an error message and returns NULL. */ + +struct dsa +{ /* dynamic storage area used by the routine tsp_read_data */ + char *fname; + /* name of the input text file */ + FILE *fp; + /* stream assigned to the input text file */ + int seqn; + /* line sequential number */ + int c; + /* current character */ + char token[255+1]; + /* current token */ +}; + +static int get_char(struct dsa *dsa) +{ dsa->c = fgetc(dsa->fp); + if (ferror(dsa->fp)) + { xprintf("%s:%d: read error - %s\n", + dsa->fname, dsa->seqn, strerror(errno)); + return 1; + } + if (feof(dsa->fp)) + dsa->c = EOF; + else if (dsa->c == '\n') + dsa->seqn++; + else if (isspace(dsa->c)) + dsa->c = ' '; + else if (iscntrl(dsa->c)) + { xprintf("%s:%d: invalid control character 0x%02X\n", + dsa->fname, dsa->seqn, dsa->c); + return 1; + } + return 0; +} + +static int skip_spaces(struct dsa *dsa, int across) +{ while (dsa->c == ' ' || (across && dsa->c == '\n')) + if (get_char(dsa)) return 1; + return 0; +} + +static int scan_keyword(struct dsa *dsa) +{ int len = 0; + if (skip_spaces(dsa, 0)) return 1; + dsa->token[0] = '\0'; + while (isalnum(dsa->c) || dsa->c == '_') + { if (len == 31) + { xprintf("%s:%d: keyword `%s...' too long\n", dsa->fname, + dsa->seqn, dsa->token); + return 1; + } + dsa->token[len++] = (char)dsa->c, dsa->token[len] = '\0'; + if (get_char(dsa)) return 1; + } + if (len == 0) + { xprintf("%s:%d: missing keyword\n", dsa->fname, dsa->seqn); + return 1; + } + return 0; +} + +static int check_colon(struct dsa *dsa) +{ if (skip_spaces(dsa, 0)) return 1; + if (dsa->c != ':') + { xprintf("%s:%d: missing colon after `%s'\n", dsa->fname, + dsa->seqn, dsa->token); + return 1; + } + if (get_char(dsa)) return 1; + return 0; +} + +static int scan_token(struct dsa *dsa, int across) +{ int len = 0; + if (skip_spaces(dsa, across)) return 1; + dsa->token[0] = '\0'; + while (!(dsa->c == EOF || dsa->c == '\n' || dsa->c == ' ')) + { if (len == 255) + { dsa->token[31] = '\0'; + xprintf("%s:%d: token `%s...' too long\n", dsa->fname, + dsa->seqn, dsa->token); + return 1; + } + dsa->token[len++] = (char)dsa->c, dsa->token[len] = '\0'; + if (get_char(dsa)) return 1; + } + return 0; +} + +static int check_newline(struct dsa *dsa) +{ if (skip_spaces(dsa, 0)) return 1; + if (!(dsa->c == EOF || dsa->c == '\n')) + { xprintf("%s:%d: extra symbols detected\n", dsa->fname, + dsa->seqn); + return 1; + } + if (get_char(dsa)) return 1; + return 0; +} + +static int scan_comment(struct dsa *dsa) +{ int len = 0; + if (skip_spaces(dsa, 0)) return 1; + dsa->token[0] = '\0'; + while (!(dsa->c == EOF || dsa->c == '\n')) + { if (len == 255) + { xprintf("%s:%d: comment too long\n", dsa->fname, dsa->seqn) + ; + return 1; + } + dsa->token[len++] = (char)dsa->c, dsa->token[len] = '\0'; + if (get_char(dsa)) return 1; + } + return 0; +} + +static int scan_integer(struct dsa *dsa, int across, int *val) +{ if (scan_token(dsa, across)) return 1; + if (strlen(dsa->token) == 0) + { xprintf("%s:%d: missing integer\n", dsa->fname, dsa->seqn); + return 1; + } + if (str2int(dsa->token, val)) + { xprintf("%s:%d: integer `%s' invalid\n", dsa->fname, dsa->seqn + , dsa->token); + return 1; + } + return 0; +} + +static int scan_number(struct dsa *dsa, int across, double *val) +{ if (scan_token(dsa, across)) return 1; + if (strlen(dsa->token) == 0) + { xprintf("%s:%d: missing number\n", dsa->fname, dsa->seqn); + return 1; + } + if (str2num(dsa->token, val)) + { xprintf("%s:%d: number `%s' invalid\n", dsa->fname, dsa->seqn, + dsa->token); + return 1; + } + return 0; +} + +TSP *tsp_read_data(char *fname) +{ struct dsa _dsa, *dsa = &_dsa; + TSP *tsp = NULL; + dsa->fname = fname; + xprintf("tsp_read_data: reading TSP data from `%s'...\n", + dsa->fname); + dsa->fp = fopen(dsa->fname, "r"); + if (dsa->fp == NULL) + { xprintf("tsp_read_data: unable to open `%s' - %s\n", + dsa->fname, strerror(errno)); + goto fail; + } + tsp = xmalloc(sizeof(TSP)); + tsp->name = NULL; + tsp->type = TSP_UNDEF; + tsp->comment = NULL; + tsp->dimension = 0; + tsp->edge_weight_type = TSP_UNDEF; + tsp->edge_weight_format = TSP_UNDEF; + tsp->display_data_type = TSP_UNDEF; + tsp->node_x_coord = NULL; + tsp->node_y_coord = NULL; + tsp->dply_x_coord = NULL; + tsp->dply_y_coord = NULL; + tsp->tour = NULL; + tsp->edge_weight = NULL; + dsa->seqn = 1; + if (get_char(dsa)) goto fail; +loop: if (scan_keyword(dsa)) goto fail; + if (strcmp(dsa->token, "NAME") == 0) + { if (tsp->name != NULL) + { xprintf("%s:%d: NAME entry multiply defined\n", dsa->fname, + dsa->seqn); + goto fail; + } + if (check_colon(dsa)) goto fail; + if (scan_token(dsa, 0)) goto fail; + if (strlen(dsa->token) == 0) + { xprintf("%s:%d: NAME entry incomplete\n", dsa->fname, + dsa->seqn); + goto fail; + } + tsp->name = xmalloc(strlen(dsa->token) + 1); + strcpy(tsp->name, dsa->token); + xprintf("tsp_read_data: NAME: %s\n", tsp->name); + if (check_newline(dsa)) goto fail; + } + else if (strcmp(dsa->token, "TYPE") == 0) + { if (tsp->type != TSP_UNDEF) + { xprintf("%s:%d: TYPE entry multiply defined\n", dsa->fname, + dsa->seqn); + goto fail; + } + if (check_colon(dsa)) goto fail; + if (scan_keyword(dsa)) goto fail; + if (strcmp(dsa->token, "TSP") == 0) + tsp->type = TSP_TSP; + else if (strcmp(dsa->token, "ATSP") == 0) + tsp->type = TSP_ATSP; + else if (strcmp(dsa->token, "TOUR") == 0) + tsp->type = TSP_TOUR; + else + { xprintf("%s:%d: data type `%s' not recognized\n", + dsa->fname, dsa->seqn, dsa->token); + goto fail; + } + xprintf("tsp_read_data: TYPE: %s\n", dsa->token); + if (check_newline(dsa)) goto fail; + } + else if (strcmp(dsa->token, "COMMENT") == 0) + { if (tsp->comment != NULL) + { xprintf("%s:%d: COMMENT entry multiply defined\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (check_colon(dsa)) goto fail; + if (scan_comment(dsa)) goto fail; + tsp->comment = xmalloc(strlen(dsa->token) + 1); + strcpy(tsp->comment, dsa->token); + xprintf("tsp_read_data: COMMENT: %s\n", tsp->comment); + if (check_newline(dsa)) goto fail; + } + else if (strcmp(dsa->token, "DIMENSION") == 0) + { if (tsp->dimension != 0) + { xprintf("%s:%d: DIMENSION entry multiply defined\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (check_colon(dsa)) goto fail; + if (scan_integer(dsa, 0, &tsp->dimension)) goto fail; + if (tsp->dimension < 1) + { xprintf("%s:%d: invalid dimension\n", dsa->fname, + dsa->seqn); + goto fail; + } + xprintf("tsp_read_data: DIMENSION: %d\n", tsp->dimension); + if (check_newline(dsa)) goto fail; + } + else if (strcmp(dsa->token, "EDGE_WEIGHT_TYPE") == 0) + { if (tsp->edge_weight_type != TSP_UNDEF) + { xprintf("%s:%d: EDGE_WEIGHT_TYPE entry multiply defined\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (check_colon(dsa)) goto fail; + if (scan_keyword(dsa)) goto fail; + if (strcmp(dsa->token, "GEO") == 0) + tsp->edge_weight_type = TSP_GEO; + else if (strcmp(dsa->token, "EUC_2D") == 0) + tsp->edge_weight_type = TSP_EUC_2D; + else if (strcmp(dsa->token, "ATT") == 0) + tsp->edge_weight_type = TSP_ATT; + else if (strcmp(dsa->token, "EXPLICIT") == 0) + tsp->edge_weight_type = TSP_EXPLICIT; + else if (strcmp(dsa->token, "CEIL_2D") == 0) + tsp->edge_weight_type = TSP_CEIL_2D; + else + { xprintf("%s:%d: edge weight type `%s' not recognized\n", + dsa->fname, dsa->seqn, dsa->token); + goto fail; + } + xprintf("tsp_read_data: EDGE_WEIGHT_TYPE: %s\n", dsa->token); + if (check_newline(dsa)) goto fail; + } + else if (strcmp(dsa->token, "EDGE_WEIGHT_FORMAT") == 0) + { if (tsp->edge_weight_format != TSP_UNDEF) + { xprintf( + "%s:%d: EDGE_WEIGHT_FORMAT entry multiply defined\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (check_colon(dsa)) goto fail; + if (scan_keyword(dsa)) goto fail; + if (strcmp(dsa->token, "UPPER_ROW") == 0) + tsp->edge_weight_format = TSP_UPPER_ROW; + else if (strcmp(dsa->token, "FULL_MATRIX") == 0) + tsp->edge_weight_format = TSP_FULL_MATRIX; + else if (strcmp(dsa->token, "FUNCTION") == 0) + tsp->edge_weight_format = TSP_FUNCTION; + else if (strcmp(dsa->token, "LOWER_DIAG_ROW") == 0) + tsp->edge_weight_format = TSP_LOWER_DIAG_ROW; + else + { xprintf("%s:%d: edge weight format `%s' not recognized\n", + dsa->fname, dsa->seqn, dsa->token); + goto fail; + } + xprintf("tsp_read_data: EDGE_WEIGHT_FORMAT: %s\n", dsa->token); + if (check_newline(dsa)) goto fail; + } + else if (strcmp(dsa->token, "DISPLAY_DATA_TYPE") == 0) + { if (tsp->display_data_type != TSP_UNDEF) + { xprintf("%s:%d: DISPLAY_DATA_TYPE entry multiply defined\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (check_colon(dsa)) goto fail; + if (scan_keyword(dsa)) goto fail; + if (strcmp(dsa->token, "COORD_DISPLAY") == 0) + tsp->display_data_type = TSP_COORD_DISPLAY; + else if (strcmp(dsa->token, "TWOD_DISPLAY") == 0) + tsp->display_data_type = TSP_TWOD_DISPLAY; + else + { xprintf("%s:%d: display data type `%s' not recognized\n", + dsa->fname, dsa->seqn, dsa->token); + goto fail; + } + xprintf("tsp_read_data: DISPLAY_DATA_TYPE: %s\n", dsa->token); + if (check_newline(dsa)) goto fail; + } + else if (strcmp(dsa->token, "NODE_COORD_SECTION") == 0) + { int n = tsp->dimension, k, node; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (tsp->node_x_coord != NULL) + { xprintf("%s:%d: NODE_COORD_SECTION multiply specified\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (check_newline(dsa)) goto fail; + tsp->node_x_coord = xcalloc(1+n, sizeof(double)); + tsp->node_y_coord = xcalloc(1+n, sizeof(double)); + for (node = 1; node <= n; node++) + tsp->node_x_coord[node] = tsp->node_y_coord[node] = DBL_MAX; + for (k = 1; k <= n; k++) + { if (scan_integer(dsa, 0, &node)) goto fail; + if (!(1 <= node && node <= n)) + { xprintf("%s:%d: invalid node number %d\n", dsa->fname, + dsa->seqn, node); + goto fail; + } + if (tsp->node_x_coord[node] != DBL_MAX) + { xprintf("%s:%d: node number %d multiply specified\n", + dsa->fname, dsa->seqn, node); + goto fail; + } + if (scan_number(dsa, 0, &tsp->node_x_coord[node])) + goto fail; + if (scan_number(dsa, 0, &tsp->node_y_coord[node])) + goto fail; + if (check_newline(dsa)) goto fail; + } + } + else if (strcmp(dsa->token, "DISPLAY_DATA_SECTION") == 0) + { int n = tsp->dimension, k, node; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (tsp->dply_x_coord != NULL) + { xprintf("%s:%d: DISPLAY_DATA_SECTION multiply specified\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (check_newline(dsa)) goto fail; + tsp->dply_x_coord = xcalloc(1+n, sizeof(double)); + tsp->dply_y_coord = xcalloc(1+n, sizeof(double)); + for (node = 1; node <= n; node++) + tsp->dply_x_coord[node] = tsp->dply_y_coord[node] = DBL_MAX; + for (k = 1; k <= n; k++) + { if (scan_integer(dsa, 0, &node)) goto fail; + if (!(1 <= node && node <= n)) + { xprintf("%s:%d: invalid node number %d\n", dsa->fname, + dsa->seqn, node); + goto fail; + } + if (tsp->dply_x_coord[node] != DBL_MAX) + { xprintf("%s:%d: node number %d multiply specified\n", + dsa->fname, dsa->seqn, node); + goto fail; + } + if (scan_number(dsa, 0, &tsp->dply_x_coord[node])) + goto fail; + if (scan_number(dsa, 0, &tsp->dply_y_coord[node])) + goto fail; + if (check_newline(dsa)) goto fail; + } + } + else if (strcmp(dsa->token, "TOUR_SECTION") == 0) + { int n = tsp->dimension, k, node; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (tsp->tour != NULL) + { xprintf("%s:%d: TOUR_SECTION multiply specified\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (check_newline(dsa)) goto fail; + tsp->tour = xcalloc(1+n, sizeof(int)); + for (k = 1; k <= n; k++) + { if (scan_integer(dsa, 1, &node)) goto fail; + if (!(1 <= node && node <= n)) + { xprintf("%s:%d: invalid node number %d\n", dsa->fname, + dsa->seqn, node); + goto fail; + } + tsp->tour[k] = node; + } + if (scan_integer(dsa, 1, &node)) goto fail; + if (node != -1) + { xprintf("%s:%d: extra node(s) detected\n", dsa->fname, + dsa->seqn); + goto fail; + } + if (check_newline(dsa)) goto fail; + } + else if (strcmp(dsa->token, "EDGE_WEIGHT_SECTION") == 0) + { int n = tsp->dimension, i, j, temp; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (tsp->edge_weight_format == TSP_UNDEF) + { xprintf("%s:%d: EDGE_WEIGHT_FORMAT entry not specified\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (tsp->edge_weight != NULL) + { xprintf("%s:%d: EDGE_WEIGHT_SECTION multiply specified\n", + dsa->fname, dsa->seqn); + goto fail; + } + if (check_newline(dsa)) goto fail; + tsp->edge_weight = xcalloc(1+n*n, sizeof(int)); + switch (tsp->edge_weight_format) + { case TSP_FULL_MATRIX: + for (i = 1; i <= n; i++) + { for (j = 1; j <= n; j++) + { if (scan_integer(dsa, 1, &temp)) goto fail; + tsp->edge_weight[(i - 1) * n + j] = temp; + } + } + break; + case TSP_UPPER_ROW: + for (i = 1; i <= n; i++) + { tsp->edge_weight[(i - 1) * n + i] = 0; + for (j = i + 1; j <= n; j++) + { if (scan_integer(dsa, 1, &temp)) goto fail; + tsp->edge_weight[(i - 1) * n + j] = temp; + tsp->edge_weight[(j - 1) * n + i] = temp; + } + } + break; + case TSP_LOWER_DIAG_ROW: + for (i = 1; i <= n; i++) + { for (j = 1; j <= i; j++) + { if (scan_integer(dsa, 1, &temp)) goto fail; + tsp->edge_weight[(i - 1) * n + j] = temp; + tsp->edge_weight[(j - 1) * n + i] = temp; + } + } + break; + default: + goto fail; + } + if (check_newline(dsa)) goto fail; + } + else if (strcmp(dsa->token, "EOF") == 0) + { if (check_newline(dsa)) goto fail; + goto done; + } + else + { xprintf("%s:%d: keyword `%s' not recognized\n", dsa->fname, + dsa->seqn, dsa->token); + goto fail; + } + goto loop; +done: xprintf("tsp_read_data: %d lines were read\n", dsa->seqn-1); + fclose(dsa->fp); + return tsp; +fail: if (tsp != NULL) + { if (tsp->name != NULL) xfree(tsp->name); + if (tsp->comment != NULL) xfree(tsp->comment); + if (tsp->node_x_coord != NULL) xfree(tsp->node_x_coord); + if (tsp->node_y_coord != NULL) xfree(tsp->node_y_coord); + if (tsp->dply_x_coord != NULL) xfree(tsp->dply_x_coord); + if (tsp->dply_y_coord != NULL) xfree(tsp->dply_y_coord); + if (tsp->tour != NULL) xfree(tsp->tour); + if (tsp->edge_weight != NULL) xfree(tsp->edge_weight); + xfree(tsp); + } + if (dsa->fp != NULL) fclose(dsa->fp); + return NULL; +} + +/*---------------------------------------------------------------------- +-- tsp_free_data - free TSP instance data. +-- +-- *Synopsis* +-- +-- #include "glptsp.h" +-- void tsp_free_data(TSP *tsp); +-- +-- *Description* +-- +-- The routine tsp_free_data frees all the memory allocated to the TSP +-- instance data block, which the parameter tsp points to. */ + +void tsp_free_data(TSP *tsp) +{ if (tsp->name != NULL) xfree(tsp->name); + if (tsp->comment != NULL) xfree(tsp->comment); + if (tsp->node_x_coord != NULL) xfree(tsp->node_x_coord); + if (tsp->node_y_coord != NULL) xfree(tsp->node_y_coord); + if (tsp->dply_x_coord != NULL) xfree(tsp->dply_x_coord); + if (tsp->dply_y_coord != NULL) xfree(tsp->dply_y_coord); + if (tsp->tour != NULL) xfree(tsp->tour); + if (tsp->edge_weight != NULL) xfree(tsp->edge_weight); + xfree(tsp); + return; +} + +/*---------------------------------------------------------------------- +-- tsp_distance - compute distance between two nodes. +-- +-- *Synopsis* +-- +-- #include "glptsp.h" +-- int tsp_distance(TSP *tsp, int i, int j); +-- +-- *Description* +-- +-- The routine tsp_distance computes the distance between i-th and j-th +-- nodes for the TSP instance, which tsp points to. +-- +-- *Returns* +-- +-- The routine tsp_distance returns the computed distance. */ + +#define nint(x) ((int)((x) + 0.5)) + +static double rad(double x) +{ /* convert input coordinate to longitude/latitude, in radians */ + double pi = 3.141592, deg, min; + deg = (int)x; + min = x - deg; + return pi * (deg + 5.0 * min / 3.0) / 180.0; +} + +int tsp_distance(TSP *tsp, int i, int j) +{ int n = tsp->dimension, dij; + if (!(tsp->type == TSP_TSP || tsp->type == TSP_ATSP)) + xfault("tsp_distance: invalid TSP instance\n"); + if (!(1 <= i && i <= n && 1 <= j && j <= n)) + xfault("tsp_distance: node number out of range\n"); + switch (tsp->edge_weight_type) + { case TSP_UNDEF: + xfault("tsp_distance: edge weight type not specified\n"); + case TSP_EXPLICIT: + if (tsp->edge_weight == NULL) + xfault("tsp_distance: edge weights not specified\n"); + dij = tsp->edge_weight[(i - 1) * n + j]; + break; + case TSP_EUC_2D: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xfault("tsp_distance: node coordinates not specified\n"); + { double xd, yd; + xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; + yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; + dij = nint(sqrt(xd * xd + yd * yd)); + } + break; + case TSP_CEIL_2D: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xfault("tsp_distance: node coordinates not specified\n"); + { double xd, yd; + xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; + yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; + dij = (int)ceil(sqrt(xd * xd + yd * yd)); + } + break; + case TSP_GEO: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xfault("tsp_distance: node coordinates not specified\n"); + { double rrr = 6378.388; + double latitude_i = rad(tsp->node_x_coord[i]); + double latitude_j = rad(tsp->node_x_coord[j]); + double longitude_i = rad(tsp->node_y_coord[i]); + double longitude_j = rad(tsp->node_y_coord[j]); + double q1 = cos(longitude_i - longitude_j); + double q2 = cos(latitude_i - latitude_j); + double q3 = cos(latitude_i + latitude_j); + dij = (int)(rrr * acos(0.5 * ((1.0 + q1) * q2 - + (1.0 - q1) *q3)) + 1.0); + } + break; + case TSP_ATT: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xfault("tsp_distance: node coordinates not specified\n"); + { int tij; + double xd, yd, rij; + xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; + yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; + rij = sqrt((xd * xd + yd * yd) / 10.0); + tij = nint(rij); + if (tij < rij) dij = tij + 1; else dij = tij; + } + break; + default: + xassert(tsp->edge_weight_type != tsp->edge_weight_type); + } + return dij; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glptsp.h b/resources/3rdparty/glpk-4.53/src/glptsp.h new file mode 100644 index 000000000..6b82ee5e5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/glptsp.h @@ -0,0 +1,104 @@ +/* glptsp.h (TSP format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef GLPTSP_H +#define GLPTSP_H + +typedef struct TSP TSP; + +struct TSP +{ /* TSP (or related problem) instance in the format described in + the report [G.Reinelt, TSPLIB 95] */ + /*--------------------------------------------------------------*/ + /* the specification part */ + char *name; + /* identifies the data file */ + int type; + /* specifies the type of data: */ +#define TSP_UNDEF 0 /* undefined */ +#define TSP_TSP 1 /* symmetric TSP */ +#define TSP_ATSP 2 /* asymmetric TSP */ +#define TSP_TOUR 3 /* collection of tours */ + char *comment; + /* additional comments (usually the name of the contributor or + creator of the problem instance is given here) */ + int dimension; + /* for a TSP or ATSP, the dimension is the number of its nodes + for a TOUR it is the dimension of the corresponding problem */ + int edge_weight_type; + /* specifies how the edge weights (or distances) are given: */ +#define TSP_UNDEF 0 /* undefined */ +#define TSP_EXPLICIT 1 /* listed explicitly */ +#define TSP_EUC_2D 2 /* Eucl. distances in 2-D */ +#define TSP_CEIL_2D 3 /* Eucl. distances in 2-D rounded up */ +#define TSP_GEO 4 /* geographical distances */ +#define TSP_ATT 5 /* special distance function */ + int edge_weight_format; + /* describes the format of the edge weights if they are given + explicitly: */ +#define TSP_UNDEF 0 /* undefined */ +#define TSP_FUNCTION 1 /* given by a function */ +#define TSP_FULL_MATRIX 2 /* given by a full matrix */ +#define TSP_UPPER_ROW 3 /* upper triangulat matrix (row-wise + without diagonal entries) */ +#define TSP_LOWER_DIAG_ROW 4 /* lower triangular matrix (row-wise + including diagonal entries) */ + int display_data_type; + /* specifies how a graphical display of the nodes can be + obtained: */ +#define TSP_UNDEF 0 /* undefined */ +#define TSP_COORD_DISPLAY 1 /* display is generated from the node + coordinates */ +#define TSP_TWOD_DISPLAY 2 /* explicit coordinates in 2-D are + given */ + /*--------------------------------------------------------------*/ + /* data part */ + /* NODE_COORD_SECTION: */ + double *node_x_coord; /* double node_x_coord[1+dimension]; */ + double *node_y_coord; /* double node_y_coord[1+dimension]; */ + /* DISPLAY_DATA_SECTION: */ + double *dply_x_coord; /* double dply_x_coord[1+dimension]; */ + double *dply_y_coord; /* double dply_y_coord[1+dimension]; */ + /* TOUR_SECTION: */ + int *tour; /* int tour[1+dimension]; */ + /* EDGE_WEIGHT_SECTION: */ + int *edge_weight; /* int edge_weight[1+dimension*dimension]; */ +}; + +#define tsp_read_data _glp_tsp_read_data +#define tsp_free_data _glp_tsp_free_data +#define tsp_distance _glp_tsp_distance + +TSP *tsp_read_data(char *fname); +/* read TSP instance data */ + +void tsp_free_data(TSP *tsp); +/* free TSP instance data */ + +int tsp_distance(TSP *tsp, int i, int j); +/* compute distance between two nodes */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/lux.c b/resources/3rdparty/glpk-4.53/src/lux.c new file mode 100644 index 000000000..38cb758cb --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/lux.c @@ -0,0 +1,1030 @@ +/* lux.c (LU-factorization, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "lux.h" + +#define xfault xerror +#define dmp_create_poolx(size) dmp_create_pool() + +/*********************************************************************** +* lux_create - create LU-factorization +* +* SYNOPSIS +* +* #include "lux.h" +* LUX *lux_create(int n); +* +* DESCRIPTION +* +* The routine lux_create creates LU-factorization data structure for +* a matrix of the order n. Initially the factorization corresponds to +* the unity matrix (F = V = P = Q = I, so A = I). +* +* RETURNS +* +* The routine returns a pointer to the created LU-factorization data +* structure, which represents the unity matrix of the order n. */ + +LUX *lux_create(int n) +{ LUX *lux; + int k; + if (n < 1) + xfault("lux_create: n = %d; invalid parameter\n", n); + lux = xmalloc(sizeof(LUX)); + lux->n = n; + lux->pool = dmp_create_poolx(sizeof(LUXELM)); + lux->F_row = xcalloc(1+n, sizeof(LUXELM *)); + lux->F_col = xcalloc(1+n, sizeof(LUXELM *)); + lux->V_piv = xcalloc(1+n, sizeof(mpq_t)); + lux->V_row = xcalloc(1+n, sizeof(LUXELM *)); + lux->V_col = xcalloc(1+n, sizeof(LUXELM *)); + lux->P_row = xcalloc(1+n, sizeof(int)); + lux->P_col = xcalloc(1+n, sizeof(int)); + lux->Q_row = xcalloc(1+n, sizeof(int)); + lux->Q_col = xcalloc(1+n, sizeof(int)); + for (k = 1; k <= n; k++) + { lux->F_row[k] = lux->F_col[k] = NULL; + mpq_init(lux->V_piv[k]); + mpq_set_si(lux->V_piv[k], 1, 1); + lux->V_row[k] = lux->V_col[k] = NULL; + lux->P_row[k] = lux->P_col[k] = k; + lux->Q_row[k] = lux->Q_col[k] = k; + } + lux->rank = n; + return lux; +} + +/*********************************************************************** +* initialize - initialize LU-factorization data structures +* +* This routine initializes data structures for subsequent computing +* the LU-factorization of a given matrix A, which is specified by the +* formal routine col. On exit V = A and F = P = Q = I, where I is the +* unity matrix. */ + +static void initialize(LUX *lux, int (*col)(void *info, int j, + int ind[], mpq_t val[]), void *info, LUXWKA *wka) +{ int n = lux->n; + DMP *pool = lux->pool; + LUXELM **F_row = lux->F_row; + LUXELM **F_col = lux->F_col; + mpq_t *V_piv = lux->V_piv; + LUXELM **V_row = lux->V_row; + LUXELM **V_col = lux->V_col; + int *P_row = lux->P_row; + int *P_col = lux->P_col; + int *Q_row = lux->Q_row; + int *Q_col = lux->Q_col; + int *R_len = wka->R_len; + int *R_head = wka->R_head; + int *R_prev = wka->R_prev; + int *R_next = wka->R_next; + int *C_len = wka->C_len; + int *C_head = wka->C_head; + int *C_prev = wka->C_prev; + int *C_next = wka->C_next; + LUXELM *fij, *vij; + int i, j, k, len, *ind; + mpq_t *val; + /* F := I */ + for (i = 1; i <= n; i++) + { while (F_row[i] != NULL) + { fij = F_row[i], F_row[i] = fij->r_next; + mpq_clear(fij->val); + dmp_free_atom(pool, fij, sizeof(LUXELM)); + } + } + for (j = 1; j <= n; j++) F_col[j] = NULL; + /* V := 0 */ + for (k = 1; k <= n; k++) mpq_set_si(V_piv[k], 0, 1); + for (i = 1; i <= n; i++) + { while (V_row[i] != NULL) + { vij = V_row[i], V_row[i] = vij->r_next; + mpq_clear(vij->val); + dmp_free_atom(pool, vij, sizeof(LUXELM)); + } + } + for (j = 1; j <= n; j++) V_col[j] = NULL; + /* V := A */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(mpq_t)); + for (k = 1; k <= n; k++) mpq_init(val[k]); + for (j = 1; j <= n; j++) + { /* obtain j-th column of matrix A */ + len = col(info, j, ind, val); + if (!(0 <= len && len <= n)) + xfault("lux_decomp: j = %d: len = %d; invalid column length" + "\n", j, len); + /* copy elements of j-th column to matrix V */ + for (k = 1; k <= len; k++) + { /* get row index of a[i,j] */ + i = ind[k]; + if (!(1 <= i && i <= n)) + xfault("lux_decomp: j = %d: i = %d; row index out of ran" + "ge\n", j, i); + /* check for duplicate indices */ + if (V_row[i] != NULL && V_row[i]->j == j) + xfault("lux_decomp: j = %d: i = %d; duplicate row indice" + "s not allowed\n", j, i); + /* check for zero value */ + if (mpq_sgn(val[k]) == 0) + xfault("lux_decomp: j = %d: i = %d; zero elements not al" + "lowed\n", j, i); + /* add new element v[i,j] = a[i,j] to V */ + vij = dmp_get_atom(pool, sizeof(LUXELM)); + vij->i = i, vij->j = j; + mpq_init(vij->val); + mpq_set(vij->val, val[k]); + vij->r_prev = NULL; + vij->r_next = V_row[i]; + vij->c_prev = NULL; + vij->c_next = V_col[j]; + if (vij->r_next != NULL) vij->r_next->r_prev = vij; + if (vij->c_next != NULL) vij->c_next->c_prev = vij; + V_row[i] = V_col[j] = vij; + } + } + xfree(ind); + for (k = 1; k <= n; k++) mpq_clear(val[k]); + xfree(val); + /* P := Q := I */ + for (k = 1; k <= n; k++) + P_row[k] = P_col[k] = Q_row[k] = Q_col[k] = k; + /* the rank of A and V is not determined yet */ + lux->rank = -1; + /* initially the entire matrix V is active */ + /* determine its row lengths */ + for (i = 1; i <= n; i++) + { len = 0; + for (vij = V_row[i]; vij != NULL; vij = vij->r_next) len++; + R_len[i] = len; + } + /* build linked lists of active rows */ + for (len = 0; len <= n; len++) R_head[len] = 0; + for (i = 1; i <= n; i++) + { len = R_len[i]; + R_prev[i] = 0; + R_next[i] = R_head[len]; + if (R_next[i] != 0) R_prev[R_next[i]] = i; + R_head[len] = i; + } + /* determine its column lengths */ + for (j = 1; j <= n; j++) + { len = 0; + for (vij = V_col[j]; vij != NULL; vij = vij->c_next) len++; + C_len[j] = len; + } + /* build linked lists of active columns */ + for (len = 0; len <= n; len++) C_head[len] = 0; + for (j = 1; j <= n; j++) + { len = C_len[j]; + C_prev[j] = 0; + C_next[j] = C_head[len]; + if (C_next[j] != 0) C_prev[C_next[j]] = j; + C_head[len] = j; + } + return; +} + +/*********************************************************************** +* find_pivot - choose a pivot element +* +* This routine chooses a pivot element v[p,q] in the active submatrix +* of matrix U = P*V*Q. +* +* It is assumed that on entry the matrix U has the following partially +* triangularized form: +* +* 1 k n +* 1 x x x x x x x x x x +* . x x x x x x x x x +* . . x x x x x x x x +* . . . x x x x x x x +* k . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* n . . . . * * * * * * +* +* where rows and columns k, k+1, ..., n belong to the active submatrix +* (elements of the active submatrix are marked by '*'). +* +* Since the matrix U = P*V*Q is not stored, the routine works with the +* matrix V. It is assumed that the row-wise representation corresponds +* to the matrix V, but the column-wise representation corresponds to +* the active submatrix of the matrix V, i.e. elements of the matrix V, +* which does not belong to the active submatrix, are missing from the +* column linked lists. It is also assumed that each active row of the +* matrix V is in the set R[len], where len is number of non-zeros in +* the row, and each active column of the matrix V is in the set C[len], +* where len is number of non-zeros in the column (in the latter case +* only elements of the active submatrix are counted; such elements are +* marked by '*' on the figure above). +* +* Due to exact arithmetic any non-zero element of the active submatrix +* can be chosen as a pivot. However, to keep sparsity of the matrix V +* the routine uses Markowitz strategy, trying to choose such element +* v[p,q], which has smallest Markowitz cost (nr[p]-1) * (nc[q]-1), +* where nr[p] and nc[q] are the number of non-zero elements, resp., in +* p-th row and in q-th column of the active submatrix. +* +* In order to reduce the search, i.e. not to walk through all elements +* of the active submatrix, the routine exploits a technique proposed by +* I.Duff. This technique is based on using the sets R[len] and C[len] +* of active rows and columns. +* +* On exit the routine returns a pointer to a pivot v[p,q] chosen, or +* NULL, if the active submatrix is empty. */ + +static LUXELM *find_pivot(LUX *lux, LUXWKA *wka) +{ int n = lux->n; + LUXELM **V_row = lux->V_row; + LUXELM **V_col = lux->V_col; + int *R_len = wka->R_len; + int *R_head = wka->R_head; + int *R_next = wka->R_next; + int *C_len = wka->C_len; + int *C_head = wka->C_head; + int *C_next = wka->C_next; + LUXELM *piv, *some, *vij; + int i, j, len, min_len, ncand, piv_lim = 5; + double best, cost; + /* nothing is chosen so far */ + piv = NULL, best = DBL_MAX, ncand = 0; + /* if in the active submatrix there is a column that has the only + non-zero (column singleton), choose it as a pivot */ + j = C_head[1]; + if (j != 0) + { xassert(C_len[j] == 1); + piv = V_col[j]; + xassert(piv != NULL && piv->c_next == NULL); + goto done; + } + /* if in the active submatrix there is a row that has the only + non-zero (row singleton), choose it as a pivot */ + i = R_head[1]; + if (i != 0) + { xassert(R_len[i] == 1); + piv = V_row[i]; + xassert(piv != NULL && piv->r_next == NULL); + goto done; + } + /* there are no singletons in the active submatrix; walk through + other non-empty rows and columns */ + for (len = 2; len <= n; len++) + { /* consider active columns having len non-zeros */ + for (j = C_head[len]; j != 0; j = C_next[j]) + { /* j-th column has len non-zeros */ + /* find an element in the row of minimal length */ + some = NULL, min_len = INT_MAX; + for (vij = V_col[j]; vij != NULL; vij = vij->c_next) + { if (min_len > R_len[vij->i]) + some = vij, min_len = R_len[vij->i]; + /* if Markowitz cost of this element is not greater than + (len-1)**2, it can be chosen right now; this heuristic + reduces the search and works well in many cases */ + if (min_len <= len) + { piv = some; + goto done; + } + } + /* j-th column has been scanned */ + /* the minimal element found is a next pivot candidate */ + xassert(some != NULL); + ncand++; + /* compute its Markowitz cost */ + cost = (double)(min_len - 1) * (double)(len - 1); + /* choose between the current candidate and this element */ + if (cost < best) piv = some, best = cost; + /* if piv_lim candidates have been considered, there is a + doubt that a much better candidate exists; therefore it + is the time to terminate the search */ + if (ncand == piv_lim) goto done; + } + /* now consider active rows having len non-zeros */ + for (i = R_head[len]; i != 0; i = R_next[i]) + { /* i-th row has len non-zeros */ + /* find an element in the column of minimal length */ + some = NULL, min_len = INT_MAX; + for (vij = V_row[i]; vij != NULL; vij = vij->r_next) + { if (min_len > C_len[vij->j]) + some = vij, min_len = C_len[vij->j]; + /* if Markowitz cost of this element is not greater than + (len-1)**2, it can be chosen right now; this heuristic + reduces the search and works well in many cases */ + if (min_len <= len) + { piv = some; + goto done; + } + } + /* i-th row has been scanned */ + /* the minimal element found is a next pivot candidate */ + xassert(some != NULL); + ncand++; + /* compute its Markowitz cost */ + cost = (double)(len - 1) * (double)(min_len - 1); + /* choose between the current candidate and this element */ + if (cost < best) piv = some, best = cost; + /* if piv_lim candidates have been considered, there is a + doubt that a much better candidate exists; therefore it + is the time to terminate the search */ + if (ncand == piv_lim) goto done; + } + } +done: /* bring the pivot v[p,q] to the factorizing routine */ + return piv; +} + +/*********************************************************************** +* eliminate - perform gaussian elimination +* +* This routine performs elementary gaussian transformations in order +* to eliminate subdiagonal elements in the k-th column of the matrix +* U = P*V*Q using the pivot element u[k,k], where k is the number of +* the current elimination step. +* +* The parameter piv specifies the pivot element v[p,q] = u[k,k]. +* +* Each time when the routine applies the elementary transformation to +* a non-pivot row of the matrix V, it stores the corresponding element +* to the matrix F in order to keep the main equality A = F*V. +* +* The routine assumes that on entry the matrices L = P*F*inv(P) and +* U = P*V*Q are the following: +* +* 1 k 1 k n +* 1 1 . . . . . . . . . 1 x x x x x x x x x x +* x 1 . . . . . . . . . x x x x x x x x x +* x x 1 . . . . . . . . . x x x x x x x x +* x x x 1 . . . . . . . . . x x x x x x x +* k x x x x 1 . . . . . k . . . . * * * * * * +* x x x x _ 1 . . . . . . . . # * * * * * +* x x x x _ . 1 . . . . . . . # * * * * * +* x x x x _ . . 1 . . . . . . # * * * * * +* x x x x _ . . . 1 . . . . . # * * * * * +* n x x x x _ . . . . 1 n . . . . # * * * * * +* +* matrix L matrix U +* +* where rows and columns of the matrix U with numbers k, k+1, ..., n +* form the active submatrix (eliminated elements are marked by '#' and +* other elements of the active submatrix are marked by '*'). Note that +* each eliminated non-zero element u[i,k] of the matrix U gives the +* corresponding element l[i,k] of the matrix L (marked by '_'). +* +* Actually all operations are performed on the matrix V. Should note +* that the row-wise representation corresponds to the matrix V, but the +* column-wise representation corresponds to the active submatrix of the +* matrix V, i.e. elements of the matrix V, which doesn't belong to the +* active submatrix, are missing from the column linked lists. +* +* Let u[k,k] = v[p,q] be the pivot. In order to eliminate subdiagonal +* elements u[i',k] = v[i,q], i' = k+1, k+2, ..., n, the routine applies +* the following elementary gaussian transformations: +* +* (i-th row of V) := (i-th row of V) - f[i,p] * (p-th row of V), +* +* where f[i,p] = v[i,q] / v[p,q] is a gaussian multiplier. +* +* Additionally, in order to keep the main equality A = F*V, each time +* when the routine applies the transformation to i-th row of the matrix +* V, it also adds f[i,p] as a new element to the matrix F. +* +* IMPORTANT: On entry the working arrays flag and work should contain +* zeros. This status is provided by the routine on exit. */ + +static void eliminate(LUX *lux, LUXWKA *wka, LUXELM *piv, int flag[], + mpq_t work[]) +{ DMP *pool = lux->pool; + LUXELM **F_row = lux->F_row; + LUXELM **F_col = lux->F_col; + mpq_t *V_piv = lux->V_piv; + LUXELM **V_row = lux->V_row; + LUXELM **V_col = lux->V_col; + int *R_len = wka->R_len; + int *R_head = wka->R_head; + int *R_prev = wka->R_prev; + int *R_next = wka->R_next; + int *C_len = wka->C_len; + int *C_head = wka->C_head; + int *C_prev = wka->C_prev; + int *C_next = wka->C_next; + LUXELM *fip, *vij, *vpj, *viq, *next; + mpq_t temp; + int i, j, p, q; + mpq_init(temp); + /* determine row and column indices of the pivot v[p,q] */ + xassert(piv != NULL); + p = piv->i, q = piv->j; + /* remove p-th (pivot) row from the active set; it will never + return there */ + if (R_prev[p] == 0) + R_head[R_len[p]] = R_next[p]; + else + R_next[R_prev[p]] = R_next[p]; + if (R_next[p] == 0) + ; + else + R_prev[R_next[p]] = R_prev[p]; + /* remove q-th (pivot) column from the active set; it will never + return there */ + if (C_prev[q] == 0) + C_head[C_len[q]] = C_next[q]; + else + C_next[C_prev[q]] = C_next[q]; + if (C_next[q] == 0) + ; + else + C_prev[C_next[q]] = C_prev[q]; + /* store the pivot value in a separate array */ + mpq_set(V_piv[p], piv->val); + /* remove the pivot from p-th row */ + if (piv->r_prev == NULL) + V_row[p] = piv->r_next; + else + piv->r_prev->r_next = piv->r_next; + if (piv->r_next == NULL) + ; + else + piv->r_next->r_prev = piv->r_prev; + R_len[p]--; + /* remove the pivot from q-th column */ + if (piv->c_prev == NULL) + V_col[q] = piv->c_next; + else + piv->c_prev->c_next = piv->c_next; + if (piv->c_next == NULL) + ; + else + piv->c_next->c_prev = piv->c_prev; + C_len[q]--; + /* free the space occupied by the pivot */ + mpq_clear(piv->val); + dmp_free_atom(pool, piv, sizeof(LUXELM)); + /* walk through p-th (pivot) row, which already does not contain + the pivot v[p,q], and do the following... */ + for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next) + { /* get column index of v[p,j] */ + j = vpj->j; + /* store v[p,j] in the working array */ + flag[j] = 1; + mpq_set(work[j], vpj->val); + /* remove j-th column from the active set; it will return there + later with a new length */ + if (C_prev[j] == 0) + C_head[C_len[j]] = C_next[j]; + else + C_next[C_prev[j]] = C_next[j]; + if (C_next[j] == 0) + ; + else + C_prev[C_next[j]] = C_prev[j]; + /* v[p,j] leaves the active submatrix, so remove it from j-th + column; however, v[p,j] is kept in p-th row */ + if (vpj->c_prev == NULL) + V_col[j] = vpj->c_next; + else + vpj->c_prev->c_next = vpj->c_next; + if (vpj->c_next == NULL) + ; + else + vpj->c_next->c_prev = vpj->c_prev; + C_len[j]--; + } + /* now walk through q-th (pivot) column, which already does not + contain the pivot v[p,q], and perform gaussian elimination */ + while (V_col[q] != NULL) + { /* element v[i,q] has to be eliminated */ + viq = V_col[q]; + /* get row index of v[i,q] */ + i = viq->i; + /* remove i-th row from the active set; later it will return + there with a new length */ + if (R_prev[i] == 0) + R_head[R_len[i]] = R_next[i]; + else + R_next[R_prev[i]] = R_next[i]; + if (R_next[i] == 0) + ; + else + R_prev[R_next[i]] = R_prev[i]; + /* compute gaussian multiplier f[i,p] = v[i,q] / v[p,q] and + store it in the matrix F */ + fip = dmp_get_atom(pool, sizeof(LUXELM)); + fip->i = i, fip->j = p; + mpq_init(fip->val); + mpq_div(fip->val, viq->val, V_piv[p]); + fip->r_prev = NULL; + fip->r_next = F_row[i]; + fip->c_prev = NULL; + fip->c_next = F_col[p]; + if (fip->r_next != NULL) fip->r_next->r_prev = fip; + if (fip->c_next != NULL) fip->c_next->c_prev = fip; + F_row[i] = F_col[p] = fip; + /* v[i,q] has to be eliminated, so remove it from i-th row */ + if (viq->r_prev == NULL) + V_row[i] = viq->r_next; + else + viq->r_prev->r_next = viq->r_next; + if (viq->r_next == NULL) + ; + else + viq->r_next->r_prev = viq->r_prev; + R_len[i]--; + /* and also from q-th column */ + V_col[q] = viq->c_next; + C_len[q]--; + /* free the space occupied by v[i,q] */ + mpq_clear(viq->val); + dmp_free_atom(pool, viq, sizeof(LUXELM)); + /* perform gaussian transformation: + (i-th row) := (i-th row) - f[i,p] * (p-th row) + note that now p-th row, which is in the working array, + does not contain the pivot v[p,q], and i-th row does not + contain the element v[i,q] to be eliminated */ + /* walk through i-th row and transform existing non-zero + elements */ + for (vij = V_row[i]; vij != NULL; vij = next) + { next = vij->r_next; + /* get column index of v[i,j] */ + j = vij->j; + /* v[i,j] := v[i,j] - f[i,p] * v[p,j] */ + if (flag[j]) + { /* v[p,j] != 0 */ + flag[j] = 0; + mpq_mul(temp, fip->val, work[j]); + mpq_sub(vij->val, vij->val, temp); + if (mpq_sgn(vij->val) == 0) + { /* new v[i,j] is zero, so remove it from the active + submatrix */ + /* remove v[i,j] from i-th row */ + if (vij->r_prev == NULL) + V_row[i] = vij->r_next; + else + vij->r_prev->r_next = vij->r_next; + if (vij->r_next == NULL) + ; + else + vij->r_next->r_prev = vij->r_prev; + R_len[i]--; + /* remove v[i,j] from j-th column */ + if (vij->c_prev == NULL) + V_col[j] = vij->c_next; + else + vij->c_prev->c_next = vij->c_next; + if (vij->c_next == NULL) + ; + else + vij->c_next->c_prev = vij->c_prev; + C_len[j]--; + /* free the space occupied by v[i,j] */ + mpq_clear(vij->val); + dmp_free_atom(pool, vij, sizeof(LUXELM)); + } + } + } + /* now flag is the pattern of the set v[p,*] \ v[i,*] */ + /* walk through p-th (pivot) row and create new elements in + i-th row, which appear due to fill-in */ + for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next) + { j = vpj->j; + if (flag[j]) + { /* create new non-zero v[i,j] = 0 - f[i,p] * v[p,j] and + add it to i-th row and j-th column */ + vij = dmp_get_atom(pool, sizeof(LUXELM)); + vij->i = i, vij->j = j; + mpq_init(vij->val); + mpq_mul(vij->val, fip->val, work[j]); + mpq_neg(vij->val, vij->val); + vij->r_prev = NULL; + vij->r_next = V_row[i]; + vij->c_prev = NULL; + vij->c_next = V_col[j]; + if (vij->r_next != NULL) vij->r_next->r_prev = vij; + if (vij->c_next != NULL) vij->c_next->c_prev = vij; + V_row[i] = V_col[j] = vij; + R_len[i]++, C_len[j]++; + } + else + { /* there is no fill-in, because v[i,j] already exists in + i-th row; restore the flag, which was reset before */ + flag[j] = 1; + } + } + /* now i-th row has been completely transformed and can return + to the active set with a new length */ + R_prev[i] = 0; + R_next[i] = R_head[R_len[i]]; + if (R_next[i] != 0) R_prev[R_next[i]] = i; + R_head[R_len[i]] = i; + } + /* at this point q-th (pivot) column must be empty */ + xassert(C_len[q] == 0); + /* walk through p-th (pivot) row again and do the following... */ + for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next) + { /* get column index of v[p,j] */ + j = vpj->j; + /* erase v[p,j] from the working array */ + flag[j] = 0; + mpq_set_si(work[j], 0, 1); + /* now j-th column has been completely transformed, so it can + return to the active list with a new length */ + C_prev[j] = 0; + C_next[j] = C_head[C_len[j]]; + if (C_next[j] != 0) C_prev[C_next[j]] = j; + C_head[C_len[j]] = j; + } + mpq_clear(temp); + /* return to the factorizing routine */ + return; +} + +/*********************************************************************** +* lux_decomp - compute LU-factorization +* +* SYNOPSIS +* +* #include "lux.h" +* int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[], +* mpq_t val[]), void *info); +* +* DESCRIPTION +* +* The routine lux_decomp computes LU-factorization of a given square +* matrix A. +* +* The parameter lux specifies LU-factorization data structure built by +* means of the routine lux_create. +* +* The formal routine col specifies the original matrix A. In order to +* obtain j-th column of the matrix A the routine lux_decomp calls the +* routine col with the parameter j (1 <= j <= n, where n is the order +* of A). In response the routine col should store row indices and +* numerical values of non-zero elements of j-th column of A to the +* locations ind[1], ..., ind[len] and val[1], ..., val[len], resp., +* where len is the number of non-zeros in j-th column, which should be +* returned on exit. Neiter zero nor duplicate elements are allowed. +* +* The parameter info is a transit pointer passed to the formal routine +* col; it can be used for various purposes. +* +* RETURNS +* +* The routine lux_decomp returns the singularity flag. Zero flag means +* that the original matrix A is non-singular while non-zero flag means +* that A is (exactly!) singular. +* +* Note that LU-factorization is valid in both cases, however, in case +* of singularity some rows of the matrix V (including pivot elements) +* will be empty. +* +* REPAIRING SINGULAR MATRIX +* +* If the routine lux_decomp returns non-zero flag, it provides all +* necessary information that can be used for "repairing" the matrix A, +* where "repairing" means replacing linearly dependent columns of the +* matrix A by appropriate columns of the unity matrix. This feature is +* needed when the routine lux_decomp is used for reinverting the basis +* matrix within the simplex method procedure. +* +* On exit linearly dependent columns of the matrix U have the numbers +* rank+1, rank+2, ..., n, where rank is the exact rank of the matrix A +* stored by the routine to the member lux->rank. The correspondence +* between columns of A and U is the same as between columns of V and U. +* Thus, linearly dependent columns of the matrix A have the numbers +* Q_col[rank+1], Q_col[rank+2], ..., Q_col[n], where Q_col is an array +* representing the permutation matrix Q in column-like format. It is +* understood that each j-th linearly dependent column of the matrix U +* should be replaced by the unity vector, where all elements are zero +* except the unity diagonal element u[j,j]. On the other hand j-th row +* of the matrix U corresponds to the row of the matrix V (and therefore +* of the matrix A) with the number P_row[j], where P_row is an array +* representing the permutation matrix P in row-like format. Thus, each +* j-th linearly dependent column of the matrix U should be replaced by +* a column of the unity matrix with the number P_row[j]. +* +* The code that repairs the matrix A may look like follows: +* +* for (j = rank+1; j <= n; j++) +* { replace column Q_col[j] of the matrix A by column P_row[j] of +* the unity matrix; +* } +* +* where rank, P_row, and Q_col are members of the structure LUX. */ + +int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[], + mpq_t val[]), void *info) +{ int n = lux->n; + LUXELM **V_row = lux->V_row; + LUXELM **V_col = lux->V_col; + int *P_row = lux->P_row; + int *P_col = lux->P_col; + int *Q_row = lux->Q_row; + int *Q_col = lux->Q_col; + LUXELM *piv, *vij; + LUXWKA *wka; + int i, j, k, p, q, t, *flag; + mpq_t *work; + /* allocate working area */ + wka = xmalloc(sizeof(LUXWKA)); + wka->R_len = xcalloc(1+n, sizeof(int)); + wka->R_head = xcalloc(1+n, sizeof(int)); + wka->R_prev = xcalloc(1+n, sizeof(int)); + wka->R_next = xcalloc(1+n, sizeof(int)); + wka->C_len = xcalloc(1+n, sizeof(int)); + wka->C_head = xcalloc(1+n, sizeof(int)); + wka->C_prev = xcalloc(1+n, sizeof(int)); + wka->C_next = xcalloc(1+n, sizeof(int)); + /* initialize LU-factorization data structures */ + initialize(lux, col, info, wka); + /* allocate working arrays */ + flag = xcalloc(1+n, sizeof(int)); + work = xcalloc(1+n, sizeof(mpq_t)); + for (k = 1; k <= n; k++) + { flag[k] = 0; + mpq_init(work[k]); + } + /* main elimination loop */ + for (k = 1; k <= n; k++) + { /* choose a pivot element v[p,q] */ + piv = find_pivot(lux, wka); + if (piv == NULL) + { /* no pivot can be chosen, because the active submatrix is + empty */ + break; + } + /* determine row and column indices of the pivot element */ + p = piv->i, q = piv->j; + /* let v[p,q] correspond to u[i',j']; permute k-th and i'-th + rows and k-th and j'-th columns of the matrix U = P*V*Q to + move the element u[i',j'] to the position u[k,k] */ + i = P_col[p], j = Q_row[q]; + xassert(k <= i && i <= n && k <= j && j <= n); + /* permute k-th and i-th rows of the matrix U */ + t = P_row[k]; + P_row[i] = t, P_col[t] = i; + P_row[k] = p, P_col[p] = k; + /* permute k-th and j-th columns of the matrix U */ + t = Q_col[k]; + Q_col[j] = t, Q_row[t] = j; + Q_col[k] = q, Q_row[q] = k; + /* eliminate subdiagonal elements of k-th column of the matrix + U = P*V*Q using the pivot element u[k,k] = v[p,q] */ + eliminate(lux, wka, piv, flag, work); + } + /* determine the rank of A (and V) */ + lux->rank = k - 1; + /* free working arrays */ + xfree(flag); + for (k = 1; k <= n; k++) mpq_clear(work[k]); + xfree(work); + /* build column lists of the matrix V using its row lists */ + for (j = 1; j <= n; j++) + xassert(V_col[j] == NULL); + for (i = 1; i <= n; i++) + { for (vij = V_row[i]; vij != NULL; vij = vij->r_next) + { j = vij->j; + vij->c_prev = NULL; + vij->c_next = V_col[j]; + if (vij->c_next != NULL) vij->c_next->c_prev = vij; + V_col[j] = vij; + } + } + /* free working area */ + xfree(wka->R_len); + xfree(wka->R_head); + xfree(wka->R_prev); + xfree(wka->R_next); + xfree(wka->C_len); + xfree(wka->C_head); + xfree(wka->C_prev); + xfree(wka->C_next); + xfree(wka); + /* return to the calling program */ + return (lux->rank < n); +} + +/*********************************************************************** +* lux_f_solve - solve system F*x = b or F'*x = b +* +* SYNOPSIS +* +* #include "lux.h" +* void lux_f_solve(LUX *lux, int tr, mpq_t x[]); +* +* DESCRIPTION +* +* The routine lux_f_solve solves either the system F*x = b (if the +* flag tr is zero) or the system F'*x = b (if the flag tr is non-zero), +* where the matrix F is a component of LU-factorization specified by +* the parameter lux, F' is a matrix transposed to F. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix F. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void lux_f_solve(LUX *lux, int tr, mpq_t x[]) +{ int n = lux->n; + LUXELM **F_row = lux->F_row; + LUXELM **F_col = lux->F_col; + int *P_row = lux->P_row; + LUXELM *fik, *fkj; + int i, j, k; + mpq_t temp; + mpq_init(temp); + if (!tr) + { /* solve the system F*x = b */ + for (j = 1; j <= n; j++) + { k = P_row[j]; + if (mpq_sgn(x[k]) != 0) + { for (fik = F_col[k]; fik != NULL; fik = fik->c_next) + { mpq_mul(temp, fik->val, x[k]); + mpq_sub(x[fik->i], x[fik->i], temp); + } + } + } + } + else + { /* solve the system F'*x = b */ + for (i = n; i >= 1; i--) + { k = P_row[i]; + if (mpq_sgn(x[k]) != 0) + { for (fkj = F_row[k]; fkj != NULL; fkj = fkj->r_next) + { mpq_mul(temp, fkj->val, x[k]); + mpq_sub(x[fkj->j], x[fkj->j], temp); + } + } + } + } + mpq_clear(temp); + return; +} + +/*********************************************************************** +* lux_v_solve - solve system V*x = b or V'*x = b +* +* SYNOPSIS +* +* #include "lux.h" +* void lux_v_solve(LUX *lux, int tr, double x[]); +* +* DESCRIPTION +* +* The routine lux_v_solve solves either the system V*x = b (if the +* flag tr is zero) or the system V'*x = b (if the flag tr is non-zero), +* where the matrix V is a component of LU-factorization specified by +* the parameter lux, V' is a matrix transposed to V. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix V. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void lux_v_solve(LUX *lux, int tr, mpq_t x[]) +{ int n = lux->n; + mpq_t *V_piv = lux->V_piv; + LUXELM **V_row = lux->V_row; + LUXELM **V_col = lux->V_col; + int *P_row = lux->P_row; + int *Q_col = lux->Q_col; + LUXELM *vij; + int i, j, k; + mpq_t *b, temp; + b = xcalloc(1+n, sizeof(mpq_t)); + for (k = 1; k <= n; k++) + mpq_init(b[k]), mpq_set(b[k], x[k]), mpq_set_si(x[k], 0, 1); + mpq_init(temp); + if (!tr) + { /* solve the system V*x = b */ + for (k = n; k >= 1; k--) + { i = P_row[k], j = Q_col[k]; + if (mpq_sgn(b[i]) != 0) + { mpq_set(x[j], b[i]); + mpq_div(x[j], x[j], V_piv[i]); + for (vij = V_col[j]; vij != NULL; vij = vij->c_next) + { mpq_mul(temp, vij->val, x[j]); + mpq_sub(b[vij->i], b[vij->i], temp); + } + } + } + } + else + { /* solve the system V'*x = b */ + for (k = 1; k <= n; k++) + { i = P_row[k], j = Q_col[k]; + if (mpq_sgn(b[j]) != 0) + { mpq_set(x[i], b[j]); + mpq_div(x[i], x[i], V_piv[i]); + for (vij = V_row[i]; vij != NULL; vij = vij->r_next) + { mpq_mul(temp, vij->val, x[i]); + mpq_sub(b[vij->j], b[vij->j], temp); + } + } + } + } + for (k = 1; k <= n; k++) mpq_clear(b[k]); + mpq_clear(temp); + xfree(b); + return; +} + +/*********************************************************************** +* lux_solve - solve system A*x = b or A'*x = b +* +* SYNOPSIS +* +* #include "lux.h" +* void lux_solve(LUX *lux, int tr, mpq_t x[]); +* +* DESCRIPTION +* +* The routine lux_solve solves either the system A*x = b (if the flag +* tr is zero) or the system A'*x = b (if the flag tr is non-zero), +* where the parameter lux specifies LU-factorization of the matrix A, +* A' is a matrix transposed to A. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix A. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void lux_solve(LUX *lux, int tr, mpq_t x[]) +{ if (lux->rank < lux->n) + xfault("lux_solve: LU-factorization has incomplete rank\n"); + if (!tr) + { /* A = F*V, therefore inv(A) = inv(V)*inv(F) */ + lux_f_solve(lux, 0, x); + lux_v_solve(lux, 0, x); + } + else + { /* A' = V'*F', therefore inv(A') = inv(F')*inv(V') */ + lux_v_solve(lux, 1, x); + lux_f_solve(lux, 1, x); + } + return; +} + +/*********************************************************************** +* lux_delete - delete LU-factorization +* +* SYNOPSIS +* +* #include "lux.h" +* void lux_delete(LUX *lux); +* +* DESCRIPTION +* +* The routine lux_delete deletes LU-factorization data structure, +* which the parameter lux points to, freeing all the memory allocated +* to this object. */ + +void lux_delete(LUX *lux) +{ int n = lux->n; + LUXELM *fij, *vij; + int i; + for (i = 1; i <= n; i++) + { for (fij = lux->F_row[i]; fij != NULL; fij = fij->r_next) + mpq_clear(fij->val); + mpq_clear(lux->V_piv[i]); + for (vij = lux->V_row[i]; vij != NULL; vij = vij->r_next) + mpq_clear(vij->val); + } + dmp_delete_pool(lux->pool); + xfree(lux->F_row); + xfree(lux->F_col); + xfree(lux->V_piv); + xfree(lux->V_row); + xfree(lux->V_col); + xfree(lux->P_row); + xfree(lux->P_col); + xfree(lux->Q_row); + xfree(lux->Q_col); + xfree(lux); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/lux.h b/resources/3rdparty/glpk-4.53/src/lux.h new file mode 100644 index 000000000..6efce3636 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/lux.h @@ -0,0 +1,220 @@ +/* lux.h (LU-factorization, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef LUX_H +#define LUX_H + +#include "dmp.h" +#include "glpgmp.h" + +/*********************************************************************** +* The structure LUX defines LU-factorization of a square matrix A, +* which is the following quartet: +* +* [A] = (F, V, P, Q), (1) +* +* where F and V are such matrices that +* +* A = F * V, (2) +* +* and P and Q are such permutation matrices that the matrix +* +* L = P * F * inv(P) (3) +* +* is lower triangular with unity diagonal, and the matrix +* +* U = P * V * Q (4) +* +* is upper triangular. All the matrices have the order n. +* +* The matrices F and V are stored in row/column-wise sparse format as +* row and column linked lists of non-zero elements. Unity elements on +* the main diagonal of the matrix F are not stored. Pivot elements of +* the matrix V (that correspond to diagonal elements of the matrix U) +* are also missing from the row and column lists and stored separately +* in an ordinary array. +* +* The permutation matrices P and Q are stored as ordinary arrays using +* both row- and column-like formats. +* +* The matrices L and U being completely defined by the matrices F, V, +* P, and Q are not stored explicitly. +* +* It is easy to show that the factorization (1)-(3) is some version of +* LU-factorization. Indeed, from (3) and (4) it follows that: +* +* F = inv(P) * L * P, +* +* V = inv(P) * U * inv(Q), +* +* and substitution into (2) gives: +* +* A = F * V = inv(P) * L * U * inv(Q). +* +* For more details see the program documentation. */ + +typedef struct LUX LUX; +typedef struct LUXELM LUXELM; +typedef struct LUXWKA LUXWKA; + +struct LUX +{ /* LU-factorization of a square matrix */ + int n; + /* the order of matrices A, F, V, P, Q */ + DMP *pool; + /* memory pool for elements of matrices F and V */ + LUXELM **F_row; /* LUXELM *F_row[1+n]; */ + /* F_row[0] is not used; + F_row[i], 1 <= i <= n, is a pointer to the list of elements in + i-th row of matrix F (diagonal elements are not stored) */ + LUXELM **F_col; /* LUXELM *F_col[1+n]; */ + /* F_col[0] is not used; + F_col[j], 1 <= j <= n, is a pointer to the list of elements in + j-th column of matrix F (diagonal elements are not stored) */ + mpq_t *V_piv; /* mpq_t V_piv[1+n]; */ + /* V_piv[0] is not used; + V_piv[p], 1 <= p <= n, is a pivot element v[p,q] corresponding + to a diagonal element u[k,k] of matrix U = P*V*Q (used on k-th + elimination step, k = 1, 2, ..., n) */ + LUXELM **V_row; /* LUXELM *V_row[1+n]; */ + /* V_row[0] is not used; + V_row[i], 1 <= i <= n, is a pointer to the list of elements in + i-th row of matrix V (except pivot elements) */ + LUXELM **V_col; /* LUXELM *V_col[1+n]; */ + /* V_col[0] is not used; + V_col[j], 1 <= j <= n, is a pointer to the list of elements in + j-th column of matrix V (except pivot elements) */ + int *P_row; /* int P_row[1+n]; */ + /* P_row[0] is not used; + P_row[i] = j means that p[i,j] = 1, where p[i,j] is an element + of permutation matrix P */ + int *P_col; /* int P_col[1+n]; */ + /* P_col[0] is not used; + P_col[j] = i means that p[i,j] = 1, where p[i,j] is an element + of permutation matrix P */ + /* if i-th row or column of matrix F is i'-th row or column of + matrix L = P*F*inv(P), or if i-th row of matrix V is i'-th row + of matrix U = P*V*Q, then P_row[i'] = i and P_col[i] = i' */ + int *Q_row; /* int Q_row[1+n]; */ + /* Q_row[0] is not used; + Q_row[i] = j means that q[i,j] = 1, where q[i,j] is an element + of permutation matrix Q */ + int *Q_col; /* int Q_col[1+n]; */ + /* Q_col[0] is not used; + Q_col[j] = i means that q[i,j] = 1, where q[i,j] is an element + of permutation matrix Q */ + /* if j-th column of matrix V is j'-th column of matrix U = P*V*Q, + then Q_row[j] = j' and Q_col[j'] = j */ + int rank; + /* the (exact) rank of matrices A and V */ +}; + +struct LUXELM +{ /* element of matrix F or V */ + int i; + /* row index, 1 <= i <= m */ + int j; + /* column index, 1 <= j <= n */ + mpq_t val; + /* numeric (non-zero) element value */ + LUXELM *r_prev; + /* pointer to previous element in the same row */ + LUXELM *r_next; + /* pointer to next element in the same row */ + LUXELM *c_prev; + /* pointer to previous element in the same column */ + LUXELM *c_next; + /* pointer to next element in the same column */ +}; + +struct LUXWKA +{ /* working area (used only during factorization) */ + /* in order to efficiently implement Markowitz strategy and Duff + search technique there are two families {R[0], R[1], ..., R[n]} + and {C[0], C[1], ..., C[n]}; member R[k] is a set of active + rows of matrix V having k non-zeros, and member C[k] is a set + of active columns of matrix V having k non-zeros (in the active + submatrix); each set R[k] and C[k] is implemented as a separate + doubly linked list */ + int *R_len; /* int R_len[1+n]; */ + /* R_len[0] is not used; + R_len[i], 1 <= i <= n, is the number of non-zero elements in + i-th row of matrix V (that is the length of i-th row) */ + int *R_head; /* int R_head[1+n]; */ + /* R_head[k], 0 <= k <= n, is the number of a first row, which is + active and whose length is k */ + int *R_prev; /* int R_prev[1+n]; */ + /* R_prev[0] is not used; + R_prev[i], 1 <= i <= n, is the number of a previous row, which + is active and has the same length as i-th row */ + int *R_next; /* int R_next[1+n]; */ + /* R_prev[0] is not used; + R_prev[i], 1 <= i <= n, is the number of a next row, which is + active and has the same length as i-th row */ + int *C_len; /* int C_len[1+n]; */ + /* C_len[0] is not used; + C_len[j], 1 <= j <= n, is the number of non-zero elements in + j-th column of the active submatrix of matrix V (that is the + length of j-th column in the active submatrix) */ + int *C_head; /* int C_head[1+n]; */ + /* C_head[k], 0 <= k <= n, is the number of a first column, which + is active and whose length is k */ + int *C_prev; /* int C_prev[1+n]; */ + /* C_prev[0] is not used; + C_prev[j], 1 <= j <= n, is the number of a previous column, + which is active and has the same length as j-th column */ + int *C_next; /* int C_next[1+n]; */ + /* C_next[0] is not used; + C_next[j], 1 <= j <= n, is the number of a next column, which + is active and has the same length as j-th column */ +}; + +#define lux_create _glp_lux_create +LUX *lux_create(int n); +/* create LU-factorization */ + +#define lux_decomp _glp_lux_decomp +int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[], + mpq_t val[]), void *info); +/* compute LU-factorization */ + +#define lux_f_solve _glp_lux_f_solve +void lux_f_solve(LUX *lux, int tr, mpq_t x[]); +/* solve system F*x = b or F'*x = b */ + +#define lux_v_solve _glp_lux_v_solve +void lux_v_solve(LUX *lux, int tr, mpq_t x[]); +/* solve system V*x = b or V'*x = b */ + +#define lux_solve _glp_lux_solve +void lux_solve(LUX *lux, int tr, mpq_t x[]); +/* solve system A*x = b or A'*x = b */ + +#define lux_delete _glp_lux_delete +void lux_delete(LUX *lux); +/* delete LU-factorization */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/minisat/LICENSE b/resources/3rdparty/glpk-4.53/src/minisat/LICENSE new file mode 100644 index 000000000..8a6b9f362 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/minisat/LICENSE @@ -0,0 +1,20 @@ +MiniSat -- Copyright (c) 2005, Niklas Sorensson + +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 AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/resources/3rdparty/glpk-4.53/src/minisat/README b/resources/3rdparty/glpk-4.53/src/minisat/README new file mode 100644 index 000000000..c183c7d61 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/minisat/README @@ -0,0 +1,22 @@ +NOTE: Files in this subdirectory are NOT part of the GLPK package, but + are used with GLPK. + + The original code was modified according to GLPK requirements by + Andrew Makhorin <mao@gnu.org>. +************************************************************************ +MiniSat-C v1.14.1 +======================================== + +* Fixed some serious bugs. +* Tweaked to be Visual Studio friendly (by Alan Mishchenko). + This disabled reading of gzipped DIMACS files and signal handling, + but none of these features are essential (and easy to re-enable, if + wanted). + +MiniSat-C v1.14 +======================================== + +Ok, we get it. You hate C++. You hate templates. We agree; C++ is a +seriously messed up language. Although we are more pragmatic about the +quirks and maldesigns in C++, we sympathize with you. So here is a +pure C version of MiniSat, put together by Niklas Sorensson. diff --git a/resources/3rdparty/glpk-4.53/src/minisat/minisat.c b/resources/3rdparty/glpk-4.53/src/minisat/minisat.c new file mode 100644 index 000000000..f242d838a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/minisat/minisat.c @@ -0,0 +1,1299 @@ +/* minisat.c */ + +/* Modified by Andrew Makhorin <mao@gnu.org>, August 2011 */ + +/*********************************************************************** +* MiniSat -- Copyright (c) 2005, Niklas Sorensson +* http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ +* +* 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 AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +***********************************************************************/ +/* Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko */ + +#include "env.h" +#include "minisat.h" + +#if 1 /* by mao */ +static void *ymalloc(int size) +{ void *ptr; + xassert(size > 0); + ptr = malloc(size); + if (ptr == NULL) + xerror("MiniSat: no memory available\n"); + return ptr; +} + +static void *yrealloc(void *ptr, int size) +{ xassert(size > 0); + if (ptr == NULL) + ptr = malloc(size); + else + ptr = realloc(ptr, size); + if (ptr == NULL) + xerror("MiniSat: no memory available\n"); + return ptr; +} + +static void yfree(void *ptr) +{ xassert(ptr != NULL); + free(ptr); + return; +} + +#define assert xassert +#define printf xprintf +#define fflush(f) /* nop */ +#define malloc ymalloc +#define realloc yrealloc +#define free yfree +#define inline /* empty */ +#endif + +/*====================================================================*/ +/* Debug: */ + +#if 0 +#define VERBOSEDEBUG 1 +#endif + +/* For derivation output (verbosity level 2) */ +#define L_IND "%-*d" +#define L_ind solver_dlevel(s)*3+3,solver_dlevel(s) +#define L_LIT "%sx%d" +#define L_lit(p) lit_sign(p)?"~":"", (lit_var(p)) + +#if 0 /* by mao */ +/* Just like 'assert()' but expression will be evaluated in the release + version as well. */ +static inline void check(int expr) { assert(expr); } +#endif + +#if 0 /* by mao */ +static void printlits(lit* begin, lit* end) +{ + int i; + for (i = 0; i < end - begin; i++) + printf(L_LIT" ",L_lit(begin[i])); +} +#endif + +/*====================================================================*/ +/* Random numbers: */ + +/* Returns a random float 0 <= x < 1. Seed must never be 0. */ +static inline double drand(double* seed) { + int q; + *seed *= 1389796; + q = (int)(*seed / 2147483647); + *seed -= (double)q * 2147483647; + return *seed / 2147483647; } + +/* Returns a random integer 0 <= x < size. Seed must never be 0. */ +static inline int irand(double* seed, int size) { + return (int)(drand(seed) * size); } + +/*====================================================================*/ +/* Predeclarations: */ + +static void sort(void** array, int size, + int(*comp)(const void *, const void *)); + +/*====================================================================*/ +/* Clause datatype + minor functions: */ + +#if 0 /* by mao; see minisat.h */ +struct clause_t +{ + int size_learnt; + lit lits[0]; +}; +#endif + +#define clause_size(c) ((c)->size_learnt >> 1) + +#define clause_begin(c) ((c)->lits) + +#define clause_learnt(c) ((c)->size_learnt & 1) + +#define clause_activity(c) \ + (*((float*)&(c)->lits[(c)->size_learnt>>1])) + +#define clause_setactivity(c, a) \ + (void)(*((float*)&(c)->lits[(c)->size_learnt>>1]) = (a)) + +/*====================================================================*/ +/* Encode literals in clause pointers: */ + +#define clause_from_lit(l) \ + (clause*)((unsigned long)(l) + (unsigned long)(l) + 1) + +#define clause_is_lit(c) \ + ((unsigned long)(c) & 1) + +#define clause_read_lit(c) \ + (lit)((unsigned long)(c) >> 1) + +/*====================================================================*/ +/* Simple helpers: */ + +#define solver_dlevel(s) \ + (int)veci_size(&(s)->trail_lim) + +#define solver_read_wlist(s, l) \ + (vecp *)(&(s)->wlists[l]) + +static inline void vecp_remove(vecp* v, void* e) +{ + void** ws = vecp_begin(v); + int j = 0; + + for (; ws[j] != e ; j++); + assert(j < vecp_size(v)); + for (; j < vecp_size(v)-1; j++) ws[j] = ws[j+1]; + vecp_resize(v,vecp_size(v)-1); +} + +/*====================================================================*/ +/* Variable order functions: */ + +static inline void order_update(solver* s, int v) +{ /* updateorder */ + int* orderpos = s->orderpos; + double* activity = s->activity; + int* heap = veci_begin(&s->order); + int i = orderpos[v]; + int x = heap[i]; + int parent = (i - 1) / 2; + + assert(s->orderpos[v] != -1); + + while (i != 0 && activity[x] > activity[heap[parent]]){ + heap[i] = heap[parent]; + orderpos[heap[i]] = i; + i = parent; + parent = (i - 1) / 2; + } + heap[i] = x; + orderpos[x] = i; +} + +#define order_assigned(s, v) /* nop */ + +static inline void order_unassigned(solver* s, int v) +{ /* undoorder */ + int* orderpos = s->orderpos; + if (orderpos[v] == -1){ + orderpos[v] = veci_size(&s->order); + veci_push(&s->order,v); + order_update(s,v); + } +} + +static int order_select(solver* s, float random_var_freq) +{ /* selectvar */ + int* heap; + double* activity; + int* orderpos; + + lbool* values = s->assigns; + + /* Random decision: */ + if (drand(&s->random_seed) < random_var_freq){ + int next = irand(&s->random_seed,s->size); + assert(next >= 0 && next < s->size); + if (values[next] == l_Undef) + return next; + } + + /* Activity based decision: */ + + heap = veci_begin(&s->order); + activity = s->activity; + orderpos = s->orderpos; + + while (veci_size(&s->order) > 0){ + int next = heap[0]; + int size = veci_size(&s->order)-1; + int x = heap[size]; + + veci_resize(&s->order,size); + + orderpos[next] = -1; + + if (size > 0){ + double act = activity[x]; + + int i = 0; + int child = 1; + + while (child < size){ + if (child+1 < size + && activity[heap[child]] < activity[heap[child+1]]) + child++; + + assert(child < size); + + if (act >= activity[heap[child]]) + break; + + heap[i] = heap[child]; + orderpos[heap[i]] = i; + i = child; + child = 2 * child + 1; + } + heap[i] = x; + orderpos[heap[i]] = i; + } + + if (values[next] == l_Undef) + return next; + } + + return var_Undef; +} + +/*====================================================================*/ +/* Activity functions: */ + +static inline void act_var_rescale(solver* s) { + double* activity = s->activity; + int i; + for (i = 0; i < s->size; i++) + activity[i] *= 1e-100; + s->var_inc *= 1e-100; +} + +static inline void act_var_bump(solver* s, int v) { + double* activity = s->activity; + if ((activity[v] += s->var_inc) > 1e100) + act_var_rescale(s); + + /* printf("bump %d %f\n", v-1, activity[v]); */ + + if (s->orderpos[v] != -1) + order_update(s,v); + +} + +static inline void act_var_decay(solver* s) + { s->var_inc *= s->var_decay; } + +static inline void act_clause_rescale(solver* s) { + clause** cs = (clause**)vecp_begin(&s->learnts); + int i; + for (i = 0; i < vecp_size(&s->learnts); i++){ + float a = clause_activity(cs[i]); + clause_setactivity(cs[i], a * (float)1e-20); + } + s->cla_inc *= (float)1e-20; +} + +static inline void act_clause_bump(solver* s, clause *c) { + float a = clause_activity(c) + s->cla_inc; + clause_setactivity(c,a); + if (a > 1e20) act_clause_rescale(s); +} + +static inline void act_clause_decay(solver* s) + { s->cla_inc *= s->cla_decay; } + +/*====================================================================*/ +/* Clause functions: */ + +/* pre: size > 1 && no variable occurs twice + */ +static clause* clause_new(solver* s, lit* begin, lit* end, int learnt) +{ + int size; + clause* c; + int i; + + assert(end - begin > 1); + assert(learnt >= 0 && learnt < 2); + size = end - begin; + c = (clause*)malloc(sizeof(clause) + + sizeof(lit) * size + learnt * sizeof(float)); + c->size_learnt = (size << 1) | learnt; +#if 0 /* by mao; meaningless non-portable check */ + assert(((unsigned int)c & 1) == 0); +#endif + + for (i = 0; i < size; i++) + c->lits[i] = begin[i]; + + if (learnt) + *((float*)&c->lits[size]) = 0.0; + + assert(begin[0] >= 0); + assert(begin[0] < s->size*2); + assert(begin[1] >= 0); + assert(begin[1] < s->size*2); + + assert(lit_neg(begin[0]) < s->size*2); + assert(lit_neg(begin[1]) < s->size*2); + + /* vecp_push(solver_read_wlist(s,lit_neg(begin[0])),(void*)c); */ + /* vecp_push(solver_read_wlist(s,lit_neg(begin[1])),(void*)c); */ + + vecp_push(solver_read_wlist(s,lit_neg(begin[0])), + (void*)(size > 2 ? c : clause_from_lit(begin[1]))); + vecp_push(solver_read_wlist(s,lit_neg(begin[1])), + (void*)(size > 2 ? c : clause_from_lit(begin[0]))); + + return c; +} + +static void clause_remove(solver* s, clause* c) +{ + lit* lits = clause_begin(c); + assert(lit_neg(lits[0]) < s->size*2); + assert(lit_neg(lits[1]) < s->size*2); + + /* vecp_remove(solver_read_wlist(s,lit_neg(lits[0])),(void*)c); */ + /* vecp_remove(solver_read_wlist(s,lit_neg(lits[1])),(void*)c); */ + + assert(lits[0] < s->size*2); + vecp_remove(solver_read_wlist(s,lit_neg(lits[0])), + (void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[1]))); + vecp_remove(solver_read_wlist(s,lit_neg(lits[1])), + (void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[0]))); + + if (clause_learnt(c)){ + s->stats.learnts--; + s->stats.learnts_literals -= clause_size(c); + }else{ + s->stats.clauses--; + s->stats.clauses_literals -= clause_size(c); + } + + free(c); +} + +static lbool clause_simplify(solver* s, clause* c) +{ + lit* lits = clause_begin(c); + lbool* values = s->assigns; + int i; + + assert(solver_dlevel(s) == 0); + + for (i = 0; i < clause_size(c); i++){ + lbool sig = !lit_sign(lits[i]); sig += sig - 1; + if (values[lit_var(lits[i])] == sig) + return l_True; + } + return l_False; +} + +/*====================================================================*/ +/* Minor (solver) functions: */ + +void solver_setnvars(solver* s,int n) +{ + int var; + + if (s->cap < n){ + + while (s->cap < n) s->cap = s->cap*2+1; + + s->wlists = (vecp*) realloc(s->wlists, + sizeof(vecp)*s->cap*2); + s->activity = (double*) realloc(s->activity, + sizeof(double)*s->cap); + s->assigns = (lbool*) realloc(s->assigns, + sizeof(lbool)*s->cap); + s->orderpos = (int*) realloc(s->orderpos, + sizeof(int)*s->cap); + s->reasons = (clause**)realloc(s->reasons, + sizeof(clause*)*s->cap); + s->levels = (int*) realloc(s->levels, + sizeof(int)*s->cap); + s->tags = (lbool*) realloc(s->tags, + sizeof(lbool)*s->cap); + s->trail = (lit*) realloc(s->trail, + sizeof(lit)*s->cap); + } + + for (var = s->size; var < n; var++){ + vecp_new(&s->wlists[2*var]); + vecp_new(&s->wlists[2*var+1]); + s->activity [var] = 0; + s->assigns [var] = l_Undef; + s->orderpos [var] = veci_size(&s->order); + s->reasons [var] = (clause*)0; + s->levels [var] = 0; + s->tags [var] = l_Undef; + + /* does not hold because variables enqueued at top level will + not be reinserted in the heap + assert(veci_size(&s->order) == var); + */ + veci_push(&s->order,var); + order_update(s, var); + } + + s->size = n > s->size ? n : s->size; +} + +static inline bool enqueue(solver* s, lit l, clause* from) +{ + lbool* values = s->assigns; + int v = lit_var(l); + lbool val = values[v]; + lbool sig; +#ifdef VERBOSEDEBUG + printf(L_IND"enqueue("L_LIT")\n", L_ind, L_lit(l)); +#endif + + /* lbool */ sig = !lit_sign(l); sig += sig - 1; + if (val != l_Undef){ + return val == sig; + }else{ + /* New fact -- store it. */ + int* levels; + clause** reasons; +#ifdef VERBOSEDEBUG + printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(l)); +#endif + /* int* */ levels = s->levels; + /* clause** */ reasons = s->reasons; + + values [v] = sig; + levels [v] = solver_dlevel(s); + reasons[v] = from; + s->trail[s->qtail++] = l; + + order_assigned(s, v); + return true; + } +} + +static inline void assume(solver* s, lit l){ + assert(s->qtail == s->qhead); + assert(s->assigns[lit_var(l)] == l_Undef); +#ifdef VERBOSEDEBUG + printf(L_IND"assume("L_LIT")\n", L_ind, L_lit(l)); +#endif + veci_push(&s->trail_lim,s->qtail); + enqueue(s,l,(clause*)0); +} + +static inline void solver_canceluntil(solver* s, int level) { + lit* trail; + lbool* values; + clause** reasons; + int bound; + int c; + + if (solver_dlevel(s) <= level) + return; + + trail = s->trail; + values = s->assigns; + reasons = s->reasons; + bound = (veci_begin(&s->trail_lim))[level]; + + for (c = s->qtail-1; c >= bound; c--) { + int x = lit_var(trail[c]); + values [x] = l_Undef; + reasons[x] = (clause*)0; + } + + for (c = s->qhead-1; c >= bound; c--) + order_unassigned(s,lit_var(trail[c])); + + s->qhead = s->qtail = bound; + veci_resize(&s->trail_lim,level); +} + +static void solver_record(solver* s, veci* cls) +{ + lit* begin = veci_begin(cls); + lit* end = begin + veci_size(cls); + clause* c = (veci_size(cls) > 1) ? clause_new(s,begin,end,1) + : (clause*)0; + enqueue(s,*begin,c); + + assert(veci_size(cls) > 0); + + if (c != 0) { + vecp_push(&s->learnts,c); + act_clause_bump(s,c); + s->stats.learnts++; + s->stats.learnts_literals += veci_size(cls); + } +} + +static double solver_progress(solver* s) +{ + lbool* values = s->assigns; + int* levels = s->levels; + int i; + + double progress = 0; + double F = 1.0 / s->size; + for (i = 0; i < s->size; i++) + if (values[i] != l_Undef) + progress += pow(F, levels[i]); + return progress / s->size; +} + +/*====================================================================*/ +/* Major methods: */ + +static bool solver_lit_removable(solver* s, lit l, int minl) +{ + lbool* tags = s->tags; + clause** reasons = s->reasons; + int* levels = s->levels; + int top = veci_size(&s->tagged); + + assert(lit_var(l) >= 0 && lit_var(l) < s->size); + assert(reasons[lit_var(l)] != 0); + veci_resize(&s->stack,0); + veci_push(&s->stack,lit_var(l)); + + while (veci_size(&s->stack) > 0){ + clause* c; + int v = veci_begin(&s->stack)[veci_size(&s->stack)-1]; + assert(v >= 0 && v < s->size); + veci_resize(&s->stack,veci_size(&s->stack)-1); + assert(reasons[v] != 0); + c = reasons[v]; + + if (clause_is_lit(c)){ + int v = lit_var(clause_read_lit(c)); + if (tags[v] == l_Undef && levels[v] != 0){ + if (reasons[v] != 0 + && ((1 << (levels[v] & 31)) & minl)){ + veci_push(&s->stack,v); + tags[v] = l_True; + veci_push(&s->tagged,v); + }else{ + int* tagged = veci_begin(&s->tagged); + int j; + for (j = top; j < veci_size(&s->tagged); j++) + tags[tagged[j]] = l_Undef; + veci_resize(&s->tagged,top); + return false; + } + } + }else{ + lit* lits = clause_begin(c); + int i, j; + + for (i = 1; i < clause_size(c); i++){ + int v = lit_var(lits[i]); + if (tags[v] == l_Undef && levels[v] != 0){ + if (reasons[v] != 0 + && ((1 << (levels[v] & 31)) & minl)){ + + veci_push(&s->stack,lit_var(lits[i])); + tags[v] = l_True; + veci_push(&s->tagged,v); + }else{ + int* tagged = veci_begin(&s->tagged); + for (j = top; j < veci_size(&s->tagged); j++) + tags[tagged[j]] = l_Undef; + veci_resize(&s->tagged,top); + return false; + } + } + } + } + } + + return true; +} + +static void solver_analyze(solver* s, clause* c, veci* learnt) +{ + lit* trail = s->trail; + lbool* tags = s->tags; + clause** reasons = s->reasons; + int* levels = s->levels; + int cnt = 0; + lit p = lit_Undef; + int ind = s->qtail-1; + lit* lits; + int i, j, minl; + int* tagged; + + veci_push(learnt,lit_Undef); + + do{ + assert(c != 0); + + if (clause_is_lit(c)){ + lit q = clause_read_lit(c); + assert(lit_var(q) >= 0 && lit_var(q) < s->size); + if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){ + tags[lit_var(q)] = l_True; + veci_push(&s->tagged,lit_var(q)); + act_var_bump(s,lit_var(q)); + if (levels[lit_var(q)] == solver_dlevel(s)) + cnt++; + else + veci_push(learnt,q); + } + }else{ + + if (clause_learnt(c)) + act_clause_bump(s,c); + + lits = clause_begin(c); + /* printlits(lits,lits+clause_size(c)); printf("\n"); */ + for (j = (p == lit_Undef ? 0 : 1); j < clause_size(c); j++){ + lit q = lits[j]; + assert(lit_var(q) >= 0 && lit_var(q) < s->size); + if (tags[lit_var(q)] == l_Undef + && levels[lit_var(q)] > 0){ + tags[lit_var(q)] = l_True; + veci_push(&s->tagged,lit_var(q)); + act_var_bump(s,lit_var(q)); + if (levels[lit_var(q)] == solver_dlevel(s)) + cnt++; + else + veci_push(learnt,q); + } + } + } + + while (tags[lit_var(trail[ind--])] == l_Undef); + + p = trail[ind+1]; + c = reasons[lit_var(p)]; + cnt--; + + }while (cnt > 0); + + *veci_begin(learnt) = lit_neg(p); + + lits = veci_begin(learnt); + minl = 0; + for (i = 1; i < veci_size(learnt); i++){ + int lev = levels[lit_var(lits[i])]; + minl |= 1 << (lev & 31); + } + + /* simplify (full) */ + for (i = j = 1; i < veci_size(learnt); i++){ + if (reasons[lit_var(lits[i])] == 0 + || !solver_lit_removable(s,lits[i],minl)) + lits[j++] = lits[i]; + } + + /* update size of learnt + statistics */ + s->stats.max_literals += veci_size(learnt); + veci_resize(learnt,j); + s->stats.tot_literals += j; + + /* clear tags */ + tagged = veci_begin(&s->tagged); + for (i = 0; i < veci_size(&s->tagged); i++) + tags[tagged[i]] = l_Undef; + veci_resize(&s->tagged,0); + +#ifdef DEBUG + for (i = 0; i < s->size; i++) + assert(tags[i] == l_Undef); +#endif + +#ifdef VERBOSEDEBUG + printf(L_IND"Learnt {", L_ind); + for (i = 0; i < veci_size(learnt); i++) + printf(" "L_LIT, L_lit(lits[i])); +#endif + if (veci_size(learnt) > 1){ + int max_i = 1; + int max = levels[lit_var(lits[1])]; + lit tmp; + + for (i = 2; i < veci_size(learnt); i++) + if (levels[lit_var(lits[i])] > max){ + max = levels[lit_var(lits[i])]; + max_i = i; + } + + tmp = lits[1]; + lits[1] = lits[max_i]; + lits[max_i] = tmp; + } +#ifdef VERBOSEDEBUG + { + int lev = veci_size(learnt) > 1 ? levels[lit_var(lits[1])] : 0; + printf(" } at level %d\n", lev); + } +#endif +} + +clause* solver_propagate(solver* s) +{ + lbool* values = s->assigns; + clause* confl = (clause*)0; + lit* lits; + + /* printf("solver_propagate\n"); */ + while (confl == 0 && s->qtail - s->qhead > 0){ + lit p = s->trail[s->qhead++]; + vecp* ws = solver_read_wlist(s,p); + clause **begin = (clause**)vecp_begin(ws); + clause **end = begin + vecp_size(ws); + clause **i, **j; + + s->stats.propagations++; + s->simpdb_props--; + + /* printf("checking lit %d: "L_LIT"\n", veci_size(ws), + L_lit(p)); */ + for (i = j = begin; i < end; ){ + if (clause_is_lit(*i)){ + *j++ = *i; + if (!enqueue(s,clause_read_lit(*i),clause_from_lit(p))){ + confl = s->binary; + (clause_begin(confl))[1] = lit_neg(p); + (clause_begin(confl))[0] = clause_read_lit(*i++); + + /* Copy the remaining watches: */ + while (i < end) + *j++ = *i++; + } + }else{ + lit false_lit; + lbool sig; + + lits = clause_begin(*i); + + /* Make sure the false literal is data[1]: */ + false_lit = lit_neg(p); + if (lits[0] == false_lit){ + lits[0] = lits[1]; + lits[1] = false_lit; + } + assert(lits[1] == false_lit); + /* printf("checking clause: "); + printlits(lits, lits+clause_size(*i)); + printf("\n"); */ + + /* If 0th watch is true, then clause is already + satisfied. */ + sig = !lit_sign(lits[0]); sig += sig - 1; + if (values[lit_var(lits[0])] == sig){ + *j++ = *i; + }else{ + /* Look for new watch: */ + lit* stop = lits + clause_size(*i); + lit* k; + for (k = lits + 2; k < stop; k++){ + lbool sig = lit_sign(*k); sig += sig - 1; + if (values[lit_var(*k)] != sig){ + lits[1] = *k; + *k = false_lit; + vecp_push(solver_read_wlist(s, + lit_neg(lits[1])),*i); + goto next; } + } + + *j++ = *i; + /* Clause is unit under assignment: */ + if (!enqueue(s,lits[0], *i)){ + confl = *i++; + /* Copy the remaining watches: */ + while (i < end) + *j++ = *i++; + } + } + } + next: + i++; + } + + s->stats.inspects += j - (clause**)vecp_begin(ws); + vecp_resize(ws,j - (clause**)vecp_begin(ws)); + } + + return confl; +} + +static inline int clause_cmp (const void* x, const void* y) { + return clause_size((clause*)x) > 2 + && (clause_size((clause*)y) == 2 + || clause_activity((clause*)x) + < clause_activity((clause*)y)) ? -1 : 1; } + +void solver_reducedb(solver* s) +{ + int i, j; + double extra_lim = s->cla_inc / vecp_size(&s->learnts); + /* Remove any clause below this activity */ + clause** learnts = (clause**)vecp_begin(&s->learnts); + clause** reasons = s->reasons; + + sort(vecp_begin(&s->learnts), vecp_size(&s->learnts), clause_cmp); + + for (i = j = 0; i < vecp_size(&s->learnts) / 2; i++){ + if (clause_size(learnts[i]) > 2 + && reasons[lit_var(*clause_begin(learnts[i]))] + != learnts[i]) + clause_remove(s,learnts[i]); + else + learnts[j++] = learnts[i]; + } + for (; i < vecp_size(&s->learnts); i++){ + if (clause_size(learnts[i]) > 2 + && reasons[lit_var(*clause_begin(learnts[i]))] + != learnts[i] + && clause_activity(learnts[i]) < extra_lim) + clause_remove(s,learnts[i]); + else + learnts[j++] = learnts[i]; + } + + /* printf("reducedb deleted %d\n", vecp_size(&s->learnts) - j); */ + + vecp_resize(&s->learnts,j); +} + +static lbool solver_search(solver* s, int nof_conflicts, + int nof_learnts) +{ + int* levels = s->levels; + double var_decay = 0.95; + double clause_decay = 0.999; + double random_var_freq = 0.02; + + int conflictC = 0; + veci learnt_clause; + + assert(s->root_level == solver_dlevel(s)); + + s->stats.starts++; + s->var_decay = (float)(1 / var_decay ); + s->cla_decay = (float)(1 / clause_decay); + veci_resize(&s->model,0); + veci_new(&learnt_clause); + + for (;;){ + clause* confl = solver_propagate(s); + if (confl != 0){ + /* CONFLICT */ + int blevel; + +#ifdef VERBOSEDEBUG + printf(L_IND"**CONFLICT**\n", L_ind); +#endif + s->stats.conflicts++; conflictC++; + if (solver_dlevel(s) == s->root_level){ + veci_delete(&learnt_clause); + return l_False; + } + + veci_resize(&learnt_clause,0); + solver_analyze(s, confl, &learnt_clause); + blevel = veci_size(&learnt_clause) > 1 + ? levels[lit_var(veci_begin(&learnt_clause)[1])] + : s->root_level; + blevel = s->root_level > blevel ? s->root_level : blevel; + solver_canceluntil(s,blevel); + solver_record(s,&learnt_clause); + act_var_decay(s); + act_clause_decay(s); + + }else{ + /* NO CONFLICT */ + int next; + + if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ + /* Reached bound on number of conflicts: */ + s->progress_estimate = solver_progress(s); + solver_canceluntil(s,s->root_level); + veci_delete(&learnt_clause); + return l_Undef; } + + if (solver_dlevel(s) == 0) + /* Simplify the set of problem clauses: */ + solver_simplify(s); + + if (nof_learnts >= 0 + && vecp_size(&s->learnts) - s->qtail >= nof_learnts) + /* Reduce the set of learnt clauses: */ + solver_reducedb(s); + + /* New variable decision: */ + s->stats.decisions++; + next = order_select(s,(float)random_var_freq); + + if (next == var_Undef){ + /* Model found: */ + lbool* values = s->assigns; + int i; + for (i = 0; i < s->size; i++) + veci_push(&s->model,(int)values[i]); + solver_canceluntil(s,s->root_level); + veci_delete(&learnt_clause); + + /* + veci apa; veci_new(&apa); + for (i = 0; i < s->size; i++) + veci_push(&apa,(int)(s->model.ptr[i] == l_True + ? toLit(i) : lit_neg(toLit(i)))); + printf("model: "); + printlits((lit*)apa.ptr, + (lit*)apa.ptr + veci_size(&apa)); printf("\n"); + veci_delete(&apa); + */ + + return l_True; + } + + assume(s,lit_neg(toLit(next))); + } + } + +#if 0 /* by mao; unreachable code */ + return l_Undef; /* cannot happen */ +#endif +} + +/*====================================================================*/ +/* External solver functions: */ + +solver* solver_new(void) +{ + solver* s = (solver*)malloc(sizeof(solver)); + + /* initialize vectors */ + vecp_new(&s->clauses); + vecp_new(&s->learnts); + veci_new(&s->order); + veci_new(&s->trail_lim); + veci_new(&s->tagged); + veci_new(&s->stack); + veci_new(&s->model); + + /* initialize arrays */ + s->wlists = 0; + s->activity = 0; + s->assigns = 0; + s->orderpos = 0; + s->reasons = 0; + s->levels = 0; + s->tags = 0; + s->trail = 0; + + /* initialize other vars */ + s->size = 0; + s->cap = 0; + s->qhead = 0; + s->qtail = 0; + s->cla_inc = 1; + s->cla_decay = 1; + s->var_inc = 1; + s->var_decay = 1; + s->root_level = 0; + s->simpdb_assigns = 0; + s->simpdb_props = 0; + s->random_seed = 91648253; + s->progress_estimate = 0; + s->binary = (clause*)malloc(sizeof(clause) + + sizeof(lit)*2); + s->binary->size_learnt = (2 << 1); + s->verbosity = 0; + + s->stats.starts = 0; + s->stats.decisions = 0; + s->stats.propagations = 0; + s->stats.inspects = 0; + s->stats.conflicts = 0; + s->stats.clauses = 0; + s->stats.clauses_literals = 0; + s->stats.learnts = 0; + s->stats.learnts_literals = 0; + s->stats.max_literals = 0; + s->stats.tot_literals = 0; + + return s; +} + +void solver_delete(solver* s) +{ + int i; + for (i = 0; i < vecp_size(&s->clauses); i++) + free(vecp_begin(&s->clauses)[i]); + + for (i = 0; i < vecp_size(&s->learnts); i++) + free(vecp_begin(&s->learnts)[i]); + + /* delete vectors */ + vecp_delete(&s->clauses); + vecp_delete(&s->learnts); + veci_delete(&s->order); + veci_delete(&s->trail_lim); + veci_delete(&s->tagged); + veci_delete(&s->stack); + veci_delete(&s->model); + free(s->binary); + + /* delete arrays */ + if (s->wlists != 0){ + int i; + for (i = 0; i < s->size*2; i++) + vecp_delete(&s->wlists[i]); + + /* if one is different from null, all are */ + free(s->wlists); + free(s->activity ); + free(s->assigns ); + free(s->orderpos ); + free(s->reasons ); + free(s->levels ); + free(s->trail ); + free(s->tags ); + } + + free(s); +} + +bool solver_addclause(solver* s, lit* begin, lit* end) +{ + lit *i,*j; + int maxvar; + lbool* values; + lit last; + + if (begin == end) return false; + + /* printlits(begin,end); printf("\n"); */ + /* insertion sort */ + maxvar = lit_var(*begin); + for (i = begin + 1; i < end; i++){ + lit l = *i; + maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar; + for (j = i; j > begin && *(j-1) > l; j--) + *j = *(j-1); + *j = l; + } + solver_setnvars(s,maxvar+1); + + /* printlits(begin,end); printf("\n"); */ + values = s->assigns; + + /* delete duplicates */ + last = lit_Undef; + for (i = j = begin; i < end; i++){ + /* printf("lit: "L_LIT", value = %d\n", L_lit(*i), + (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)])); */ + lbool sig = !lit_sign(*i); sig += sig - 1; + if (*i == lit_neg(last) || sig == values[lit_var(*i)]) + return true; /* tautology */ + else if (*i != last && values[lit_var(*i)] == l_Undef) + last = *j++ = *i; + } + + /* printf("final: "); printlits(begin,j); printf("\n"); */ + + if (j == begin) /* empty clause */ + return false; + else if (j - begin == 1) /* unit clause */ + return enqueue(s,*begin,(clause*)0); + + /* create new clause */ + vecp_push(&s->clauses,clause_new(s,begin,j,0)); + + s->stats.clauses++; + s->stats.clauses_literals += j - begin; + + return true; +} + +bool solver_simplify(solver* s) +{ + clause** reasons; + int type; + + assert(solver_dlevel(s) == 0); + + if (solver_propagate(s) != 0) + return false; + + if (s->qhead == s->simpdb_assigns || s->simpdb_props > 0) + return true; + + reasons = s->reasons; + for (type = 0; type < 2; type++){ + vecp* cs = type ? &s->learnts : &s->clauses; + clause** cls = (clause**)vecp_begin(cs); + + int i, j; + for (j = i = 0; i < vecp_size(cs); i++){ + if (reasons[lit_var(*clause_begin(cls[i]))] != cls[i] && + clause_simplify(s,cls[i]) == l_True) + clause_remove(s,cls[i]); + else + cls[j++] = cls[i]; + } + vecp_resize(cs,j); + } + + s->simpdb_assigns = s->qhead; + /* (shouldn't depend on 'stats' really, but it will do for now) */ + s->simpdb_props = (int)(s->stats.clauses_literals + + s->stats.learnts_literals); + + return true; +} + +bool solver_solve(solver* s, lit* begin, lit* end) +{ + double nof_conflicts = 100; + double nof_learnts = solver_nclauses(s) / 3; + lbool status = l_Undef; + lbool* values = s->assigns; + lit* i; + + /* printf("solve: "); printlits(begin, end); printf("\n"); */ + for (i = begin; i < end; i++){ + switch (lit_sign(*i) ? -values[lit_var(*i)] + : values[lit_var(*i)]){ + case 1: /* l_True: */ + break; + case 0: /* l_Undef */ + assume(s, *i); + if (solver_propagate(s) == NULL) + break; + /* falltrough */ + case -1: /* l_False */ + solver_canceluntil(s, 0); + return false; + } + } + + s->root_level = solver_dlevel(s); + + if (s->verbosity >= 1){ + printf("==================================[MINISAT]============" + "=======================\n"); + printf("| Conflicts | ORIGINAL | LEARNT " + " | Progress |\n"); + printf("| | Clauses Literals | Limit Clauses Litera" + "ls Lit/Cl | |\n"); + printf("=======================================================" + "=======================\n"); + } + + while (status == l_Undef){ + double Ratio = (s->stats.learnts == 0)? 0.0 : + s->stats.learnts_literals / (double)s->stats.learnts; + + if (s->verbosity >= 1){ + printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %" + "6.3f %% |\n", + (double)s->stats.conflicts, + (double)s->stats.clauses, + (double)s->stats.clauses_literals, + (double)nof_learnts, + (double)s->stats.learnts, + (double)s->stats.learnts_literals, + Ratio, + s->progress_estimate*100); + fflush(stdout); + } + status = solver_search(s,(int)nof_conflicts, (int)nof_learnts); + nof_conflicts *= 1.5; + nof_learnts *= 1.1; + } + if (s->verbosity >= 1) + printf("=======================================================" + "=======================\n"); + + solver_canceluntil(s,0); + return status != l_False; +} + +int solver_nvars(solver* s) +{ + return s->size; +} + +int solver_nclauses(solver* s) +{ + return vecp_size(&s->clauses); +} + +int solver_nconflicts(solver* s) +{ + return (int)s->stats.conflicts; +} + +/*====================================================================*/ +/* Sorting functions (sigh): */ + +static inline void selectionsort(void** array, int size, + int(*comp)(const void *, const void *)) +{ + int i, j, best_i; + void* tmp; + + for (i = 0; i < size-1; i++){ + best_i = i; + for (j = i+1; j < size; j++){ + if (comp(array[j], array[best_i]) < 0) + best_i = j; + } + tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; + } +} + +static void sortrnd(void** array, int size, + int(*comp)(const void *, const void *), + double* seed) +{ + if (size <= 15) + selectionsort(array, size, comp); + + else{ + void* pivot = array[irand(seed, size)]; + void* tmp; + int i = -1; + int j = size; + + for(;;){ + do i++; while(comp(array[i], pivot)<0); + do j--; while(comp(pivot, array[j])<0); + + if (i >= j) break; + + tmp = array[i]; array[i] = array[j]; array[j] = tmp; + } + + sortrnd(array , i , comp, seed); + sortrnd(&array[i], size-i, comp, seed); + } +} + +static void sort(void** array, int size, + int(*comp)(const void *, const void *)) +{ + double seed = 91648253; + sortrnd(array,size,comp,&seed); +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/minisat/minisat.h b/resources/3rdparty/glpk-4.53/src/minisat/minisat.h new file mode 100644 index 000000000..2733e8d63 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/minisat/minisat.h @@ -0,0 +1,230 @@ +/* minisat.h */ + +/* Modified by Andrew Makhorin <mao@gnu.org>, August 2011 */ + +/*********************************************************************** +* MiniSat -- Copyright (c) 2005, Niklas Sorensson +* http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ +* +* 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 AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +***********************************************************************/ +/* Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko */ + +#ifndef MINISAT_H +#define MINISAT_H + +/*====================================================================*/ +/* Simple types: */ + +typedef int bool; + +#define true 1 +#define false 0 + +typedef int lit; +#if 0 /* by mao */ +typedef char lbool; +#else +typedef int lbool; +#endif + +#define var_Undef (int)(-1) +#define lit_Undef (lit)(-2) + +#define l_Undef (lbool)0 +#define l_True (lbool)1 +#define l_False (lbool)(-1) + +#define toLit(v) (lit)((v) + (v)) +#define lit_neg(l) (lit)((l) ^ 1) +#define lit_var(l) (int)((l) >> 1) +#define lit_sign(l) (int)((l) & 1) + +/*====================================================================*/ +/* Vectors: */ + +/* vector of 32-bit intergers (added for 64-bit portability) */ +typedef struct /* veci_t */ { + int size; + int cap; + int* ptr; +} veci; + +#define veci_new(v) \ +{ (v)->size = 0; \ + (v)->cap = 4; \ + (v)->ptr = (int*)malloc(sizeof(int)*(v)->cap); \ +} + +#define veci_delete(v) free((v)->ptr) + +#define veci_begin(v) ((v)->ptr) + +#define veci_size(v) ((v)->size) + +#define veci_resize(v, k) (void)((v)->size = (k)) +/* only safe to shrink !! */ + +#define veci_push(v, e) \ +{ if ((v)->size == (v)->cap) \ + { int newsize = (v)->cap * 2+1; \ + (v)->ptr = (int*)realloc((v)->ptr,sizeof(int)*newsize); \ + (v)->cap = newsize; \ + } \ + (v)->ptr[(v)->size++] = (e); \ +} + +/* vector of 32- or 64-bit pointers */ +typedef struct /* vecp_t */ { + int size; + int cap; + void** ptr; +} vecp; + +#define vecp_new(v) \ +{ (v)->size = 0; \ + (v)->cap = 4; \ + (v)->ptr = (void**)malloc(sizeof(void*)*(v)->cap); \ +} + +#define vecp_delete(v) free((v)->ptr) + +#define vecp_begin(v) ((v)->ptr) + +#define vecp_size(v) ((v)->size) + +#define vecp_resize(v, k) (void)((v)->size = (k)) +/* only safe to shrink !! */ + +#define vecp_push(v, e) \ +{ if ((v)->size == (v)->cap) \ + { int newsize = (v)->cap * 2+1; \ + (v)->ptr = (void**)realloc((v)->ptr,sizeof(void*)*newsize); \ + (v)->cap = newsize; \ + } \ + (v)->ptr[(v)->size++] = (e); \ +} + +/*====================================================================*/ +/* Solver representation: */ + +typedef struct /* clause_t */ +{ + int size_learnt; + lit lits[1]; +} clause; + +typedef struct /* stats_t */ +{ + double starts, decisions, propagations, inspects, conflicts; + double clauses, clauses_literals, learnts, learnts_literals, + max_literals, tot_literals; +} stats; + +typedef struct /* solver_t */ +{ + int size; /* nof variables */ + int cap; /* size of varmaps */ + int qhead; /* Head index of queue. */ + int qtail; /* Tail index of queue. */ + + /* clauses */ + vecp clauses; /* List of problem constraints. + (contains: clause*) */ + vecp learnts; /* List of learnt clauses. + (contains: clause*) */ + + /* activities */ + double var_inc; /* Amount to bump next variable with. */ + double var_decay; /* INVERSE decay factor for variable + activity: stores 1/decay. */ + float cla_inc; /* Amount to bump next clause with. */ + float cla_decay; /* INVERSE decay factor for clause + activity: stores 1/decay. */ + + vecp* wlists; + double* activity; /* A heuristic measurement of the activity + of a variable. */ + lbool* assigns; /* Current values of variables. */ + int* orderpos; /* Index in variable order. */ + clause** reasons; + int* levels; + lit* trail; + + clause* binary; /* A temporary binary clause */ + lbool* tags; + veci tagged; /* (contains: var) */ + veci stack; /* (contains: var) */ + + veci order; /* Variable order. (heap) (contains: var) */ + veci trail_lim; /* Separator indices for different decision + levels in 'trail'. (contains: int) */ + veci model; /* If problem is solved, this vector + contains the model (contains: lbool). */ + + int root_level; /* Level of first proper decision. */ + int simpdb_assigns;/* Number of top-level assignments at last + 'simplifyDB()'. */ + int simpdb_props; /* Number of propagations before next + 'simplifyDB()'. */ + double random_seed; + double progress_estimate; + int verbosity; /* Verbosity level. + 0=silent, + 1=some progress report, + 2=everything */ + + stats stats; +} solver; + +/*====================================================================*/ +/* Public interface: */ + +#if 1 /* by mao; to keep namespace clean */ +#define solver_new _glp_minisat_new +#define solver_delete _glp_minisat_delete +#define solver_addclause _glp_minisat_addclause +#define solver_simplify _glp_minisat_simplify +#define solver_solve _glp_minisat_solve +#define solver_nvars _glp_minisat_nvars +#define solver_nclauses _glp_minisat_nclauses +#define solver_nconflicts _glp_minisat_nconflicts +#define solver_setnvars _glp_minisat_setnvars +#define solver_propagate _glp_minisat_propagate +#define solver_reducedb _glp_minisat_reducedb +#endif + +solver* solver_new(void); +void solver_delete(solver* s); + +bool solver_addclause(solver* s, lit* begin, lit* end); +bool solver_simplify(solver* s); +bool solver_solve(solver* s, lit* begin, lit* end); + +int solver_nvars(solver* s); +int solver_nclauses(solver* s); +int solver_nconflicts(solver* s); + +void solver_setnvars(solver* s,int n); + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/bignum.c b/resources/3rdparty/glpk-4.53/src/misc/bignum.c new file mode 100644 index 000000000..f91df5fd0 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/bignum.c @@ -0,0 +1,286 @@ +/* bignum.c (bignum arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2006, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "bignum.h" + +/*********************************************************************** +* Two routines below are intended to multiply and divide unsigned +* integer numbers of arbitrary precision. +* +* The routines assume that an unsigned integer number is represented in +* the positional numeral system with the base 2^16 = 65536, i.e. each +* "digit" of the number is in the range [0, 65535] and represented as +* a 16-bit value of the unsigned short type. In other words, a number x +* has the following representation: +* +* n-1 +* x = sum d[j] * 65536^j, +* j=0 +* +* where n is the number of places (positions), and d[j] is j-th "digit" +* of x, 0 <= d[j] <= 65535. +***********************************************************************/ + +/*********************************************************************** +* NAME +* +* bigmul - multiply unsigned integer numbers of arbitrary precision +* +* SYNOPSIS +* +* #include "bignum.h" +* void bigmul(int n, int m, unsigned short x[], unsigned short y[]); +* +* DESCRIPTION +* +* The routine bigmul multiplies unsigned integer numbers of arbitrary +* precision. +* +* n is the number of digits of multiplicand, n >= 1; +* +* m is the number of digits of multiplier, m >= 1; +* +* x is an array containing digits of the multiplicand in elements +* x[m], x[m+1], ..., x[n+m-1]. Contents of x[0], x[1], ..., x[m-1] are +* ignored on entry. +* +* y is an array containing digits of the multiplier in elements y[0], +* y[1], ..., y[m-1]. +* +* On exit digits of the product are stored in elements x[0], x[1], ..., +* x[n+m-1]. The array y is not changed. */ + +void bigmul(int n, int m, unsigned short x[], unsigned short y[]) +{ int i, j; + unsigned int t; + xassert(n >= 1); + xassert(m >= 1); + for (j = 0; j < m; j++) x[j] = 0; + for (i = 0; i < n; i++) + { if (x[i+m]) + { t = 0; + for (j = 0; j < m; j++) + { t += (unsigned int)x[i+m] * (unsigned int)y[j] + + (unsigned int)x[i+j]; + x[i+j] = (unsigned short)t; + t >>= 16; + } + x[i+m] = (unsigned short)t; + } + } + return; +} + +/*********************************************************************** +* NAME +* +* bigdiv - divide unsigned integer numbers of arbitrary precision +* +* SYNOPSIS +* +* #include "bignum.h" +* void bigdiv(int n, int m, unsigned short x[], unsigned short y[]); +* +* DESCRIPTION +* +* The routine bigdiv divides one unsigned integer number of arbitrary +* precision by another with the algorithm described in [1]. +* +* n is the difference between the number of digits of dividend and the +* number of digits of divisor, n >= 0. +* +* m is the number of digits of divisor, m >= 1. +* +* x is an array containing digits of the dividend in elements x[0], +* x[1], ..., x[n+m-1]. +* +* y is an array containing digits of the divisor in elements y[0], +* y[1], ..., y[m-1]. The highest digit y[m-1] must be non-zero. +* +* On exit n+1 digits of the quotient are stored in elements x[m], +* x[m+1], ..., x[n+m], and m digits of the remainder are stored in +* elements x[0], x[1], ..., x[m-1]. The array y is changed but then +* restored. +* +* REFERENCES +* +* 1. D. Knuth. The Art of Computer Programming. Vol. 2: Seminumerical +* Algorithms. Stanford University, 1969. */ + +void bigdiv(int n, int m, unsigned short x[], unsigned short y[]) +{ int i, j; + unsigned int t; + unsigned short d, q, r; + xassert(n >= 0); + xassert(m >= 1); + xassert(y[m-1] != 0); + /* special case when divisor has the only digit */ + if (m == 1) + { d = 0; + for (i = n; i >= 0; i--) + { t = ((unsigned int)d << 16) + (unsigned int)x[i]; + x[i+1] = (unsigned short)(t / y[0]); + d = (unsigned short)(t % y[0]); + } + x[0] = d; + goto done; + } + /* multiply dividend and divisor by a normalizing coefficient in + * order to provide the condition y[m-1] >= base / 2 */ + d = (unsigned short)(0x10000 / ((unsigned int)y[m-1] + 1)); + if (d == 1) + x[n+m] = 0; + else + { t = 0; + for (i = 0; i < n+m; i++) + { t += (unsigned int)x[i] * (unsigned int)d; + x[i] = (unsigned short)t; + t >>= 16; + } + x[n+m] = (unsigned short)t; + t = 0; + for (j = 0; j < m; j++) + { t += (unsigned int)y[j] * (unsigned int)d; + y[j] = (unsigned short)t; + t >>= 16; + } + } + /* main loop */ + for (i = n; i >= 0; i--) + { /* estimate and correct the current digit of quotient */ + if (x[i+m] < y[m-1]) + { t = ((unsigned int)x[i+m] << 16) + (unsigned int)x[i+m-1]; + q = (unsigned short)(t / (unsigned int)y[m-1]); + r = (unsigned short)(t % (unsigned int)y[m-1]); + if (q == 0) goto putq; else goto test; + } + q = 0; + r = x[i+m-1]; +decr: q--; /* if q = 0 then q-- = 0xFFFF */ + t = (unsigned int)r + (unsigned int)y[m-1]; + r = (unsigned short)t; + if (t > 0xFFFF) goto msub; +test: t = (unsigned int)y[m-2] * (unsigned int)q; + if ((unsigned short)(t >> 16) > r) goto decr; + if ((unsigned short)(t >> 16) < r) goto msub; + if ((unsigned short)t > x[i+m-2]) goto decr; +msub: /* now subtract divisor multiplied by the current digit of + * quotient from the current dividend */ + if (q == 0) goto putq; + t = 0; + for (j = 0; j < m; j++) + { t += (unsigned int)y[j] * (unsigned int)q; + if (x[i+j] < (unsigned short)t) t += 0x10000; + x[i+j] -= (unsigned short)t; + t >>= 16; + } + if (x[i+m] >= (unsigned short)t) goto putq; + /* perform correcting addition, because the current digit of + * quotient is greater by one than its correct value */ + q--; + t = 0; + for (j = 0; j < m; j++) + { t += (unsigned int)x[i+j] + (unsigned int)y[j]; + x[i+j] = (unsigned short)t; + t >>= 16; + } +putq: /* store the current digit of quotient */ + x[i+m] = q; + } + /* divide divisor and remainder by the normalizing coefficient in + * order to restore their original values */ + if (d > 1) + { t = 0; + for (i = m-1; i >= 0; i--) + { t = (t << 16) + (unsigned int)x[i]; + x[i] = (unsigned short)(t / (unsigned int)d); + t %= (unsigned int)d; + } + t = 0; + for (j = m-1; j >= 0; j--) + { t = (t << 16) + (unsigned int)y[j]; + y[j] = (unsigned short)(t / (unsigned int)d); + t %= (unsigned int)d; + } + } +done: return; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include "rng.h" + +#define N_MAX 7 +/* maximal number of digits in multiplicand */ + +#define M_MAX 5 +/* maximal number of digits in multiplier */ + +#define N_TEST 1000000 +/* number of tests */ + +int main(void) +{ RNG *rand; + int d, j, n, m, test; + unsigned short x[N_MAX], y[M_MAX], z[N_MAX+M_MAX]; + rand = rng_create_rand(); + for (test = 1; test <= N_TEST; test++) + { /* x[0,...,n-1] := multiplicand */ + n = 1 + rng_unif_rand(rand, N_MAX-1); + assert(1 <= n && n <= N_MAX); + for (j = 0; j < n; j++) + { d = rng_unif_rand(rand, 65536); + assert(0 <= d && d <= 65535); + x[j] = (unsigned short)d; + } + /* y[0,...,m-1] := multiplier */ + m = 1 + rng_unif_rand(rand, M_MAX-1); + assert(1 <= m && m <= M_MAX); + for (j = 0; j < m; j++) + { d = rng_unif_rand(rand, 65536); + assert(0 <= d && d <= 65535); + y[j] = (unsigned short)d; + } + if (y[m-1] == 0) y[m-1] = 1; + /* z[0,...,n+m-1] := x * y */ + for (j = 0; j < n; j++) z[m+j] = x[j]; + bigmul(n, m, z, y); + /* z[0,...,m-1] := z mod y, z[m,...,n+m-1] := z div y */ + bigdiv(n, m, z, y); + /* z mod y must be 0 */ + for (j = 0; j < m; j++) assert(z[j] == 0); + /* z div y must be x */ + for (j = 0; j < n; j++) assert(z[m+j] == x[j]); + } + fprintf(stderr, "%d tests successfully passed\n", N_TEST); + rng_delete_rand(rand); + return 0; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/bignum.h b/resources/3rdparty/glpk-4.53/src/misc/bignum.h new file mode 100644 index 000000000..b6361d2bc --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/bignum.h @@ -0,0 +1,37 @@ +/* bignum.h (arbitrary precision arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2006, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef BIGNUM_H +#define BIGNUM_H + +#define bigmul _glp_bigmul +void bigmul(int n, int m, unsigned short x[], unsigned short y[]); +/* multiply unsigned integer numbers of arbitrary precision */ + +#define bigdiv _glp_bigdiv +void bigdiv(int n, int m, unsigned short x[], unsigned short y[]); +/* divide unsigned integer numbers of arbitrary precision */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/dmp.c b/resources/3rdparty/glpk-4.53/src/misc/dmp.c new file mode 100644 index 000000000..e92b3e90e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/dmp.c @@ -0,0 +1,243 @@ +/* dmp.c (dynamic memory pool) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "dmp.h" + +struct DMP +{ /* dynamic memory pool */ + void *avail[32]; + /* avail[k], 0 <= k <= 31, is a pointer to first available (free) + * atom of (k+1)*8 bytes long; at the beginning of each free atom + * there is a pointer to another free atom of the same size */ + void *block; + /* pointer to most recently allocated memory block; at the + * beginning of each allocated memory block there is a pointer to + * previously allocated memory block */ + int used; + /* number of bytes used in most recently allocated memory block */ + size_t count; + /* number of atoms which are currently in use */ +}; + +#define DMP_BLK_SIZE 8000 +/* size of memory blocks, in bytes, allocated for memory pools */ + +struct prefix +{ /* atom prefix (for debugging only) */ + DMP *pool; + /* dynamic memory pool */ + int size; + /* original atom size, in bytes */ +}; + +#define prefix_size ((sizeof(struct prefix) + 7) & ~7) +/* size of atom prefix rounded up to multiple of 8 bytes */ + +int dmp_debug; +/* debug mode flag */ + +/*********************************************************************** +* NAME +* +* dmp_create_pool - create dynamic memory pool +* +* SYNOPSIS +* +* #include "dmp.h" +* DMP *dmp_create_pool(void); +* +* DESCRIPTION +* +* The routine dmp_create_pool creates a dynamic memory pool. +* +* RETURNS +* +* The routine returns a pointer to the memory pool created. */ + +DMP *dmp_create_pool(void) +{ DMP *pool; + int k; + xassert(sizeof(void *) <= 8); + if (dmp_debug) + xprintf("dmp_create_pool: warning: debug mode is on\n"); + pool = talloc(1, DMP); + for (k = 0; k <= 31; k++) + pool->avail[k] = NULL; + pool->block = NULL; + pool->used = DMP_BLK_SIZE; + pool->count = 0; + return pool; +} + +/*********************************************************************** +* NAME +* +* dmp_get_atom - get free atom from dynamic memory pool +* +* SYNOPSIS +* +* #include "dmp.h" +* void *dmp_get_atom(DMP *pool, int size); +* +* DESCRIPTION +* +* The routine dmp_get_atom obtains a free atom (memory space) from the +* specified memory pool. +* +* The parameter size is the atom size, in bytes, 1 <= size <= 256. +* +* Note that the free atom contains arbitrary data, not binary zeros. +* +* RETURNS +* +* The routine returns a pointer to the free atom obtained. */ + +void *dmp_get_atom(DMP *pool, int size) +{ void *atom; + int k, need; + xassert(1 <= size && size <= 256); + /* round up atom size to multiple of 8 bytes */ + need = (size + 7) & ~7; + /* determine number of corresponding list of free atoms */ + k = (need >> 3) - 1; + /* obtain free atom */ + if (pool->avail[k] == NULL) + { /* corresponding list of free atoms is empty */ + /* if debug mode is on, add atom prefix size */ + if (dmp_debug) + need += prefix_size; + if (pool->used + need > DMP_BLK_SIZE) + { /* allocate new memory block */ + void *block = talloc(DMP_BLK_SIZE, char); + *(void **)block = pool->block; + pool->block = block; + pool->used = 8; /* sufficient to store pointer */ + } + /* allocate new atom in current memory block */ + atom = (char *)pool->block + pool->used; + pool->used += need; + } + else + { /* obtain atom from corresponding list of free atoms */ + atom = pool->avail[k]; + pool->avail[k] = *(void **)atom; + } + /* if debug mode is on, fill atom prefix */ + if (dmp_debug) + { ((struct prefix *)atom)->pool = pool; + ((struct prefix *)atom)->size = size; + atom = (char *)atom + prefix_size; + } + /* increase number of allocated atoms */ + pool->count++; + return atom; +} + +/*********************************************************************** +* NAME +* +* dmp_free_atom - return atom to dynamic memory pool +* +* SYNOPSIS +* +* #include "dmp.h" +* void dmp_free_atom(DMP *pool, void *atom, int size); +* +* DESCRIPTION +* +* The routine dmp_free_atom returns the specified atom (memory space) +* to the specified memory pool, making the atom free. +* +* The parameter size is the atom size, in bytes, 1 <= size <= 256. +* +* Note that the atom can be returned only to the pool, from which it +* was obtained, and its size must be exactly the same as on obtaining +* it from the pool. */ + +void dmp_free_atom(DMP *pool, void *atom, int size) +{ int k; + xassert(1 <= size && size <= 256); + /* determine number of corresponding list of free atoms */ + k = ((size + 7) >> 3) - 1; + /* if debug mode is on, check atom prefix */ + if (dmp_debug) + { atom = (char *)atom - prefix_size; + xassert(((struct prefix *)atom)->pool == pool); + xassert(((struct prefix *)atom)->size == size); + } + /* return atom to corresponding list of free atoms */ + *(void **)atom = pool->avail[k]; + pool->avail[k] = atom; + /* decrease number of allocated atoms */ + xassert(pool->count > 0); + pool->count--; + return; +} + +/*********************************************************************** +* NAME +* +* dmp_in_use - determine how many atoms are still in use +* +* SYNOPSIS +* +* #include "dmp.h" +* size_t dmp_in_use(DMP *pool); +* +* RETURNS +* +* The routine returns the number of atoms of the specified memory pool +* which are still in use. */ + +size_t dmp_in_use(DMP *pool) +{ return + pool->count; +} + +/*********************************************************************** +* NAME +* +* dmp_delete_pool - delete dynamic memory pool +* +* SYNOPSIS +* +* #include "dmp.h" +* void dmp_delete_pool(DMP *pool); +* +* DESCRIPTION +* +* The routine dmp_delete_pool deletes the specified dynamic memory +* pool freeing all the memory allocated to this object. */ + +void dmp_delete_pool(DMP *pool) +{ while (pool->block != NULL) + { void *block = pool->block; + pool->block = *(void **)block; + tfree(block); + } + tfree(pool); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/dmp.h b/resources/3rdparty/glpk-4.53/src/misc/dmp.h new file mode 100644 index 000000000..e2ef01a89 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/dmp.h @@ -0,0 +1,63 @@ +/* dmp.h (dynamic memory pool) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef DMP_H +#define DMP_H + +#include "stdc.h" + +typedef struct DMP DMP; + +#define dmp_debug _glp_dmp_debug +extern int dmp_debug; +/* debug mode flag */ + +#define dmp_create_pool _glp_dmp_create_pool +DMP *dmp_create_pool(void); +/* create dynamic memory pool */ + +#define dmp_talloc(pool, type) \ + ((type *)dmp_get_atom(pool, sizeof(type))) + +#define dmp_get_atom _glp_dmp_get_atom +void *dmp_get_atom(DMP *pool, int size); +/* get free atom from dynamic memory pool */ + +#define dmp_tfree(pool, atom) \ + dmp_free_atom(pool, atom, sizeof(*(atom))) + +#define dmp_free_atom _glp_dmp_free_atom +void dmp_free_atom(DMP *pool, void *atom, int size); +/* return atom to dynamic memory pool */ + +#define dmp_in_use _glp_dmp_in_use +size_t dmp_in_use(DMP *pool); +/* determine how many atoms are still in use */ + +#define dmp_delete_pool _glp_dmp_delete_pool +void dmp_delete_pool(DMP *pool); +/* delete dynamic memory pool */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/ffalg.c b/resources/3rdparty/glpk-4.53/src/misc/ffalg.c new file mode 100644 index 000000000..c55d8d4a2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/ffalg.c @@ -0,0 +1,221 @@ +/* ffalg.c (Ford-Fulkerson algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "ffalg.h" + +/*********************************************************************** +* NAME +* +* ffalg - Ford-Fulkerson algorithm +* +* SYNOPSIS +* +* #include "ffalg.h" +* void ffalg(int nv, int na, const int tail[], const int head[], +* int s, int t, const int cap[], int x[], char cut[]); +* +* DESCRIPTION +* +* The routine ffalg implements the Ford-Fulkerson algorithm to find a +* maximal flow in the specified flow network. +* +* INPUT PARAMETERS +* +* nv is the number of nodes, nv >= 2. +* +* na is the number of arcs, na >= 0. +* +* tail[a], a = 1,...,na, is the index of tail node of arc a. +* +* head[a], a = 1,...,na, is the index of head node of arc a. +* +* s is the source node index, 1 <= s <= nv. +* +* t is the sink node index, 1 <= t <= nv, t != s. +* +* cap[a], a = 1,...,na, is the capacity of arc a, cap[a] >= 0. +* +* NOTE: Multiple arcs are allowed, but self-loops are not allowed. +* +* OUTPUT PARAMETERS +* +* x[a], a = 1,...,na, is optimal value of the flow through arc a. +* +* cut[i], i = 1,...,nv, is 1 if node i is labelled, and 0 otherwise. +* The set of arcs, whose one endpoint is labelled and other is not, +* defines the minimal cut corresponding to the maximal flow found. +* If the parameter cut is NULL, the cut information are not stored. +* +* REFERENCES +* +* L.R.Ford, Jr., and D.R.Fulkerson, "Flows in Networks," The RAND +* Corp., Report R-375-PR (August 1962), Chap. I "Static Maximal Flow," +* pp.30-33. */ + +void ffalg(int nv, int na, const int tail[], const int head[], + int s, int t, const int cap[], int x[], char cut[]) +{ int a, delta, i, j, k, pos1, pos2, temp, + *ptr, *arc, *link, *list; + /* sanity checks */ + xassert(nv >= 2); + xassert(na >= 0); + xassert(1 <= s && s <= nv); + xassert(1 <= t && t <= nv); + xassert(s != t); + for (a = 1; a <= na; a++) + { i = tail[a], j = head[a]; + xassert(1 <= i && i <= nv); + xassert(1 <= j && j <= nv); + xassert(i != j); + xassert(cap[a] >= 0); + } + /* allocate working arrays */ + ptr = xcalloc(1+nv+1, sizeof(int)); + arc = xcalloc(1+na+na, sizeof(int)); + link = xcalloc(1+nv, sizeof(int)); + list = xcalloc(1+nv, sizeof(int)); + /* ptr[i] := (degree of node i) */ + for (i = 1; i <= nv; i++) + ptr[i] = 0; + for (a = 1; a <= na; a++) + { ptr[tail[a]]++; + ptr[head[a]]++; + } + /* initialize arc pointers */ + ptr[1]++; + for (i = 1; i < nv; i++) + ptr[i+1] += ptr[i]; + ptr[nv+1] = ptr[nv]; + /* build arc lists */ + for (a = 1; a <= na; a++) + { arc[--ptr[tail[a]]] = a; + arc[--ptr[head[a]]] = a; + } + xassert(ptr[1] == 1); + xassert(ptr[nv+1] == na+na+1); + /* now the indices of arcs incident to node i are stored in + * locations arc[ptr[i]], arc[ptr[i]+1], ..., arc[ptr[i+1]-1] */ + /* initialize arc flows */ + for (a = 1; a <= na; a++) + x[a] = 0; +loop: /* main loop starts here */ + /* build augmenting tree rooted at s */ + /* link[i] = 0 means that node i is not labelled yet; + * link[i] = a means that arc a immediately precedes node i */ + /* initially node s is labelled as the root */ + for (i = 1; i <= nv; i++) + link[i] = 0; + link[s] = -1, list[1] = s, pos1 = pos2 = 1; + /* breadth first search */ + while (pos1 <= pos2) + { /* dequeue node i */ + i = list[pos1++]; + /* consider all arcs incident to node i */ + for (k = ptr[i]; k < ptr[i+1]; k++) + { a = arc[k]; + if (tail[a] == i) + { /* a = i->j is a forward arc from s to t */ + j = head[a]; + /* if node j has been labelled, skip the arc */ + if (link[j] != 0) continue; + /* if the arc does not allow increasing the flow through + * it, skip the arc */ + if (x[a] == cap[a]) continue; + } + else if (head[a] == i) + { /* a = i<-j is a backward arc from s to t */ + j = tail[a]; + /* if node j has been labelled, skip the arc */ + if (link[j] != 0) continue; + /* if the arc does not allow decreasing the flow through + * it, skip the arc */ + if (x[a] == 0) continue; + } + else + xassert(a != a); + /* label node j and enqueue it */ + link[j] = a, list[++pos2] = j; + /* check for breakthrough */ + if (j == t) goto brkt; + } + } + /* NONBREAKTHROUGH */ + /* no augmenting path exists; current flow is maximal */ + /* store minimal cut information, if necessary */ + if (cut != NULL) + { for (i = 1; i <= nv; i++) + cut[i] = (char)(link[i] != 0); + } + goto done; +brkt: /* BREAKTHROUGH */ + /* walk through arcs of the augmenting path (s, ..., t) found in + * the reverse order and determine maximal change of the flow */ + delta = 0; + for (j = t; j != s; j = i) + { /* arc a immediately precedes node j in the path */ + a = link[j]; + if (head[a] == j) + { /* a = i->j is a forward arc of the cycle */ + i = tail[a]; + /* x[a] may be increased until its upper bound */ + temp = cap[a] - x[a]; + } + else if (tail[a] == j) + { /* a = i<-j is a backward arc of the cycle */ + i = head[a]; + /* x[a] may be decreased until its lower bound */ + temp = x[a]; + } + else + xassert(a != a); + if (delta == 0 || delta > temp) delta = temp; + } + xassert(delta > 0); + /* increase the flow along the path */ + for (j = t; j != s; j = i) + { /* arc a immediately precedes node j in the path */ + a = link[j]; + if (head[a] == j) + { /* a = i->j is a forward arc of the cycle */ + i = tail[a]; + x[a] += delta; + } + else if (tail[a] == j) + { /* a = i<-j is a backward arc of the cycle */ + i = head[a]; + x[a] -= delta; + } + else + xassert(a != a); + } + goto loop; +done: /* free working arrays */ + xfree(ptr); + xfree(arc); + xfree(link); + xfree(list); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/ffalg.h b/resources/3rdparty/glpk-4.53/src/misc/ffalg.h new file mode 100644 index 000000000..662b747f3 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/ffalg.h @@ -0,0 +1,34 @@ +/* ffalg.h (Ford-Fulkerson algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef FFALG_H +#define FFALG_H + +#define ffalg _glp_ffalg +void ffalg(int nv, int na, const int tail[], const int head[], + int s, int t, const int cap[], int x[], char cut[]); +/* Ford-Fulkerson algorithm */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/fp2rat.c b/resources/3rdparty/glpk-4.53/src/misc/fp2rat.c new file mode 100644 index 000000000..1e462b9cb --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/fp2rat.c @@ -0,0 +1,164 @@ +/* fp2rat.c (convert floating-point number to rational number) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* fp2rat - convert floating-point number to rational number +* +* SYNOPSIS +* +* #include "misc.h" +* int fp2rat(double x, double eps, double *p, double *q); +* +* DESCRIPTION +* +* Given a floating-point number 0 <= x < 1 the routine fp2rat finds +* its "best" rational approximation p / q, where p >= 0 and q > 0 are +* integer numbers, such that |x - p / q| <= eps. +* +* RETURNS +* +* The routine fp2rat returns the number of iterations used to achieve +* the specified precision eps. +* +* EXAMPLES +* +* For x = sqrt(2) - 1 = 0.414213562373095 and eps = 1e-6 the routine +* gives p = 408 and q = 985, where 408 / 985 = 0.414213197969543. +* +* BACKGROUND +* +* It is well known that every positive real number x can be expressed +* as the following continued fraction: +* +* x = b[0] + a[1] +* ------------------------ +* b[1] + a[2] +* ----------------- +* b[2] + a[3] +* ---------- +* b[3] + ... +* +* where: +* +* a[k] = 1, k = 0, 1, 2, ... +* +* b[k] = floor(x[k]), k = 0, 1, 2, ... +* +* x[0] = x, +* +* x[k] = 1 / frac(x[k-1]), k = 1, 2, 3, ... +* +* To find the "best" rational approximation of x the routine computes +* partial fractions f[k] by dropping after k terms as follows: +* +* f[k] = A[k] / B[k], +* +* where: +* +* A[-1] = 1, A[0] = b[0], B[-1] = 0, B[0] = 1, +* +* A[k] = b[k] * A[k-1] + a[k] * A[k-2], +* +* B[k] = b[k] * B[k-1] + a[k] * B[k-2]. +* +* Once the condition +* +* |x - f[k]| <= eps +* +* has been satisfied, the routine reports p = A[k] and q = B[k] as the +* final answer. +* +* In the table below here is some statistics obtained for one million +* random numbers uniformly distributed in the range [0, 1). +* +* eps max p mean p max q mean q max k mean k +* ------------------------------------------------------------- +* 1e-1 8 1.6 9 3.2 3 1.4 +* 1e-2 98 6.2 99 12.4 5 2.4 +* 1e-3 997 20.7 998 41.5 8 3.4 +* 1e-4 9959 66.6 9960 133.5 10 4.4 +* 1e-5 97403 211.7 97404 424.2 13 5.3 +* 1e-6 479669 669.9 479670 1342.9 15 6.3 +* 1e-7 1579030 2127.3 3962146 4257.8 16 7.3 +* 1e-8 26188823 6749.4 26188824 13503.4 19 8.2 +* +* REFERENCES +* +* W. B. Jones and W. J. Thron, "Continued Fractions: Analytic Theory +* and Applications," Encyclopedia on Mathematics and Its Applications, +* Addison-Wesley, 1980. */ + +int fp2rat(double x, double eps, double *p, double *q) +{ int k; + double xk, Akm1, Ak, Bkm1, Bk, ak, bk, fk, temp; + xassert(0.0 <= x && x < 1.0); + for (k = 0; ; k++) + { xassert(k <= 100); + if (k == 0) + { /* x[0] = x */ + xk = x; + /* A[-1] = 1 */ + Akm1 = 1.0; + /* A[0] = b[0] = floor(x[0]) = 0 */ + Ak = 0.0; + /* B[-1] = 0 */ + Bkm1 = 0.0; + /* B[0] = 1 */ + Bk = 1.0; + } + else + { /* x[k] = 1 / frac(x[k-1]) */ + temp = xk - floor(xk); + xassert(temp != 0.0); + xk = 1.0 / temp; + /* a[k] = 1 */ + ak = 1.0; + /* b[k] = floor(x[k]) */ + bk = floor(xk); + /* A[k] = b[k] * A[k-1] + a[k] * A[k-2] */ + temp = bk * Ak + ak * Akm1; + Akm1 = Ak, Ak = temp; + /* B[k] = b[k] * B[k-1] + a[k] * B[k-2] */ + temp = bk * Bk + ak * Bkm1; + Bkm1 = Bk, Bk = temp; + } + /* f[k] = A[k] / B[k] */ + fk = Ak / Bk; +#if 0 + print("%.*g / %.*g = %.*g", + DBL_DIG, Ak, DBL_DIG, Bk, DBL_DIG, fk); +#endif + if (fabs(x - fk) <= eps) + break; + } + *p = Ak; + *q = Bk; + return k; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/gcd.c b/resources/3rdparty/glpk-4.53/src/misc/gcd.c new file mode 100644 index 000000000..b5c596209 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/gcd.c @@ -0,0 +1,102 @@ +/* gcd.c (greatest common divisor) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* gcd - find greatest common divisor of two integers +* +* SYNOPSIS +* +* #include "misc.h" +* int gcd(int x, int y); +* +* RETURNS +* +* The routine gcd returns gcd(x, y), the greatest common divisor of +* the two positive integers given. +* +* ALGORITHM +* +* The routine gcd is based on Euclid's algorithm. +* +* REFERENCES +* +* Don Knuth, The Art of Computer Programming, Vol.2: Seminumerical +* Algorithms, 3rd Edition, Addison-Wesley, 1997. Section 4.5.2: The +* Greatest Common Divisor, pp. 333-56. */ + +int gcd(int x, int y) +{ int r; + xassert(x > 0 && y > 0); + while (y > 0) + r = x % y, x = y, y = r; + return x; +} + +/*********************************************************************** +* NAME +* +* gcdn - find greatest common divisor of n integers +* +* SYNOPSIS +* +* #include "misc.h" +* int gcdn(int n, int x[]); +* +* RETURNS +* +* The routine gcdn returns gcd(x[1], x[2], ..., x[n]), the greatest +* common divisor of n positive integers given, n > 0. +* +* BACKGROUND +* +* The routine gcdn is based on the following identity: +* +* gcd(x, y, z) = gcd(gcd(x, y), z). +* +* REFERENCES +* +* Don Knuth, The Art of Computer Programming, Vol.2: Seminumerical +* Algorithms, 3rd Edition, Addison-Wesley, 1997. Section 4.5.2: The +* Greatest Common Divisor, pp. 333-56. */ + +int gcdn(int n, int x[]) +{ int d, j; + xassert(n > 0); + for (j = 1; j <= n; j++) + { xassert(x[j] > 0); + if (j == 1) + d = x[1]; + else + d = gcd(d, x[j]); + if (d == 1) + break; + } + return d; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/jd.c b/resources/3rdparty/glpk-4.53/src/misc/jd.c new file mode 100644 index 000000000..e678a1ee9 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/jd.c @@ -0,0 +1,152 @@ +/* jd.c (conversions between calendar date and Julian day number) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include <stddef.h> +#include "jd.h" + +/*********************************************************************** +* NAME +* +* jday - convert calendar date to Julian day number +* +* SYNOPSIS +* +* #include "jd.h" +* int jday(int d, int m, int y); +* +* DESCRIPTION +* +* The routine jday converts a calendar date, Gregorian calendar, to +* corresponding Julian day number j. +* +* From the given day d, month m, and year y, the Julian day number j +* is computed without using tables. +* +* The routine is valid for 1 <= y <= 4000. +* +* RETURNS +* +* The routine jday returns the Julian day number, or negative value if +* the specified date is incorrect. +* +* REFERENCES +* +* R. G. Tantzen, Algorithm 199: conversions between calendar date and +* Julian day number, Communications of the ACM, vol. 6, no. 8, p. 444, +* Aug. 1963. */ + +int jday(int d, int m, int y) +{ int c, ya, j, dd; + if (!(1 <= d && d <= 31 && + 1 <= m && m <= 12 && + 1 <= y && y <= 4000)) + return -1; + if (m >= 3) + m -= 3; + else + m += 9, y--; + c = y / 100; + ya = y - 100 * c; + j = (146097 * c) / 4 + (1461 * ya) / 4 + (153 * m + 2) / 5 + d + + 1721119; + jdate(j, &dd, NULL, NULL); + if (d != dd) + return -1; + return j; +} + +/*********************************************************************** +* NAME +* +* jdate - convert Julian day number to calendar date +* +* SYNOPSIS +* +* #include "jd.h" +* int jdate(int j, int *d, int *m, int *y); +* +* DESCRIPTION +* +* The routine jdate converts a Julian day number j to corresponding +* calendar date, Gregorian calendar. +* +* The day d, month m, and year y are computed without using tables and +* stored in corresponding locations. +* +* The routine is valid for 1721426 <= j <= 3182395. +* +* RETURNS +* +* If the conversion is successful, the routine returns zero, otherwise +* non-zero. +* +* REFERENCES +* +* R. G. Tantzen, Algorithm 199: conversions between calendar date and +* Julian day number, Communications of the ACM, vol. 6, no. 8, p. 444, +* Aug. 1963. */ + +int jdate(int j, int *d_, int *m_, int *y_) +{ int d, m, y; + if (!(1721426 <= j && j <= 3182395)) + return 1; + j -= 1721119; + y = (4 * j - 1) / 146097; + j = (4 * j - 1) % 146097; + d = j / 4; + j = (4 * d + 3) / 1461; + d = (4 * d + 3) % 1461; + d = (d + 4) / 4; + m = (5 * d - 3) / 153; + d = (5 * d - 3) % 153; + d = (d + 5) / 5; + y = 100 * y + j; + if (m <= 9) + m += 3; + else m -= 9, + y++; + if (d_ != NULL) *d_ = d; + if (m_ != NULL) *m_ = m; + if (y_ != NULL) *y_ = y; + return 0; +} + +#ifdef GLP_TEST +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +int main(void) +{ int jbeg, jend, j, d, m, y; + jbeg = jday(1, 1, 1); + jend = jday(31, 12, 4000); + for (j = jbeg; j <= jend; j++) + { assert(jdate(j, &d, &m, &y) == 0); + assert(jday(d, m, y) == j); + } + printf("Routines jday and jdate work correctly.\n"); + return 0; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/jd.h b/resources/3rdparty/glpk-4.53/src/misc/jd.h new file mode 100644 index 000000000..daaa85894 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/jd.h @@ -0,0 +1,32 @@ +/* jd.h (conversions between calendar date and Julian day number) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#define jday _glp_jday +int jday(int d, int m, int y); +/* convert calendar date to Julian day number */ + +#define jdate _glp_jdate +int jdate(int j, int *d, int *m, int *y); +/* convert Julian day number to calendar date */ + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/keller.c b/resources/3rdparty/glpk-4.53/src/misc/keller.c new file mode 100644 index 000000000..2c4849d7d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/keller.c @@ -0,0 +1,235 @@ +/* keller.c (cover edges by cliques, Kellerman's heuristic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "glpk.h" +#include "env.h" +#include "keller.h" + +/*********************************************************************** +* NAME +* +* kellerman - cover edges by cliques with Kellerman's heuristic +* +* SYNOPSIS +* +* #include "keller.h" +* int kellerman(int n, int (*func)(void *info, int i, int ind[]), +* void *info, glp_graph *H); +* +* DESCRIPTION +* +* The routine kellerman implements Kellerman's heuristic algorithm +* to find a minimal set of cliques which cover all edges of specified +* graph G = (V, E). +* +* The parameter n specifies the number of vertices |V|, n >= 0. +* +* Formal routine func specifies the set of edges E in the following +* way. Running the routine kellerman calls the routine func and passes +* to it parameter i, which is the number of some vertex, 1 <= i <= n. +* In response the routine func should store numbers of all vertices +* adjacent to vertex i to locations ind[1], ind[2], ..., ind[len] and +* return the value of len, which is the number of adjacent vertices, +* 0 <= len <= n. Self-loops are allowed, but ignored. Multiple edges +* are not allowed. +* +* The parameter info is a transit pointer (magic cookie) passed to the +* formal routine func as its first parameter. +* +* The result provided by the routine kellerman is the bipartite graph +* H = (V union C, F), which defines the covering found. (The program +* object of type glp_graph specified by the parameter H should be +* previously created with the routine glp_create_graph. On entry the +* routine kellerman erases the content of this object with the routine +* glp_erase_graph.) Vertices of first part V correspond to vertices of +* the graph G and have the same ordinal numbers 1, 2, ..., n. Vertices +* of second part C correspond to cliques and have ordinal numbers +* n+1, n+2, ..., n+k, where k is the total number of cliques in the +* edge covering found. Every edge f in F in the program object H is +* represented as arc f = (i->j), where i in V and j in C, which means +* that vertex i of the graph G is in clique C[j], 1 <= j <= k. (Thus, +* if two vertices of the graph G are in the same clique, these vertices +* are adjacent in G, and corresponding edge is covered by that clique.) +* +* RETURNS +* +* The routine Kellerman returns k, the total number of cliques in the +* edge covering found. +* +* REFERENCE +* +* For more details see: glpk/doc/notes/keller.pdf (in Russian). */ + +struct set +{ /* set of vertices */ + int size; + /* size (cardinality) of the set, 0 <= card <= n */ + int *list; /* int list[1+n]; */ + /* the set contains vertices list[1,...,size] */ + int *pos; /* int pos[1+n]; */ + /* pos[i] > 0 means that vertex i is in the set and + * list[pos[i]] = i; pos[i] = 0 means that vertex i is not in + * the set */ +}; + +int kellerman(int n, int (*func)(void *info, int i, int ind[]), + void *info, void /* glp_graph */ *H_) +{ glp_graph *H = H_; + struct set W_, *W = &W_, V_, *V = &V_; + glp_arc *a; + int i, j, k, m, t, len, card, best; + xassert(n >= 0); + /* H := (V, 0; 0), where V is the set of vertices of graph G */ + glp_erase_graph(H, H->v_size, H->a_size); + glp_add_vertices(H, n); + /* W := 0 */ + W->size = 0; + W->list = xcalloc(1+n, sizeof(int)); + W->pos = xcalloc(1+n, sizeof(int)); + memset(&W->pos[1], 0, sizeof(int) * n); + /* V := 0 */ + V->size = 0; + V->list = xcalloc(1+n, sizeof(int)); + V->pos = xcalloc(1+n, sizeof(int)); + memset(&V->pos[1], 0, sizeof(int) * n); + /* main loop */ + for (i = 1; i <= n; i++) + { /* W must be empty */ + xassert(W->size == 0); + /* W := { j : i > j and (i,j) in E } */ + len = func(info, i, W->list); + xassert(0 <= len && len <= n); + for (t = 1; t <= len; t++) + { j = W->list[t]; + xassert(1 <= j && j <= n); + if (j >= i) continue; + xassert(W->pos[j] == 0); + W->list[++W->size] = j, W->pos[j] = W->size; + } + /* on i-th iteration we need to cover edges (i,j) for all + * j in W */ + /* if W is empty, it is a special case */ + if (W->size == 0) + { /* set k := k + 1 and create new clique C[k] = { i } */ + k = glp_add_vertices(H, 1) - n; + glp_add_arc(H, i, n + k); + continue; + } + /* try to include vertex i into existing cliques */ + /* V must be empty */ + xassert(V->size == 0); + /* k is the number of cliques found so far */ + k = H->nv - n; + for (m = 1; m <= k; m++) + { /* do while V != W; since here V is within W, we can use + * equivalent condition: do while |V| < |W| */ + if (V->size == W->size) break; + /* check if C[m] is within W */ + for (a = H->v[n + m]->in; a != NULL; a = a->h_next) + { j = a->tail->i; + if (W->pos[j] == 0) break; + } + if (a != NULL) continue; + /* C[m] is within W, expand clique C[m] with vertex i */ + /* C[m] := C[m] union {i} */ + glp_add_arc(H, i, n + m); + /* V is a set of vertices whose incident edges are already + * covered by existing cliques */ + /* V := V union C[m] */ + for (a = H->v[n + m]->in; a != NULL; a = a->h_next) + { j = a->tail->i; + if (V->pos[j] == 0) + V->list[++V->size] = j, V->pos[j] = V->size; + } + } + /* remove from set W the vertices whose incident edges are + * already covered by existing cliques */ + /* W := W \ V, V := 0 */ + for (t = 1; t <= V->size; t++) + { j = V->list[t], V->pos[j] = 0; + if (W->pos[j] != 0) + { /* remove vertex j from W */ + if (W->pos[j] != W->size) + { int jj = W->list[W->size]; + W->list[W->pos[j]] = jj; + W->pos[jj] = W->pos[j]; + } + W->size--, W->pos[j] = 0; + } + } + V->size = 0; + /* now set W contains only vertices whose incident edges are + * still not covered by existing cliques; create new cliques + * to cover remaining edges until set W becomes empty */ + while (W->size > 0) + { /* find clique C[m], 1 <= m <= k, which shares maximal + * number of vertices with W; to break ties choose clique + * having smallest number m */ + m = 0, best = -1; + k = H->nv - n; + for (t = 1; t <= k; t++) + { /* compute cardinality of intersection of W and C[t] */ + card = 0; + for (a = H->v[n + t]->in; a != NULL; a = a->h_next) + { j = a->tail->i; + if (W->pos[j] != 0) card++; + } + if (best < card) + m = t, best = card; + } + xassert(m > 0); + /* set k := k + 1 and create new clique: + * C[k] := (W intersect C[m]) union { i }, which covers all + * edges incident to vertices from (W intersect C[m]) */ + k = glp_add_vertices(H, 1) - n; + for (a = H->v[n + m]->in; a != NULL; a = a->h_next) + { j = a->tail->i; + if (W->pos[j] != 0) + { /* vertex j is in both W and C[m]; include it in new + * clique C[k] */ + glp_add_arc(H, j, n + k); + /* remove vertex j from W, since edge (i,j) will be + * covered by new clique C[k] */ + if (W->pos[j] != W->size) + { int jj = W->list[W->size]; + W->list[W->pos[j]] = jj; + W->pos[jj] = W->pos[j]; + } + W->size--, W->pos[j] = 0; + } + } + /* include vertex i to new clique C[k] to cover edges (i,j) + * incident to all vertices j just removed from W */ + glp_add_arc(H, i, n + k); + } + } + /* free working arrays */ + xfree(W->list); + xfree(W->pos); + xfree(V->list); + xfree(V->pos); + /* return the number of cliques in the edge covering found */ + return H->nv - n; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/keller.h b/resources/3rdparty/glpk-4.53/src/misc/keller.h new file mode 100644 index 000000000..77dfbf67c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/keller.h @@ -0,0 +1,34 @@ +/* keller.h (cover edges by cliques, Kellerman's heuristic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef KELLER_H +#define KELLER_H + +#define kellerman _glp_kellerman +int kellerman(int n, int (*func)(void *info, int i, int ind[]), + void *info, void /* glp_graph */ *H); +/* cover edges by cliques with Kellerman's heuristic */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/mc13d.c b/resources/3rdparty/glpk-4.53/src/misc/mc13d.c new file mode 100644 index 000000000..d8bab398d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/mc13d.c @@ -0,0 +1,314 @@ +/* mc13d.c (permutations to block triangular form) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is the result of translation of the Fortran subroutines +* MC13D and MC13E associated with the following paper: +* +* I.S.Duff, J.K.Reid, Algorithm 529: Permutations to block triangular +* form, ACM Trans. on Math. Softw. 4 (1978), 189-192. +* +* Use of ACM Algorithms is subject to the ACM Software Copyright and +* License Agreement. See <http://www.acm.org/publications/policies>. +* +* The translation was made by Andrew Makhorin <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "mc13d.h" + +/*********************************************************************** +* NAME +* +* mc13d - permutations to block triangular form +* +* SYNOPSIS +* +* #include "mc13d.h" +* int mc13d(int n, const int icn[], const int ip[], const int lenr[], +* int ior[], int ib[], int lowl[], int numb[], int prev[]); +* +* DESCRIPTION +* +* Given the column numbers of the nonzeros in each row of the sparse +* matrix, the routine mc13d finds a symmetric permutation that makes +* the matrix block lower triangular. +* +* INPUT PARAMETERS +* +* n order of the matrix. +* +* icn array containing the column indices of the non-zeros. Those +* belonging to a single row must be contiguous but the ordering +* of column indices within each row is unimportant and wasted +* space between rows is permitted. +* +* ip ip[i], i = 1,2,...,n, is the position in array icn of the +* first column index of a non-zero in row i. +* +* lenr lenr[i], i = 1,2,...,n, is the number of non-zeros in row i. +* +* OUTPUT PARAMETERS +* +* ior ior[i], i = 1,2,...,n, gives the position on the original +* ordering of the row or column which is in position i in the +* permuted form. +* +* ib ib[i], i = 1,2,...,num, is the row number in the permuted +* matrix of the beginning of block i, 1 <= num <= n. +* +* WORKING ARRAYS +* +* arp working array of length [1+n], where arp[0] is not used. +* arp[i] is one less than the number of unsearched edges leaving +* node i. At the end of the algorithm it is set to a permutation +* which puts the matrix in block lower triangular form. +* +* ib working array of length [1+n], where ib[0] is not used. +* ib[i] is the position in the ordering of the start of the ith +* block. ib[n+1-i] holds the node number of the ith node on the +* stack. +* +* lowl working array of length [1+n], where lowl[0] is not used. +* lowl[i] is the smallest stack position of any node to which a +* path from node i has been found. It is set to n+1 when node i +* is removed from the stack. +* +* numb working array of length [1+n], where numb[0] is not used. +* numb[i] is the position of node i in the stack if it is on it, +* is the permuted order of node i for those nodes whose final +* position has been found and is otherwise zero. +* +* prev working array of length [1+n], where prev[0] is not used. +* prev[i] is the node at the end of the path when node i was +* placed on the stack. +* +* RETURNS +* +* The routine mc13d returns num, the number of blocks found. */ + +int mc13d(int n, const int icn[], const int ip[], const int lenr[], + int ior[], int ib[], int lowl[], int numb[], int prev[]) +{ int *arp = ior; + int dummy, i, i1, i2, icnt, ii, isn, ist, ist1, iv, iw, j, lcnt, + nnm1, num, stp; + /* icnt is the number of nodes whose positions in final ordering + * have been found. */ + icnt = 0; + /* num is the number of blocks that have been found. */ + num = 0; + nnm1 = n + n - 1; + /* Initialization of arrays. */ + for (j = 1; j <= n; j++) + { numb[j] = 0; + arp[j] = lenr[j] - 1; + } + for (isn = 1; isn <= n; isn++) + { /* Look for a starting node. */ + if (numb[isn] != 0) continue; + iv = isn; + /* ist is the number of nodes on the stack ... it is the stack + * pointer. */ + ist = 1; + /* Put node iv at beginning of stack. */ + lowl[iv] = numb[iv] = 1; + ib[n] = iv; + /* The body of this loop puts a new node on the stack or + * backtracks. */ + for (dummy = 1; dummy <= nnm1; dummy++) + { i1 = arp[iv]; + /* Have all edges leaving node iv been searched? */ + if (i1 >= 0) + { i2 = ip[iv] + lenr[iv] - 1; + i1 = i2 - i1; + /* Look at edges leaving node iv until one enters a new + * node or all edges are exhausted. */ + for (ii = i1; ii <= i2; ii++) + { iw = icn[ii]; + /* Has node iw been on stack already? */ + if (numb[iw] == 0) goto L70; + /* Update value of lowl[iv] if necessary. */ + if (lowl[iw] < lowl[iv]) lowl[iv] = lowl[iw]; + } + /* There are no more edges leaving node iv. */ + arp[iv] = -1; + } + /* Is node iv the root of a block? */ + if (lowl[iv] < numb[iv]) goto L60; + /* Order nodes in a block. */ + num++; + ist1 = n + 1 - ist; + lcnt = icnt + 1; + /* Peel block off the top of the stack starting at the top + * and working down to the root of the block. */ + for (stp = ist1; stp <= n; stp++) + { iw = ib[stp]; + lowl[iw] = n + 1; + numb[iw] = ++icnt; + if (iw == iv) break; + } + ist = n - stp; + ib[num] = lcnt; + /* Are there any nodes left on the stack? */ + if (ist != 0) goto L60; + /* Have all the nodes been ordered? */ + if (icnt < n) break; + goto L100; +L60: /* Backtrack to previous node on path. */ + iw = iv; + iv = prev[iv]; + /* Update value of lowl[iv] if necessary. */ + if (lowl[iw] < lowl[iv]) lowl[iv] = lowl[iw]; + continue; +L70: /* Put new node on the stack. */ + arp[iv] = i2 - ii - 1; + prev[iw] = iv; + iv = iw; + lowl[iv] = numb[iv] = ++ist; + ib[n+1-ist] = iv; + } + } +L100: /* Put permutation in the required form. */ + for (i = 1; i <= n; i++) + arp[numb[i]] = i; + return num; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +#include "env.h" + +void test(int n, int ipp); + +int main(void) +{ /* test program for routine mc13d */ + test( 1, 0); + test( 2, 1); + test( 2, 2); + test( 3, 3); + test( 4, 4); + test( 5, 10); + test(10, 10); + test(10, 20); + test(20, 20); + test(20, 50); + test(50, 50); + test(50, 200); + return 0; +} + +void fa01bs(int max, int *nrand); + +void setup(int n, char a[1+50][1+50], int ip[], int icn[], int lenr[]); + +void test(int n, int ipp) +{ int ip[1+50], icn[1+1000], ior[1+50], ib[1+51], iw[1+150], + lenr[1+50]; + char a[1+50][1+50], hold[1+100]; + int i, ii, iblock, ij, index, j, jblock, jj, k9, num; + xprintf("\n\n\nMatrix is of order %d and has %d off-diagonal non-" + "zeros\n", n, ipp); + for (j = 1; j <= n; j++) + { for (i = 1; i <= n; i++) + a[i][j] = 0; + a[j][j] = 1; + } + for (k9 = 1; k9 <= ipp; k9++) + { /* these statements should be replaced by calls to your + * favorite random number generator to place two pseudo-random + * numbers between 1 and n in the variables i and j */ + for (;;) + { fa01bs(n, &i); + fa01bs(n, &j); + if (!a[i][j]) break; + } + a[i][j] = 1; + } + /* setup converts matrix a[i,j] to required sparsity-oriented + * storage format */ + setup(n, a, ip, icn, lenr); + num = mc13d(n, icn, ip, lenr, ior, ib, &iw[0], &iw[n], &iw[n+n]); + /* output reordered matrix with blocking to improve clarity */ + xprintf("\nThe reordered matrix which has %d block%s is of the fo" + "rm\n", num, num == 1 ? "" : "s"); + ib[num+1] = n + 1; + index = 100; + iblock = 1; + for (i = 1; i <= n; i++) + { for (ij = 1; ij <= index; ij++) + hold[ij] = ' '; + if (i == ib[iblock]) + { xprintf("\n"); + iblock++; + } + jblock = 1; + index = 0; + for (j = 1; j <= n; j++) + { if (j == ib[jblock]) + { hold[++index] = ' '; + jblock++; + } + ii = ior[i]; + jj = ior[j]; + hold[++index] = (char)(a[ii][jj] ? 'X' : '0'); + } + xprintf("%.*s\n", index, &hold[1]); + } + xprintf("\nThe starting point for each block is given by\n"); + for (i = 1; i <= num; i++) + { if ((i - 1) % 12 == 0) xprintf("\n"); + xprintf(" %4d", ib[i]); + } + xprintf("\n"); + return; +} + +void setup(int n, char a[1+50][1+50], int ip[], int icn[], int lenr[]) +{ int i, j, ind; + for (i = 1; i <= n; i++) + lenr[i] = 0; + ind = 1; + for (i = 1; i <= n; i++) + { ip[i] = ind; + for (j = 1; j <= n; j++) + { if (a[i][j]) + { lenr[i]++; + icn[ind++] = j; + } + } + } + return; +} + +double g = 1431655765.0; + +double fa01as(int i) +{ /* random number generator */ + g = fmod(g * 9228907.0, 4294967296.0); + if (i >= 0) + return g / 4294967296.0; + else + return 2.0 * g / 4294967296.0 - 1.0; +} + +void fa01bs(int max, int *nrand) +{ *nrand = (int)(fa01as(1) * (double)max) + 1; + return; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/mc13d.h b/resources/3rdparty/glpk-4.53/src/misc/mc13d.h new file mode 100644 index 000000000..b260fcd60 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/mc13d.h @@ -0,0 +1,34 @@ +/* mc13d.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef MC13D_H +#define MC13D_H + +#define mc13d _glp_mc13d +int mc13d(int n, const int icn[], const int ip[], const int lenr[], + int ior[], int ib[], int lowl[], int numb[], int prev[]); +/* permutations to block triangular form */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/mc21a.c b/resources/3rdparty/glpk-4.53/src/misc/mc21a.c new file mode 100644 index 000000000..700d0f4e2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/mc21a.c @@ -0,0 +1,301 @@ +/* mc21a.c (permutations for zero-free diagonal) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is the result of translation of the Fortran subroutines +* MC21A and MC21B associated with the following paper: +* +* I.S.Duff, Algorithm 575: Permutations for zero-free diagonal, ACM +* Trans. on Math. Softw. 7 (1981), 387-390. +* +* Use of ACM Algorithms is subject to the ACM Software Copyright and +* License Agreement. See <http://www.acm.org/publications/policies>. +* +* The translation was made by Andrew Makhorin <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "mc21a.h" + +/*********************************************************************** +* NAME +* +* mc21a - permutations for zero-free diagonal +* +* SYNOPSIS +* +* #include "mc21a.h" +* int mc21a(int n, const int icn[], const int ip[], const int lenr[], +* int iperm[], int pr[], int arp[], int cv[], int out[]); +* +* DESCRIPTION +* +* Given the pattern of nonzeros of a sparse matrix, the routine mc21a +* attempts to find a permutation of its rows that makes the matrix have +* no zeros on its diagonal. +* +* INPUT PARAMETERS +* +* n order of matrix. +* +* icn array containing the column indices of the non-zeros. Those +* belonging to a single row must be contiguous but the ordering +* of column indices within each row is unimportant and wasted +* space between rows is permitted. +* +* ip ip[i], i = 1,2,...,n, is the position in array icn of the +* first column index of a non-zero in row i. +* +* lenr lenr[i], i = 1,2,...,n, is the number of non-zeros in row i. +* +* OUTPUT PARAMETER +* +* iperm contains permutation to make diagonal have the smallest +* number of zeros on it. Elements (iperm[i], i), i = 1,2,...,n, +* are non-zero at the end of the algorithm unless the matrix is +* structurally singular. In this case, (iperm[i], i) will be +* zero for n - numnz entries. +* +* WORKING ARRAYS +* +* pr working array of length [1+n], where pr[0] is not used. +* pr[i] is the previous row to i in the depth first search. +* +* arp working array of length [1+n], where arp[0] is not used. +* arp[i] is one less than the number of non-zeros in row i which +* have not been scanned when looking for a cheap assignment. +* +* cv working array of length [1+n], where cv[0] is not used. +* cv[i] is the most recent row extension at which column i was +* visited. +* +* out working array of length [1+n], where out[0] is not used. +* out[i] is one less than the number of non-zeros in row i +* which have not been scanned during one pass through the main +* loop. +* +* RETURNS +* +* The routine mc21a returns numnz, the number of non-zeros on diagonal +* of permuted matrix. */ + +int mc21a(int n, const int icn[], const int ip[], const int lenr[], + int iperm[], int pr[], int arp[], int cv[], int out[]) +{ int i, ii, in1, in2, j, j1, jord, k, kk, numnz; + /* Initialization of arrays. */ + for (i = 1; i <= n; i++) + { arp[i] = lenr[i] - 1; + cv[i] = iperm[i] = 0; + } + numnz = 0; + /* Main loop. */ + /* Each pass round this loop either results in a new assignment + * or gives a row with no assignment. */ + for (jord = 1; jord <= n; jord++) + { j = jord; + pr[j] = -1; + for (k = 1; k <= jord; k++) + { /* Look for a cheap assignment. */ + in1 = arp[j]; + if (in1 >= 0) + { in2 = ip[j] + lenr[j] - 1; + in1 = in2 - in1; + for (ii = in1; ii <= in2; ii++) + { i = icn[ii]; + if (iperm[i] == 0) goto L110; + } + /* No cheap assignment in row. */ + arp[j] = -1; + } + /* Begin looking for assignment chain starting with row j.*/ + out[j] = lenr[j] - 1; + /* Inner loop. Extends chain by one or backtracks. */ + for (kk = 1; kk <= jord; kk++) + { in1 = out[j]; + if (in1 >= 0) + { in2 = ip[j] + lenr[j] - 1; + in1 = in2 - in1; + /* Forward scan. */ + for (ii = in1; ii <= in2; ii++) + { i = icn[ii]; + if (cv[i] != jord) + { /* Column i has not yet been accessed during + * this pass. */ + j1 = j; + j = iperm[i]; + cv[i] = jord; + pr[j] = j1; + out[j1] = in2 - ii - 1; + goto L100; + } + } + } + /* Backtracking step. */ + j = pr[j]; + if (j == -1) goto L130; + } +L100: ; + } +L110: /* New assignment is made. */ + iperm[i] = j; + arp[j] = in2 - ii - 1; + numnz++; + for (k = 1; k <= jord; k++) + { j = pr[j]; + if (j == -1) break; + ii = ip[j] + lenr[j] - out[j] - 2; + i = icn[ii]; + iperm[i] = j; + } +L130: ; + } + /* If matrix is structurally singular, we now complete the + * permutation iperm. */ + if (numnz < n) + { for (i = 1; i <= n; i++) + arp[i] = 0; + k = 0; + for (i = 1; i <= n; i++) + { if (iperm[i] == 0) + out[++k] = i; + else + arp[iperm[i]] = i; + } + k = 0; + for (i = 1; i <= n; i++) + { if (arp[i] == 0) + iperm[out[++k]] = i; + } + } + return numnz; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +#include "env.h" + +int sing; + +void ranmat(int m, int n, int icn[], int iptr[], int nnnp1, int *knum, + int iw[]); + +void fa01bs(int max, int *nrand); + +int main(void) +{ /* test program for the routine mc21a */ + /* these runs on random matrices cause all possible statements in + * mc21a to be executed */ + int i, iold, j, j1, j2, jj, knum, l, licn, n, nov4, num, numnz; + int ip[1+21], icn[1+1000], iperm[1+20], lenr[1+20], iw1[1+80]; + licn = 1000; + /* run on random matrices of orders 1 through 20 */ + for (n = 1; n <= 20; n++) + { nov4 = n / 4; + if (nov4 < 1) nov4 = 1; +L10: fa01bs(nov4, &l); + knum = l * n; + /* knum is requested number of non-zeros in random matrix */ + if (knum > licn) goto L10; + /* if sing is false, matrix is guaranteed structurally + * non-singular */ + sing = ((n / 2) * 2 == n); + /* call to subroutine to generate random matrix */ + ranmat(n, n, icn, ip, n+1, &knum, iw1); + /* knum is now actual number of non-zeros in random matrix */ + if (knum > licn) goto L10; + xprintf("n = %2d; nz = %4d; sing = %d\n", n, knum, sing); + /* set up array of row lengths */ + for (i = 1; i <= n; i++) + lenr[i] = ip[i+1] - ip[i]; + /* call to mc21a */ + numnz = mc21a(n, icn, ip, lenr, iperm, &iw1[0], &iw1[n], + &iw1[n+n], &iw1[n+n+n]); + /* testing to see if there are numnz non-zeros on the diagonal + * of the permuted matrix. */ + num = 0; + for (i = 1; i <= n; i++) + { iold = iperm[i]; + j1 = ip[iold]; + j2 = j1 + lenr[iold] - 1; + if (j2 < j1) continue; + for (jj = j1; jj <= j2; jj++) + { j = icn[jj]; + if (j == i) + { num++; + break; + } + } + } + if (num != numnz) + xprintf("Failure in mc21a, numnz = %d instead of %d\n", + numnz, num); + } + return 0; +} + +void ranmat(int m, int n, int icn[], int iptr[], int nnnp1, int *knum, + int iw[]) +{ /* subroutine to generate random matrix */ + int i, ii, inum, j, lrow, matnum; + inum = (*knum / n) * 2; + if (inum > n-1) inum = n-1; + matnum = 1; + /* each pass through this loop generates a row of the matrix */ + for (j = 1; j <= m; j++) + { iptr[j] = matnum; + if (!(sing || j > n)) + icn[matnum++] = j; + if (n == 1) continue; + for (i = 1; i <= n; i++) iw[i] = 0; + if (!sing) iw[j] = 1; + fa01bs(inum, &lrow); + lrow--; + if (lrow == 0) continue; + /* lrow off-diagonal non-zeros in row j of the matrix */ + for (ii = 1; ii <= lrow; ii++) + { for (;;) + { fa01bs(n, &i); + if (iw[i] != 1) break; + } + iw[i] = 1; + icn[matnum++] = i; + } + } + for (i = m+1; i <= nnnp1; i++) + iptr[i] = matnum; + *knum = matnum - 1; + return; +} + +double g = 1431655765.0; + +double fa01as(int i) +{ /* random number generator */ + g = fmod(g * 9228907.0, 4294967296.0); + if (i >= 0) + return g / 4294967296.0; + else + return 2.0 * g / 4294967296.0 - 1.0; +} + +void fa01bs(int max, int *nrand) +{ *nrand = (int)(fa01as(1) * (double)max) + 1; + return; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/mc21a.h b/resources/3rdparty/glpk-4.53/src/misc/mc21a.h new file mode 100644 index 000000000..e0de53a15 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/mc21a.h @@ -0,0 +1,34 @@ +/* mc21a.h (permutations for zero-free diagonal) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef MC21A_H +#define MC21A_H + +#define mc21a _glp_mc21a +int mc21a(int n, const int icn[], const int ip[], const int lenr[], + int iperm[], int pr[], int arp[], int cv[], int out[]); +/* permutations for zero-free diagonal */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/misc.h b/resources/3rdparty/glpk-4.53/src/misc/misc.h new file mode 100644 index 000000000..cf6c0481c --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/misc.h @@ -0,0 +1,61 @@ +/* misc.h (miscellaneous routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef MISC_H +#define MISC_H + +#define str2int _glp_str2int +int str2int(const char *str, int *val); +/* convert character string to value of int type */ + +#define str2num _glp_str2num +int str2num(const char *str, double *val); +/* convert character string to value of double type */ + +#define strspx _glp_strspx +char *strspx(char *str); +/* remove all spaces from character string */ + +#define strtrim _glp_strtrim +char *strtrim(char *str); +/* remove trailing spaces from character string */ + +#define gcd _glp_gcd +int gcd(int x, int y); +/* find greatest common divisor of two integers */ + +#define gcdn _glp_gcdn +int gcdn(int n, int x[]); +/* find greatest common divisor of n integers */ + +#define round2n _glp_round2n +double round2n(double x); +/* round floating-point number to nearest power of two */ + +#define fp2rat _glp_fp2rat +int fp2rat(double x, double eps, double *p, double *q); +/* convert floating-point number to rational number */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/okalg.c b/resources/3rdparty/glpk-4.53/src/misc/okalg.c new file mode 100644 index 000000000..5fa6ac37e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/okalg.c @@ -0,0 +1,382 @@ +/* okalg.c (out-of-kilter algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "okalg.h" + +/*********************************************************************** +* NAME +* +* okalg - out-of-kilter algorithm +* +* SYNOPSIS +* +* #include "okalg.h" +* int okalg(int nv, int na, const int tail[], const int head[], +* const int low[], const int cap[], const int cost[], int x[], +* int pi[]); +* +* DESCRIPTION +* +* The routine okalg implements the out-of-kilter algorithm to find a +* minimal-cost circulation in the specified flow network. +* +* INPUT PARAMETERS +* +* nv is the number of nodes, nv >= 0. +* +* na is the number of arcs, na >= 0. +* +* tail[a], a = 1,...,na, is the index of tail node of arc a. +* +* head[a], a = 1,...,na, is the index of head node of arc a. +* +* low[a], a = 1,...,na, is an lower bound to the flow through arc a. +* +* cap[a], a = 1,...,na, is an upper bound to the flow through arc a, +* which is the capacity of the arc. +* +* cost[a], a = 1,...,na, is a per-unit cost of the flow through arc a. +* +* NOTES +* +* 1. Multiple arcs are allowed, but self-loops are not allowed. +* +* 2. It is required that 0 <= low[a] <= cap[a] for all arcs. +* +* 3. Arc costs may have any sign. +* +* OUTPUT PARAMETERS +* +* x[a], a = 1,...,na, is optimal value of the flow through arc a. +* +* pi[i], i = 1,...,nv, is Lagrange multiplier for flow conservation +* equality constraint corresponding to node i (the node potential). +* +* RETURNS +* +* 0 optimal circulation found; +* +* 1 there is no feasible circulation; +* +* 2 integer overflow occured; +* +* 3 optimality test failed (logic error). +* +* REFERENCES +* +* L.R.Ford, Jr., and D.R.Fulkerson, "Flows in Networks," The RAND +* Corp., Report R-375-PR (August 1962), Chap. III "Minimal Cost Flow +* Problems," pp.113-26. */ + +static int overflow(int u, int v) +{ /* check for integer overflow on computing u + v */ + if (u > 0 && v > 0 && u + v < 0) return 1; + if (u < 0 && v < 0 && u + v > 0) return 1; + return 0; +} + +int okalg(int nv, int na, const int tail[], const int head[], + const int low[], const int cap[], const int cost[], int x[], + int pi[]) +{ int a, aok, delta, i, j, k, lambda, pos1, pos2, s, t, temp, ret, + *ptr, *arc, *link, *list; + /* sanity checks */ + xassert(nv >= 0); + xassert(na >= 0); + for (a = 1; a <= na; a++) + { i = tail[a], j = head[a]; + xassert(1 <= i && i <= nv); + xassert(1 <= j && j <= nv); + xassert(i != j); + xassert(0 <= low[a] && low[a] <= cap[a]); + } + /* allocate working arrays */ + ptr = xcalloc(1+nv+1, sizeof(int)); + arc = xcalloc(1+na+na, sizeof(int)); + link = xcalloc(1+nv, sizeof(int)); + list = xcalloc(1+nv, sizeof(int)); + /* ptr[i] := (degree of node i) */ + for (i = 1; i <= nv; i++) + ptr[i] = 0; + for (a = 1; a <= na; a++) + { ptr[tail[a]]++; + ptr[head[a]]++; + } + /* initialize arc pointers */ + ptr[1]++; + for (i = 1; i < nv; i++) + ptr[i+1] += ptr[i]; + ptr[nv+1] = ptr[nv]; + /* build arc lists */ + for (a = 1; a <= na; a++) + { arc[--ptr[tail[a]]] = a; + arc[--ptr[head[a]]] = a; + } + xassert(ptr[1] == 1); + xassert(ptr[nv+1] == na+na+1); + /* now the indices of arcs incident to node i are stored in + * locations arc[ptr[i]], arc[ptr[i]+1], ..., arc[ptr[i+1]-1] */ + /* initialize arc flows and node potentials */ + for (a = 1; a <= na; a++) + x[a] = 0; + for (i = 1; i <= nv; i++) + pi[i] = 0; +loop: /* main loop starts here */ + /* find out-of-kilter arc */ + aok = 0; + for (a = 1; a <= na; a++) + { i = tail[a], j = head[a]; + if (overflow(cost[a], pi[i] - pi[j])) + { ret = 2; + goto done; + } + lambda = cost[a] + (pi[i] - pi[j]); + if (x[a] < low[a] || (lambda < 0 && x[a] < cap[a])) + { /* arc a = i->j is out of kilter, and we need to increase + * the flow through this arc */ + aok = a, s = j, t = i; + break; + } + if (x[a] > cap[a] || (lambda > 0 && x[a] > low[a])) + { /* arc a = i->j is out of kilter, and we need to decrease + * the flow through this arc */ + aok = a, s = i, t = j; + break; + } + } + if (aok == 0) + { /* all arcs are in kilter */ + /* check for feasibility */ + for (a = 1; a <= na; a++) + { if (!(low[a] <= x[a] && x[a] <= cap[a])) + { ret = 3; + goto done; + } + } + for (i = 1; i <= nv; i++) + { temp = 0; + for (k = ptr[i]; k < ptr[i+1]; k++) + { a = arc[k]; + if (tail[a] == i) + { /* a is outgoing arc */ + temp += x[a]; + } + else if (head[a] == i) + { /* a is incoming arc */ + temp -= x[a]; + } + else + xassert(a != a); + } + if (temp != 0) + { ret = 3; + goto done; + } + } + /* check for optimality */ + for (a = 1; a <= na; a++) + { i = tail[a], j = head[a]; + lambda = cost[a] + (pi[i] - pi[j]); + if ((lambda > 0 && x[a] != low[a]) || + (lambda < 0 && x[a] != cap[a])) + { ret = 3; + goto done; + } + } + /* current circulation is optimal */ + ret = 0; + goto done; + } + /* now we need to find a cycle (t, a, s, ..., t), which allows + * increasing the flow along it, where a is the out-of-kilter arc + * just found */ + /* link[i] = 0 means that node i is not labelled yet; + * link[i] = a means that arc a immediately precedes node i */ + /* initially only node s is labelled */ + for (i = 1; i <= nv; i++) + link[i] = 0; + link[s] = aok, list[1] = s, pos1 = pos2 = 1; + /* breadth first search */ + while (pos1 <= pos2) + { /* dequeue node i */ + i = list[pos1++]; + /* consider all arcs incident to node i */ + for (k = ptr[i]; k < ptr[i+1]; k++) + { a = arc[k]; + if (tail[a] == i) + { /* a = i->j is a forward arc from s to t */ + j = head[a]; + /* if node j has been labelled, skip the arc */ + if (link[j] != 0) continue; + /* if the arc does not allow increasing the flow through + * it, skip the arc */ + if (x[a] >= cap[a]) continue; + if (overflow(cost[a], pi[i] - pi[j])) + { ret = 2; + goto done; + } + lambda = cost[a] + (pi[i] - pi[j]); + if (lambda > 0 && x[a] >= low[a]) continue; + } + else if (head[a] == i) + { /* a = i<-j is a backward arc from s to t */ + j = tail[a]; + /* if node j has been labelled, skip the arc */ + if (link[j] != 0) continue; + /* if the arc does not allow decreasing the flow through + * it, skip the arc */ + if (x[a] <= low[a]) continue; + if (overflow(cost[a], pi[j] - pi[i])) + { ret = 2; + goto done; + } + lambda = cost[a] + (pi[j] - pi[i]); + if (lambda < 0 && x[a] <= cap[a]) continue; + } + else + xassert(a != a); + /* label node j and enqueue it */ + link[j] = a, list[++pos2] = j; + /* check for breakthrough */ + if (j == t) goto brkt; + } + } + /* NONBREAKTHROUGH */ + /* consider all arcs, whose one endpoint is labelled and other is + * not, and determine maximal change of node potentials */ + delta = 0; + for (a = 1; a <= na; a++) + { i = tail[a], j = head[a]; + if (link[i] != 0 && link[j] == 0) + { /* a = i->j, where node i is labelled, node j is not */ + if (overflow(cost[a], pi[i] - pi[j])) + { ret = 2; + goto done; + } + lambda = cost[a] + (pi[i] - pi[j]); + if (x[a] <= cap[a] && lambda > 0) + if (delta == 0 || delta > + lambda) delta = + lambda; + } + else if (link[i] == 0 && link[j] != 0) + { /* a = j<-i, where node j is labelled, node i is not */ + if (overflow(cost[a], pi[i] - pi[j])) + { ret = 2; + goto done; + } + lambda = cost[a] + (pi[i] - pi[j]); + if (x[a] >= low[a] && lambda < 0) + if (delta == 0 || delta > - lambda) delta = - lambda; + } + } + if (delta == 0) + { /* there is no feasible circulation */ + ret = 1; + goto done; + } + /* increase potentials of all unlabelled nodes */ + for (i = 1; i <= nv; i++) + { if (link[i] == 0) + { if (overflow(pi[i], delta)) + { ret = 2; + goto done; + } + pi[i] += delta; + } + } + goto loop; +brkt: /* BREAKTHROUGH */ + /* walk through arcs of the cycle (t, a, s, ..., t) found in the + * reverse order and determine maximal change of the flow */ + delta = 0; + for (j = t;; j = i) + { /* arc a immediately precedes node j in the cycle */ + a = link[j]; + if (head[a] == j) + { /* a = i->j is a forward arc of the cycle */ + i = tail[a]; + lambda = cost[a] + (pi[i] - pi[j]); + if (lambda > 0 && x[a] < low[a]) + { /* x[a] may be increased until its lower bound */ + temp = low[a] - x[a]; + } + else if (lambda <= 0 && x[a] < cap[a]) + { /* x[a] may be increased until its upper bound */ + temp = cap[a] - x[a]; + } + else + xassert(a != a); + } + else if (tail[a] == j) + { /* a = i<-j is a backward arc of the cycle */ + i = head[a]; + lambda = cost[a] + (pi[j] - pi[i]); + if (lambda < 0 && x[a] > cap[a]) + { /* x[a] may be decreased until its upper bound */ + temp = x[a] - cap[a]; + } + else if (lambda >= 0 && x[a] > low[a]) + { /* x[a] may be decreased until its lower bound */ + temp = x[a] - low[a]; + } + else + xassert(a != a); + } + else + xassert(a != a); + if (delta == 0 || delta > temp) delta = temp; + /* check for end of the cycle */ + if (i == t) break; + } + xassert(delta > 0); + /* increase the flow along the cycle */ + for (j = t;; j = i) + { /* arc a immediately precedes node j in the cycle */ + a = link[j]; + if (head[a] == j) + { /* a = i->j is a forward arc of the cycle */ + i = tail[a]; + /* overflow cannot occur */ + x[a] += delta; + } + else if (tail[a] == j) + { /* a = i<-j is a backward arc of the cycle */ + i = head[a]; + /* overflow cannot occur */ + x[a] -= delta; + } + else + xassert(a != a); + /* check for end of the cycle */ + if (i == t) break; + } + goto loop; +done: /* free working arrays */ + xfree(ptr); + xfree(arc); + xfree(link); + xfree(list); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/okalg.h b/resources/3rdparty/glpk-4.53/src/misc/okalg.h new file mode 100644 index 000000000..71a4a0df7 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/okalg.h @@ -0,0 +1,35 @@ +/* okalg.h (out-of-kilter algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef OKALG_H +#define OKALG_H + +#define okalg _glp_okalg +int okalg(int nv, int na, const int tail[], const int head[], + const int low[], const int cap[], const int cost[], int x[], + int pi[]); +/* out-of-kilter algorithm */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/qmd.c b/resources/3rdparty/glpk-4.53/src/misc/qmd.c new file mode 100644 index 000000000..a3397dcf9 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/qmd.c @@ -0,0 +1,584 @@ +/* qmd.c (quotient minimum degree algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* THIS CODE IS THE RESULT OF TRANSLATION OF THE FORTRAN SUBROUTINES +* GENQMD, QMDRCH, QMDQT, QMDUPD, AND QMDMRG FROM THE BOOK: +* +* ALAN GEORGE, JOSEPH W-H LIU. COMPUTER SOLUTION OF LARGE SPARSE +* POSITIVE DEFINITE SYSTEMS. PRENTICE-HALL, 1981. +* +* THE TRANSLATION HAS BEEN DONE WITH THE PERMISSION OF THE AUTHORS +* OF THE ORIGINAL FORTRAN SUBROUTINES: ALAN GEORGE AND JOSEPH LIU, +* UNIVERSITY OF WATERLOO, WATERLOO, ONTARIO, CANADA. +* +* The translation was made by Andrew Makhorin <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "qmd.h" + +/*********************************************************************** +* NAME +* +* genqmd - GENeral Quotient Minimum Degree algorithm +* +* SYNOPSIS +* +* #include "qmd.h" +* void genqmd(int *neqns, int xadj[], int adjncy[], int perm[], +* int invp[], int deg[], int marker[], int rchset[], int nbrhd[], +* int qsize[], int qlink[], int *nofsub); +* +* PURPOSE +* +* This routine implements the minimum degree algorithm. It makes use +* of the implicit representation of the elimination graph by quotient +* graphs, and the notion of indistinguishable nodes. +* +* CAUTION +* +* The adjancy vector adjncy will be destroyed. +* +* INPUT PARAMETERS +* +* neqns - number of equations; +* (xadj, adjncy) - +* the adjancy structure. +* +* OUTPUT PARAMETERS +* +* perm - the minimum degree ordering; +* invp - the inverse of perm. +* +* WORKING PARAMETERS +* +* deg - the degree vector. deg[i] is negative means node i has been +* numbered; +* marker - a marker vector, where marker[i] is negative means node i +* has been merged with another nodeand thus can be ignored; +* rchset - vector used for the reachable set; +* nbrhd - vector used for neighborhood set; +* qsize - vector used to store the size of indistinguishable +* supernodes; +* qlink - vector used to store indistinguishable nodes, i, qlink[i], +* qlink[qlink[i]], ... are the members of the supernode +* represented by i. +* +* PROGRAM SUBROUTINES +* +* qmdrch, qmdqt, qmdupd. +***********************************************************************/ + +void genqmd(int *_neqns, int xadj[], int adjncy[], int perm[], + int invp[], int deg[], int marker[], int rchset[], int nbrhd[], + int qsize[], int qlink[], int *_nofsub) +{ int inode, ip, irch, j, mindeg, ndeg, nhdsze, node, np, num, + nump1, nxnode, rchsze, search, thresh; +# define neqns (*_neqns) +# define nofsub (*_nofsub) + /* Initialize degree vector and other working variables. */ + mindeg = neqns; + nofsub = 0; + for (node = 1; node <= neqns; node++) + { perm[node] = node; + invp[node] = node; + marker[node] = 0; + qsize[node] = 1; + qlink[node] = 0; + ndeg = xadj[node+1] - xadj[node]; + deg[node] = ndeg; + if (ndeg < mindeg) mindeg = ndeg; + } + num = 0; + /* Perform threshold search to get a node of min degree. + * Variable search point to where search should start. */ +s200: search = 1; + thresh = mindeg; + mindeg = neqns; +s300: nump1 = num + 1; + if (nump1 > search) search = nump1; + for (j = search; j <= neqns; j++) + { node = perm[j]; + if (marker[node] >= 0) + { ndeg = deg[node]; + if (ndeg <= thresh) goto s500; + if (ndeg < mindeg) mindeg = ndeg; + } + } + goto s200; + /* Node has minimum degree. Find its reachable sets by calling + * qmdrch. */ +s500: search = j; + nofsub += deg[node]; + marker[node] = 1; + qmdrch(&node, xadj, adjncy, deg, marker, &rchsze, rchset, &nhdsze, + nbrhd); + /* Eliminate all nodes indistinguishable from node. They are given + * by node, qlink[node], ... . */ + nxnode = node; +s600: num++; + np = invp[nxnode]; + ip = perm[num]; + perm[np] = ip; + invp[ip] = np; + perm[num] = nxnode; + invp[nxnode] = num; + deg[nxnode] = -1; + nxnode = qlink[nxnode]; + if (nxnode > 0) goto s600; + if (rchsze > 0) + { /* Update the degrees of the nodes in the reachable set and + * identify indistinguishable nodes. */ + qmdupd(xadj, adjncy, &rchsze, rchset, deg, qsize, qlink, + marker, &rchset[rchsze+1], &nbrhd[nhdsze+1]); + /* Reset marker value of nodes in reach set. Update threshold + * value for cyclic search. Also call qmdqt to form new + * quotient graph. */ + marker[node] = 0; + for (irch = 1; irch <= rchsze; irch++) + { inode = rchset[irch]; + if (marker[inode] >= 0) + { marker[inode] = 0; + ndeg = deg[inode]; + if (ndeg < mindeg) mindeg = ndeg; + if (ndeg <= thresh) + { mindeg = thresh; + thresh = ndeg; + search = invp[inode]; + } + } + } + if (nhdsze > 0) + qmdqt(&node, xadj, adjncy, marker, &rchsze, rchset, nbrhd); + } + if (num < neqns) goto s300; + return; +# undef neqns +# undef nofsub +} + +/*********************************************************************** +* NAME +* +* qmdrch - Quotient MD ReaCHable set +* +* SYNOPSIS +* +* #include "qmd.h" +* void qmdrch(int *root, int xadj[], int adjncy[], int deg[], +* int marker[], int *rchsze, int rchset[], int *nhdsze, +* int nbrhd[]); +* +* PURPOSE +* +* This subroutine determines the reachable set of a node through a +* given subset. The adjancy structure is assumed to be stored in a +* quotient graph format. +* +* INPUT PARAMETERS +* +* root - the given node not in the subset; +* (xadj, adjncy) - +* the adjancy structure pair; +* deg - the degree vector. deg[i] < 0 means the node belongs to the +* given subset. +* +* OUTPUT PARAMETERS +* +* (rchsze, rchset) - +* the reachable set; +* (nhdsze, nbrhd) - +* the neighborhood set. +* +* UPDATED PARAMETERS +* +* marker - the marker vector for reach and nbrhd sets. > 0 means the +* node is in reach set. < 0 means the node has been merged +* with others in the quotient or it is in nbrhd set. +***********************************************************************/ + +void qmdrch(int *_root, int xadj[], int adjncy[], int deg[], + int marker[], int *_rchsze, int rchset[], int *_nhdsze, + int nbrhd[]) +{ int i, istop, istrt, j, jstop, jstrt, nabor, node; +# define root (*_root) +# define rchsze (*_rchsze) +# define nhdsze (*_nhdsze) + /* Loop through the neighbors of root in the quotient graph. */ + nhdsze = 0; + rchsze = 0; + istrt = xadj[root]; + istop = xadj[root+1] - 1; + if (istop < istrt) return; + for (i = istrt; i <= istop; i++) + { nabor = adjncy[i]; + if (nabor == 0) return; + if (marker[nabor] == 0) + { if (deg[nabor] >= 0) + { /* Include nabor into the reachable set. */ + rchsze++; + rchset[rchsze] = nabor; + marker[nabor] = 1; + goto s600; + } + /* nabor has been eliminated. Find nodes reachable from + * it. */ + marker[nabor] = -1; + nhdsze++; + nbrhd[nhdsze] = nabor; +s300: jstrt = xadj[nabor]; + jstop = xadj[nabor+1] - 1; + for (j = jstrt; j <= jstop; j++) + { node = adjncy[j]; + nabor = - node; + if (node < 0) goto s300; + if (node == 0) goto s600; + if (marker[node] == 0) + { rchsze++; + rchset[rchsze] = node; + marker[node] = 1; + } + } + } +s600: ; + } + return; +# undef root +# undef rchsze +# undef nhdsze +} + +/*********************************************************************** +* NAME +* +* qmdqt - Quotient MD Quotient graph Transformation +* +* SYNOPSIS +* +* #include "qmd.h" +* void qmdqt(int *root, int xadj[], int adjncy[], int marker[], +* int *rchsze, int rchset[], int nbrhd[]); +* +* PURPOSE +* +* This subroutine performs the quotient graph transformation after a +* node has been eliminated. +* +* INPUT PARAMETERS +* +* root - the node just eliminated. It becomes the representative of +* the new supernode; +* (xadj, adjncy) - +* the adjancy structure; +* (rchsze, rchset) - +* the reachable set of root in the old quotient graph; +* nbrhd - the neighborhood set which will be merged with root to form +* the new supernode; +* marker - the marker vector. +* +* UPDATED PARAMETERS +* +* adjncy - becomes the adjncy of the quotient graph. +***********************************************************************/ + +void qmdqt(int *_root, int xadj[], int adjncy[], int marker[], + int *_rchsze, int rchset[], int nbrhd[]) +{ int inhd, irch, j, jstop, jstrt, link, nabor, node; +# define root (*_root) +# define rchsze (*_rchsze) + irch = 0; + inhd = 0; + node = root; +s100: jstrt = xadj[node]; + jstop = xadj[node+1] - 2; + if (jstop >= jstrt) + { /* Place reach nodes into the adjacent list of node. */ + for (j = jstrt; j <= jstop; j++) + { irch++; + adjncy[j] = rchset[irch]; + if (irch >= rchsze) goto s400; + } + } + /* Link to other space provided by the nbrhd set. */ + link = adjncy[jstop+1]; + node = - link; + if (link >= 0) + { inhd++; + node = nbrhd[inhd]; + adjncy[jstop+1] = - node; + } + goto s100; + /* All reachable nodes have been saved. End the adjacent list. + * Add root to the neighborhood list of each node in the reach + * set. */ +s400: adjncy[j+1] = 0; + for (irch = 1; irch <= rchsze; irch++) + { node = rchset[irch]; + if (marker[node] >= 0) + { jstrt = xadj[node]; + jstop = xadj[node+1] - 1; + for (j = jstrt; j <= jstop; j++) + { nabor = adjncy[j]; + if (marker[nabor] < 0) + { adjncy[j] = root; + goto s600; + } + } + } +s600: ; + } + return; +# undef root +# undef rchsze +} + +/*********************************************************************** +* NAME +* +* qmdupd - Quotient MD UPDate +* +* SYNOPSIS +* +* #include "qmd.h" +* void qmdupd(int xadj[], int adjncy[], int *nlist, int list[], +* int deg[], int qsize[], int qlink[], int marker[], int rchset[], +* int nbrhd[]); +* +* PURPOSE +* +* This routine performs degree update for a set of nodes in the minimum +* degree algorithm. +* +* INPUT PARAMETERS +* +* (xadj, adjncy) - +* the adjancy structure; +* (nlist, list) - +* the list of nodes whose degree has to be updated. +* +* UPDATED PARAMETERS +* +* deg - the degree vector; +* qsize - size of indistinguishable supernodes; +* qlink - linked list for indistinguishable nodes; +* marker - used to mark those nodes in reach/nbrhd sets. +* +* WORKING PARAMETERS +* +* rchset - the reachable set; +* nbrhd - the neighborhood set. +* +* PROGRAM SUBROUTINES +* +* qmdmrg. +***********************************************************************/ + +void qmdupd(int xadj[], int adjncy[], int *_nlist, int list[], + int deg[], int qsize[], int qlink[], int marker[], int rchset[], + int nbrhd[]) +{ int deg0, deg1, il, inhd, inode, irch, j, jstop, jstrt, mark, + nabor, nhdsze, node, rchsze; +# define nlist (*_nlist) + /* Find all eliminated supernodes that are adjacent to some nodes + * in the given list. Put them into (nhdsze, nbrhd). deg0 contains + * the number of nodes in the list. */ + if (nlist <= 0) return; + deg0 = 0; + nhdsze = 0; + for (il = 1; il <= nlist; il++) + { node = list[il]; + deg0 += qsize[node]; + jstrt = xadj[node]; + jstop = xadj[node+1] - 1; + for (j = jstrt; j <= jstop; j++) + { nabor = adjncy[j]; + if (marker[nabor] == 0 && deg[nabor] < 0) + { marker[nabor] = -1; + nhdsze++; + nbrhd[nhdsze] = nabor; + } + } + } + /* Merge indistinguishable nodes in the list by calling the + * subroutine qmdmrg. */ + if (nhdsze > 0) + qmdmrg(xadj, adjncy, deg, qsize, qlink, marker, °0, &nhdsze, + nbrhd, rchset, &nbrhd[nhdsze+1]); + /* Find the new degrees of the nodes that have not been merged. */ + for (il = 1; il <= nlist; il++) + { node = list[il]; + mark = marker[node]; + if (mark == 0 || mark == 1) + { marker[node] = 2; + qmdrch(&node, xadj, adjncy, deg, marker, &rchsze, rchset, + &nhdsze, nbrhd); + deg1 = deg0; + if (rchsze > 0) + { for (irch = 1; irch <= rchsze; irch++) + { inode = rchset[irch]; + deg1 += qsize[inode]; + marker[inode] = 0; + } + } + deg[node] = deg1 - 1; + if (nhdsze > 0) + { for (inhd = 1; inhd <= nhdsze; inhd++) + { inode = nbrhd[inhd]; + marker[inode] = 0; + } + } + } + } + return; +# undef nlist +} + +/*********************************************************************** +* NAME +* +* qmdmrg - Quotient MD MeRGe +* +* SYNOPSIS +* +* #include "qmd.h" +* void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[], +* int qlink[], int marker[], int *deg0, int *nhdsze, int nbrhd[], +* int rchset[], int ovrlp[]); +* +* PURPOSE +* +* This routine merges indistinguishable nodes in the minimum degree +* ordering algorithm. It also computes the new degrees of these new +* supernodes. +* +* INPUT PARAMETERS +* +* (xadj, adjncy) - +* the adjancy structure; +* deg0 - the number of nodes in the given set; +* (nhdsze, nbrhd) - +* the set of eliminated supernodes adjacent to some nodes in +* the set. +* +* UPDATED PARAMETERS +* +* deg - the degree vector; +* qsize - size of indistinguishable nodes; +* qlink - linked list for indistinguishable nodes; +* marker - the given set is given by those nodes with marker value set +* to 1. Those nodes with degree updated will have marker value +* set to 2. +* +* WORKING PARAMETERS +* +* rchset - the reachable set; +* ovrlp - temp vector to store the intersection of two reachable sets. +***********************************************************************/ + +void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[], + int qlink[], int marker[], int *_deg0, int *_nhdsze, int nbrhd[], + int rchset[], int ovrlp[]) +{ int deg1, head, inhd, iov, irch, j, jstop, jstrt, link, lnode, + mark, mrgsze, nabor, node, novrlp, rchsze, root; +# define deg0 (*_deg0) +# define nhdsze (*_nhdsze) + /* Initialization. */ + if (nhdsze <= 0) return; + for (inhd = 1; inhd <= nhdsze; inhd++) + { root = nbrhd[inhd]; + marker[root] = 0; + } + /* Loop through each eliminated supernode in the set + * (nhdsze, nbrhd). */ + for (inhd = 1; inhd <= nhdsze; inhd++) + { root = nbrhd[inhd]; + marker[root] = -1; + rchsze = 0; + novrlp = 0; + deg1 = 0; +s200: jstrt = xadj[root]; + jstop = xadj[root+1] - 1; + /* Determine the reachable set and its intersection with the + * input reachable set. */ + for (j = jstrt; j <= jstop; j++) + { nabor = adjncy[j]; + root = - nabor; + if (nabor < 0) goto s200; + if (nabor == 0) break; + mark = marker[nabor]; + if (mark == 0) + { rchsze++; + rchset[rchsze] = nabor; + deg1 += qsize[nabor]; + marker[nabor] = 1; + } + else if (mark == 1) + { novrlp++; + ovrlp[novrlp] = nabor; + marker[nabor] = 2; + } + } + /* From the overlapped set, determine the nodes that can be + * merged together. */ + head = 0; + mrgsze = 0; + for (iov = 1; iov <= novrlp; iov++) + { node = ovrlp[iov]; + jstrt = xadj[node]; + jstop = xadj[node+1] - 1; + for (j = jstrt; j <= jstop; j++) + { nabor = adjncy[j]; + if (marker[nabor] == 0) + { marker[node] = 1; + goto s1100; + } + } + /* Node belongs to the new merged supernode. Update the + * vectors qlink and qsize. */ + mrgsze += qsize[node]; + marker[node] = -1; + lnode = node; +s900: link = qlink[lnode]; + if (link > 0) + { lnode = link; + goto s900; + } + qlink[lnode] = head; + head = node; +s1100: ; + } + if (head > 0) + { qsize[head] = mrgsze; + deg[head] = deg0 + deg1 - 1; + marker[head] = 2; + } + /* Reset marker values. */ + root = nbrhd[inhd]; + marker[root] = 0; + if (rchsze > 0) + { for (irch = 1; irch <= rchsze; irch++) + { node = rchset[irch]; + marker[node] = 0; + } + } + } + return; +# undef deg0 +# undef nhdsze +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/qmd.h b/resources/3rdparty/glpk-4.53/src/misc/qmd.h new file mode 100644 index 000000000..4c5a089ab --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/qmd.h @@ -0,0 +1,58 @@ +/* qmd.h (quotient minimum degree algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2001, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef QMD_H +#define QMD_H + +#define genqmd _glp_genqmd +void genqmd(int *neqns, int xadj[], int adjncy[], int perm[], + int invp[], int deg[], int marker[], int rchset[], int nbrhd[], + int qsize[], int qlink[], int *nofsub); +/* GENeral Quotient Minimum Degree algorithm */ + +#define qmdrch _glp_qmdrch +void qmdrch(int *root, int xadj[], int adjncy[], int deg[], + int marker[], int *rchsze, int rchset[], int *nhdsze, + int nbrhd[]); +/* Quotient MD ReaCHable set */ + +#define qmdqt _glp_qmdqt +void qmdqt(int *root, int xadj[], int adjncy[], int marker[], + int *rchsze, int rchset[], int nbrhd[]); +/* Quotient MD Quotient graph Transformation */ + +#define qmdupd _glp_qmdupd +void qmdupd(int xadj[], int adjncy[], int *nlist, int list[], + int deg[], int qsize[], int qlink[], int marker[], int rchset[], + int nbrhd[]); +/* Quotient MD UPDate */ + +#define qmdmrg _glp_qmdmrg +void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[], + int qlink[], int marker[], int *deg0, int *nhdsze, int nbrhd[], + int rchset[], int ovrlp[]); +/* Quotient MD MeRGe */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/relax4.c b/resources/3rdparty/glpk-4.53/src/misc/relax4.c new file mode 100644 index 000000000..f0a47d6d5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/relax4.c @@ -0,0 +1,2850 @@ +/* relax4.c (relaxation method of Bertsekas and Tseng) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* THIS CODE IS THE RESULT OF TRANSLATION OF THE FORTRAN CODE RELAX4. +* +* THE TRANSLATION HAS BEEN DONE WITH THE PERMISSION OF THE AUTHOR OF +* THE ORIGINAL FORTRAN CODE PROF. DIMITRI P. BERTSEKAS, MASSACHUSETTS +* INSTITUTE OF TECHNOLOGY, CAMBRIDGE, MASSACHUSETTS, USA. +* +* The translation was made by Andrew Makhorin <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "relax4.h" + +/*********************************************************************** +* WARNING +* +* A serious bug was *tentatively* fixed in this code (see #if/#endif +* marked by 'mao'). +* +* This bug is inherited from the original Fortran version of the +* RELAX-IV code. Unfortunately, the code is very intricate, so this +* bug is still under investigation. Thanks to Sylvain Fournier for bug +* report. +* +* RELAX-IV bug details +* -------------------- +* In the original RELAX-IV code there are four similar fragments in +* subroutines ascnt1 and ascnt2 like this: +* +* C +* C DECREASE THE PRICES OF THE SCANNED NODES BY DELPRC. +* C ADJUST FLOW TO MAINTAIN COMPLEMENTARY SLACKNESS WITH +* C THE PRICES. +* C +* NB = 0 +* DO 6 I=1,NSAVE +* . . . +* IF (RC(ARC).EQ.0) THEN +* DELX=DELX+U(ARC) +* NB = NB + 1 +* PRDCSR(NB) = ARC +* END IF +* . . . +* +* On some instances the variable NB becomes greater than N (the number +* of nodes) that leads to indexing error, because the array PRDCSR is +* declared as array of N elements (more precisely, as array of MAXNN +* elements, however, NB becomes even much greater than MAXNN). +***********************************************************************/ + +#define false 0 +#define true 1 + +/*********************************************************************** +* NAME +* +* RELAX-IV (version of October 1994) +* +* PURPOSE +* +* This routine implements the relaxation method of Bertsekas and Tseng +* (see [1], [2]) for linear cost ordinary network flow problems. +* +* [1] Bertsekas, D. P., "A Unified Framework for Primal-Dual Methods" +* Mathematical Programming, Vol. 32, 1985, pp. 125-145. +* [2] Bertsekas, D. P., and Tseng, P., "Relaxation Methods for +* Minimum Cost" Operations Research, Vol. 26, 1988, pp. 93-114. +* +* The relaxation method is also described in the books: +* +* [3] Bertsekas, D. P., "Linear Network Optimization: Algorithms and +* Codes" MIT Press, 1991. +* [4] Bertsekas, D. P. and Tsitsiklis, J. N., "Parallel and Distributed +* Computation: Numerical Methods", Prentice-Hall, 1989. +* [5] Bertsekas, D. P., "Network Optimization: Continuous and Discrete +* Models", Athena Scientific, 1998. +* +* RELEASE NOTE +* +* This version of relaxation code has option for a special crash +* procedure for the initial price-flow pair. This is recommended for +* difficult problems where the default initialization results in long +* running times. crash = 1 corresponds to an auction/shortest path +* method +* +* These initializations are recommended in the absence of any prior +* information on a favorable initial flow-price vector pair that +* satisfies complementary slackness. +* +* The relaxation portion of the code differs from the code RELAXT-III +* and other earlier relaxation codes in that it maintains the set of +* nodes with nonzero deficit in a fifo queue. Like its predecessor +* RELAXT-III, this code maintains a linked list of balanced (i.e., of +* zero reduced cost) arcs so to reduce the work in labeling and +* scanning. Unlike RELAXT-III, it does not use selectively shortest +* path iterations for initialization. +* +* SOURCE +* +* The original Fortran code was written by Dimitri P. Bertsekas and +* Paul Tseng, with a contribution by Jonathan Eckstein in the phase II +* initialization. The original Fortran routine AUCTION was written by +* Dimitri P. Bertsekas and is based on the method described in the +* paper: +* +* [6] Bertsekas, D. P., "An Auction/Sequential Shortest Path Algorithm +* for the Minimum Cost Flow Problem", LIDS Report P-2146, MIT, +* Nov. 1992. +* +* For inquiries about the original Fortran code, please contact: +* +* Dimitri P. Bertsekas +* Laboratory for information and decision systems +* Massachusetts Institute of Technology +* Cambridge, MA 02139 +* (617) 253-7267, dimitrib@mit.edu +* +* This code is the result of translation of the original Fortran code. +* The translation was made by Andrew Makhorin <mao@gnu.org>. +* +* USER GUIDELINES +* +* This routine is in the public domain to be used only for research +* purposes. It cannot be used as part of a commercial product, or to +* satisfy in any part commercial delivery requirements to government +* or industry, without prior agreement with the authors. Users are +* requested to acknowledge the authorship of the code, and the +* relaxation method. +* +* No modification should be made to this code other than the minimal +* necessary to make it compatible with specific platforms. +* +* INPUT PARAMETERS (see notes 1, 2, 4) +* +* n = number of nodes +* na = number of arcs +* large = a very large integer to represent infinity +* (see note 3) +* repeat = true if initialization is to be skipped +* (false otherwise) +* crash = 0 if default initialization is used +* 1 if auction initialization is used +* startn[j] = starting node for arc j, j = 1,...,na +* endn[j] = ending node for arc j, j = 1,...,na +* fou[i] = first arc out of node i, i = 1,...,n +* nxtou[j] = next arc out of the starting node of arc j, j = 1,...,na +* fin[i] = first arc into node i, i = 1,...,n +* nxtin[j] = next arc into the ending node of arc j, j = 1,...,na +* +* UPDATED PARAMETERS (see notes 1, 3, 4) +* +* rc[j] = reduced cost of arc j, j = 1,...,na +* u[j] = capacity of arc j on input +* and (capacity of arc j) - x[j] on output, j = 1,...,na +* dfct[i] = demand at node i on input +* and zero on output, i = 1,...,n +* +* OUTPUT PARAMETERS (see notes 1, 3, 4) +* +* x[j] = flow on arc j, j = 1,...,na +* nmultinode = number of multinode relaxation iterations in RELAX4 +* iter = number of relaxation iterations in RELAX4 +* num_augm = number of flow augmentation steps in RELAX4 +* num_ascnt = number of multinode ascent steps in RELAX4 +* nsp = number of auction/shortest path iterations +* +* WORKING PARAMETERS (see notes 1, 4, 5) +* +* label[1+n], prdcsr[1+n], save[1+na], tfstou[1+n], tnxtou[1+na], +* tfstin[1+n], tnxtin[1+na], nxtqueue[1+n], scan[1+n], mark[1+n], +* extend_arc[1+n], sb_level[1+n], sb_arc[1+n] +* +* RETURNS +* +* 0 = normal return +* 1,...,8 = problem is found to be infeasible +* +* NOTE 1 +* +* To run in limited memory systems, declare the arrays startn, endn, +* nxtin, nxtou, fin, fou, label, prdcsr, save, tfstou, tnxtou, tfstin, +* tnxtin, ddpos, ddneg, nxtqueue as short instead. +* +* NOTE 2 +* +* This routine makes no effort to initialize with a favorable x from +* amongst those flow vectors that satisfy complementary slackness with +* the initial reduced cost vector rc. If a favorable x is known, then +* it can be passed, together with the corresponding arrays u and dfct, +* to this routine directly. This, however, requires that the capacity +* tightening portion and the flow initialization portion of this +* routine (up to line labeled 90) be skipped. +* +* NOTE 3 +* +* All problem data should be less than large in magnitude, and large +* should be less than, say, 1/4 the largest int of the machine used. +* This will guard primarily against overflow in uncapacitated problems +* where the arc capacities are taken finite but very large. Note, +* however, that as in all codes operating with integers, overflow may +* occur if some of the problem data takes very large values. +* +* NOTE 4 +* +* [This note being specific to Fortran was removed.-A.M.] +* +* NOTE 5 +* +* ddpos and ddneg are arrays that give the directional derivatives for +* all positive and negative single-node price changes. These are used +* only in phase II of the initialization procedure, before the linked +* list of balanced arcs comes to play. Therefore, to reduce storage, +* they are equivalence to tfstou and tfstin, which are of the same size +* (number of nodes) and are used only after the tree comes into use. */ + +static void ascnt1(struct relax4_csa *csa, int dm, int *delx, + int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, + int *prevnode); + +static void ascnt2(struct relax4_csa *csa, int dm, int *delx, + int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, + int *prevnode); + +static int auction(struct relax4_csa *csa); + +int relax4(struct relax4_csa *csa) +{ /* input parameters */ + int n = csa->n; + int na = csa->na; + int large = csa->large; + int repeat = csa->repeat; + int crash = csa->crash; + int *startn = csa->startn; + int *endn = csa->endn; + int *fou = csa->fou; + int *nxtou = csa->nxtou; + int *fin = csa->fin; + int *nxtin = csa->nxtin; + /* updated parameters */ + int *rc = csa->rc; + int *u = csa->u; + int *dfct = csa->dfct; + /* output parameters */ + int *x = csa->x; +# define nmultinode (csa->nmultinode) +# define iter (csa->iter) +# define num_augm (csa->num_augm) +# define num_ascnt (csa->num_ascnt) +# define nsp (csa->nsp) + /* working parameters */ + int *label = csa->label; + int *prdcsr = csa->prdcsr; + int *save = csa->save; + int *tfstou = csa->tfstou; + int *tnxtou = csa->tnxtou; + int *tfstin = csa->tfstin; + int *tnxtin = csa->tnxtin; + int *nxtqueue = csa->nxtqueue; + char *scan = csa->scan; + char *mark = csa->mark; + int *ddpos = tfstou; + int *ddneg = tfstin; + /* local variables */ + int arc, augnod, capin, capout, defcit, delprc, delx, dm, dp, + dx, feasbl, i, ib, indef, j, lastqueue, maxcap, narc, nb, + nlabel, node, node2, node_def, naugnod, nscan, num_passes, + numnz, numnz_new, numpasses, nxtarc, nxtbrk, nxtnode, passes, + pchange, posit, prevnode, prvarc, quit, rdcost, scapin, + scapou, svitch, t, t1, t2, tmparc, tp, trc, ts; + /*--------------------------------------------------------------*/ + /* Initialization phase I */ + /* In this phase, we reduce the arc capacities by as much as + * possible without changing the problem; then we set the initial + * flow array x, together with the corresponding arrays u and + * dfct. */ + /* This phase and phase II (from here up to line labeled 90) can + * be skipped (by setting repeat to true) if the calling program + * places in common user-chosen values for the arc flows, the + * residual arc capacities, and the nodal deficits. When this is + * done, it is critical that the flow and the reduced cost for + * each arc satisfy complementary slackness and the dfct array + * properly correspond to the initial arc/flows. */ + if (repeat) + goto L90; + for (node = 1; node <= n; node++) + { node_def = dfct[node]; + ddpos[node] = node_def; + ddneg[node] = -node_def; + maxcap = 0; + scapou = 0; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { if (scapou <= large - u[arc]) + scapou += u[arc]; + else + goto L10; + } + if (scapou <= large - node_def) + capout = scapou + node_def; + else + goto L10; + if (capout < 0) + { /* problem is infeasible */ + /* exogenous flow into node exceeds out capacity */ + return 1; + } + scapin = 0; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { if (u[arc] > capout) + u[arc] = capout; + if (maxcap < u[arc]) + maxcap = u[arc]; + if (scapin <= large - u[arc]) + scapin += u[arc]; + else + goto L10; + } + if (scapin <= large + node_def) + capin = scapin - node_def; + else + goto L10; + if (capin < 0) + { /* problem is infeasible */ + /* exogenous flow out of node exceeds in capacity */ + return 2; + } + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { if (u[arc] > capin) + u[arc] = capin; + } +L10: ; + } + /*--------------------------------------------------------------*/ + /* Initialization phase II */ + /* In this phase, we initialize the prices and flows by either + * calling the routine auction or by performing only single node + * (coordinate) relaxation iterations. */ + if (crash == 1) + { nsp = 0; + if (auction(csa) != 0) + { /* problem is found to be infeasible */ + return 3; + } + goto L70; + } + /* Initialize the arc flows to satisfy complementary slackness + * with the prices. u[arc] is the residual capacity of arc, and + * x[arc] is the flow. These two always add up to the total + * capacity for arc. Also compute the directional derivatives for + * each coordinate and compute the actual deficits. */ + for (arc = 1; arc <= na; arc++) + { x[arc] = 0; + if (rc[arc] <= 0) + { t = u[arc]; + t1 = startn[arc]; + t2 = endn[arc]; + ddpos[t1] += t; + ddneg[t2] += t; + if (rc[arc] < 0) + { x[arc] = t; + u[arc] = 0; + dfct[t1] += t; + dfct[t2] -= t; + ddneg[t1] -= t; + ddpos[t2] -= t; + } + } + } + /* Make 2 or 3 passes through all nodes, performing only single + * node relaxation iterations. The number of passes depends on the + * density of the network. */ + if (na > n * 10) + numpasses = 2; + else + numpasses = 3; + for (passes = 1; passes <= numpasses; passes++) + for (node = 1; node <= n; node++) + { if (dfct[node] == 0) + continue; + if (ddpos[node] <= 0) + { /* Compute delprc, the stepsize to the next breakpoint in + * the dual cost as the price of node is increased. + * [Since the reduced cost of all outgoing (resp., incoming) + * arcs will decrease (resp., increase) as the price of node + * is increased, the next breakpoint is the minimum of the + * positive reduced cost on outgoing arcs and of the + * negative reduced cost on incoming arcs.] */ + delprc = large; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { trc = rc[arc]; + if ((trc > 0) && (trc < delprc)) + delprc = trc; + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { trc = rc[arc]; + if ((trc < 0) && (trc > -delprc)) + delprc = -trc; + } + /* If no breakpoint is left and dual ascent is still + * possible, the problem is infeasible. */ + if (delprc >= large) + { if (ddpos[node] == 0) + continue; + return 4; + } + /* delprc is the stepsize to next breakpoint. Increase + * price of node by delprc and compute the stepsize to the + * next breakpoint in the dual cost. */ +L53: nxtbrk = large; + /* Look at all arcs out of node. */ + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { trc = rc[arc]; + if (trc == 0) + { t1 = endn[arc]; + t = u[arc]; + if (t > 0) + { dfct[node] += t; + dfct[t1] -= t; + x[arc] = t; + u[arc] = 0; + } + else + t = x[arc]; + ddneg[node] -= t; + ddpos[t1] -= t; + } + /* Decrease the reduced costs on all outgoing arcs. */ + trc -= delprc; + if ((trc > 0) && (trc < nxtbrk)) + nxtbrk = trc; + else if (trc == 0) + { /* Arc goes from inactive to balanced. Update the rate + * of dual ascent at node and at its neighbor. */ + ddpos[node] += u[arc]; + ddneg[endn[arc]] += u[arc]; + } + rc[arc] = trc; + } + /* Look at all arcs into node. */ + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { trc = rc[arc]; + if (trc == 0) + { t1 = startn[arc]; + t = x[arc]; + if (t > 0) + { dfct[node] += t; + dfct[t1] -= t; + u[arc] = t; + x[arc] = 0; + } + else + t = u[arc]; + ddpos[t1] -= t; + ddneg[node] -= t; + } + /* Increase the reduced cost on all incoming arcs. */ + trc += delprc; + if ((trc < 0) && (trc > -nxtbrk)) + nxtbrk = -trc; + else if (trc == 0) + { /* Arc goes from active to balanced. Update the rate + * of dual ascent at node and at its neighbor. */ + ddneg[startn[arc]] += x[arc]; + ddpos[node] += x[arc]; + } + rc[arc] = trc; + } + /* If price of node can be increased further without + * decreasing the dual cost (even the dual cost doesn't + * increase), return to increase the price further. */ + if ((ddpos[node] <= 0) && (nxtbrk < large)) + { delprc = nxtbrk; + goto L53; + } + } + else if (ddneg[node] <= 0) + { /* Compute delprc, the stepsize to the next breakpoint in + * the dual cost as the price of node is decreased. + * [Since the reduced cost of all outgoing (resp., incoming) + * arcs will increase (resp., decrease) as the price of node + * is decreased, the next breakpoint is the minimum of the + * negative reduced cost on outgoing arcs and of the + * positive reduced cost on incoming arcs.] */ + delprc = large; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { trc = rc[arc]; + if ((trc < 0) && (trc > -delprc)) + delprc = -trc; + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { trc = rc[arc]; + if ((trc > 0) && (trc < delprc)) + delprc = trc; + } + /* If no breakpoint is left and dual ascent is still + * possible, the problem is infeasible. */ + if (delprc == large) + { if (ddneg[node] == 0) + continue; + return 5; + } + /* delprc is the stepsize to next breakpoint. Decrease + * price of node by delprc and compute the stepsize to the + * next breakpoint in the dual cost. */ +L63: nxtbrk = large; + /* Look at all arcs out of node. */ + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { trc = rc[arc]; + if (trc == 0) + { t1 = endn[arc]; + t = x[arc]; + if (t > 0) + { dfct[node] -= t; + dfct[t1] += t; + u[arc] = t; + x[arc] = 0; + } + else + t = u[arc]; + ddpos[node] -= t; + ddneg[t1] -= t; + } + /* Increase the reduced cost on all outgoing arcs. */ + trc += delprc; + if ((trc < 0) && (trc > -nxtbrk)) + nxtbrk = -trc; + else if (trc == 0) + { /* Arc goes from active to balanced. Update the rate + * of dual ascent at node and at its neighbor. */ + ddneg[node] += x[arc]; + ddpos[endn[arc]] += x[arc]; + } + rc[arc] = trc; + } + /* Look at all arcs into node. */ + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { trc = rc[arc]; + if (trc == 0) + { t1 = startn[arc]; + t = u[arc]; + if (t > 0) + { dfct[node] -= t; + dfct[t1] += t; + x[arc] = t; + u[arc] = 0; + } + else + t = x[arc]; + ddneg[t1] -= t; + ddpos[node] -= t; + } + /* Decrease the reduced cost on all incoming arcs. */ + trc -= delprc; + if ((trc > 0) && (trc < nxtbrk)) + nxtbrk = trc; + else if (trc == 0) + { /* Arc goes from inactive to balanced. Update the rate + * of dual ascent at node and at its neighbor. */ + ddpos[startn[arc]] += u[arc]; + ddneg[node] += u[arc]; + } + rc[arc] = trc; + } + /* If price of node can be decreased further without + * decreasing the dual cost (even the dual cost doesn't + * increase), return to decrease the price further. */ + if ((ddneg[node] <= 0) && (nxtbrk < large)) + { delprc = nxtbrk; + goto L63; + } + } + } + /*--------------------------------------------------------------*/ +L70: /* Initialize tree data structure. */ + for (i = 1; i <= n; i++) + tfstou[i] = tfstin[i] = 0; + for (i = 1; i <= na; i++) + { tnxtin[i] = tnxtou[i] = -1; + if (rc[i] == 0) + { tnxtou[i] = tfstou[startn[i]]; + tfstou[startn[i]] = i; + tnxtin[i] = tfstin[endn[i]]; + tfstin[endn[i]] = i; + } + } +L90: /* Initialize other variables. */ + feasbl = true; + iter = 0; + nmultinode = 0; + num_augm = 0; + num_ascnt = 0; + num_passes = 0; + numnz = n; + numnz_new = 0; + svitch = false; + for (i = 1; i <= n; i++) + mark[i] = scan[i] = false; + nlabel = 0; + /* RELAX4 uses an adaptive strategy to decide whether to continue + * the scanning process after a multinode price change. + * The threshold parameter tp and ts that control this strategy + * are set in the next two lines. */ + tp = 10; + ts = n / 15; + /* Initialize the queue of nodes with nonzero deficit. */ + for (node = 1; node <= n - 1; node++) + nxtqueue[node] = node + 1; + nxtqueue[n] = 1; + node = lastqueue = n; + /*--------------------------------------------------------------*/ + /* Start the relaxation algorithm. */ +L100: /* Code for advancing the queue of nonzero deficit nodes. */ + prevnode = node; + node = nxtqueue[node]; + defcit = dfct[node]; + if (node == lastqueue) + { numnz = numnz_new; + numnz_new = 0; + lastqueue = prevnode; + num_passes++; + } + /* Code for deleting a node from the queue. */ + if (defcit == 0) + { nxtnode = nxtqueue[node]; + if (node == nxtnode) + return 0; + else + { nxtqueue[prevnode] = nxtnode; + nxtqueue[node] = 0; + node = nxtnode; + goto L100; + } + } + else + posit = (defcit > 0); + iter++; + numnz_new++; + if (posit) + { /* Attempt a single node iteration from node with positive + * deficit. */ + pchange = false; + indef = defcit; + delx = 0; + nb = 0; + /* Check outgoing (probably) balanced arcs from node. */ + for (arc = tfstou[node]; arc > 0; arc = tnxtou[arc]) + { if ((rc[arc] == 0) && (x[arc] > 0)) + { delx += x[arc]; + nb++; + save[nb] = arc; + } + } + /* Check incoming arcs. */ + for (arc = tfstin[node]; arc > 0; arc = tnxtin[arc]) + { if ((rc[arc] == 0) && (u[arc] > 0)) + { delx += u[arc]; + nb++; + save[nb] = -arc; + } + } + /* End of initial node scan. */ +L4018: /* If no price change is possible, exit. */ + if (delx > defcit) + { quit = (defcit < indef); + goto L4016; + } + /* RELAX4 searches along the ascent direction for the best + * price by checking the slope of the dual cost at successive + * break points. First, we compute the distance to the next + * break point. */ + delprc = large; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { rdcost = rc[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { rdcost = rc[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + /* Check if problem is infeasible. */ + if ((delx < defcit) && (delprc == large)) + { /* The dual cost can be decreased without bound. */ + return 6; + } + /* Skip flow adjustment if there is no flow to modify. */ + if (delx == 0) + goto L4014; + /* Adjust the flow on the balanced arcs incident to node to + * maintain complementary slackness after the price change. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc > 0) + { node2 = endn[arc]; + t1 = x[arc]; + dfct[node2] += t1; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + u[arc] += t1; + x[arc] = 0; + } + else + { narc = -arc; + node2 = startn[narc]; + t1 = u[narc]; + dfct[node2] += t1; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[narc] += t1; + u[narc] = 0; + } + } + defcit -= delx; +L4014: if (delprc == large) + { quit = true; + goto L4019; + } + /* Node corresponds to a dual ascent direction. Decrease the + * price of node by delprc and compute the stepsize to the next + * breakpoint in the dual cost. */ + nb = 0; + pchange = true; + dp = delprc; + delprc = large; + delx = 0; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { rdcost = rc[arc] + dp; + rc[arc] = rdcost; + if (rdcost == 0) + { nb++; + save[nb] = arc; + delx += x[arc]; + } + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { rdcost = rc[arc] - dp; + rc[arc] = rdcost; + if (rdcost == 0) + { nb++; + save[nb] = -arc; + delx += u[arc]; + } + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + /* Return to check if another price change is possible. */ + goto L4018; +L4016: /* Perform flow augmentation at node. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc > 0) + { /* arc is an outgoing arc from node. */ + node2 = endn[arc]; + t1 = dfct[node2]; + if (t1 < 0) + { /* Decrease the total deficit by decreasing flow of + * arc. */ + quit = true; + t2 = x[arc]; + dx = defcit; + if (dx > -t1) dx = -t1; + if (dx > t2) dx = t2; + defcit -= dx; + dfct[node2] = t1 + dx; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[arc] = t2 - dx; + u[arc] += dx; + if (defcit == 0) + break; + } + } + else + { /* -arc is an incoming arc to node. */ + narc = -arc; + node2 = startn[narc]; + t1 = dfct[node2]; + if (t1 < 0) + { /* Decrease the total deficit by increasing flow of + * -arc. */ + quit = true; + t2 = u[narc]; + dx = defcit; + if (dx > -t1) dx = -t1; + if (dx > t2) dx = t2; + defcit -= dx; + dfct[node2] = t1 + dx; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[narc] += dx; + u[narc] = t2 - dx; + if (defcit == 0) + break; + } + } + } +L4019: dfct[node] = defcit; + /* Reconstruct the linked list of balance arcs incident to this + * node. For each adjacent node, we add any newly balanced arcs + * to the list, but do not bother removing formerly balanced + * ones (they will be removed the next time each adjacent node + * is scanned). */ + if (pchange) + { arc = tfstou[node]; + tfstou[node] = 0; + while (arc > 0) + { nxtarc = tnxtou[arc]; + tnxtou[arc] = -1; + arc = nxtarc; + } + arc = tfstin[node]; + tfstin[node] = 0; + while (arc > 0) + { nxtarc = tnxtin[arc]; + tnxtin[arc] = -1; + arc = nxtarc; + } + /* Now add the currently balanced arcs to the list for this + * node (which is now empty), and the appropriate adjacent + * ones. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc < 0) + arc = -arc; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[startn[arc]]; + tfstou[startn[arc]] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[endn[arc]]; + tfstin[endn[arc]] = arc; + } + } + } + /* End of single node iteration for positive deficit node. */ + } + else + { /* Attempt a single node iteration from node with negative + * deficit. */ + pchange = false; + defcit = -defcit; + indef = defcit; + delx = 0; + nb = 0; + for (arc = tfstin[node]; arc > 0; arc = tnxtin[arc]) + { if ((rc[arc] == 0) && (x[arc] > 0)) + { delx += x[arc]; + nb++; + save[nb] = arc; + } + } + for (arc = tfstou[node]; arc > 0; arc = tnxtou[arc]) + { if ((rc[arc] == 0) && (u[arc] > 0)) + { delx += u[arc]; + nb++; + save[nb] = -arc; + } + } +L4028: if (delx >= defcit) + { quit = (defcit < indef); + goto L4026; + } + /* Compute distance to next breakpoint. */ + delprc = large; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { rdcost = rc[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { rdcost = rc[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + /* Check if problem is infeasible. */ + if ((delx < defcit) && (delprc == large)) + return 7; + if (delx == 0) + goto L4024; + /* Flow augmentation is possible. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc > 0) + { node2 = startn[arc]; + t1 = x[arc]; + dfct[node2] -= t1; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + u[arc] += t1; + x[arc] = 0; + } + else + { narc = -arc; + node2 = endn[narc]; + t1 = u[narc]; + dfct[node2] -= t1; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[narc] += t1; + u[narc] = 0; + } + } + defcit -= delx; +L4024: if (delprc == large) + { quit = true; + goto L4029; + } + /* Price increase at node is possible. */ + nb = 0; + pchange = true; + dp = delprc; + delprc = large; + delx = 0; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { rdcost = rc[arc] + dp; + rc[arc] = rdcost; + if (rdcost == 0) + { nb++; + save[nb] = arc; + delx += x[arc]; + } + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { rdcost = rc[arc] - dp; + rc[arc] = rdcost; + if (rdcost == 0) + { nb++; + save[nb] = -arc; + delx += u[arc]; + } + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + goto L4028; +L4026: /* Perform flow augmentation at node. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc > 0) + { /* arc is an incoming arc to node. */ + node2 = startn[arc]; + t1 = dfct[node2]; + if (t1 > 0) + { quit = true; + t2 = x[arc]; + dx = defcit; + if (dx > t1) dx = t1; + if (dx > t2) dx = t2; + defcit -= dx; + dfct[node2] = t1 - dx; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[arc] = t2 - dx; + u[arc] += dx; + if (defcit == 0) + break; + } + } + else + { /* -arc is an outgoing arc from node. */ + narc = -arc; + node2 = endn[narc]; + t1 = dfct[node2]; + if (t1 > 0) + { quit = true; + t2 = u[narc]; + dx = defcit; + if (dx > t1) dx = t1; + if (dx > t2) dx = t2; + defcit -= dx; + dfct[node2] = t1 - dx; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[narc] += dx; + u[narc] = t2 - dx; + if (defcit == 0) + break; + } + } + } +L4029: dfct[node] = -defcit; + /* Reconstruct the list of balanced arcs incident to node. */ + if (pchange) + { arc = tfstou[node]; + tfstou[node] = 0; + while (arc > 0) + { nxtarc = tnxtou[arc]; + tnxtou[arc] = -1; + arc = nxtarc; + } + arc = tfstin[node]; + tfstin[node] = 0; + while (arc > 0) + { nxtarc = tnxtin[arc]; + tnxtin[arc] = -1; + arc = nxtarc; + } + /* Now add the currently balanced arcs to the list for this + * node (which is now empty), and the appropriate adjacent + * ones. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc <= 0) + arc = -arc; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[startn[arc]]; + tfstou[startn[arc]] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[endn[arc]]; + tfstin[endn[arc]] = arc; + } + } + } + /* End of single node iteration for a negative deficit node. */ + } + if (quit || (num_passes <= 3)) + goto L100; + /* Do a multinode iteration from node. */ + nmultinode++; + /* If number of nonzero deficit nodes is small, continue labeling + * until a flow augmentation is done. */ + svitch = (numnz < tp); + /* Unmark nodes labeled earlier. */ + for (j = 1; j <= nlabel; j++) + { node2 = label[j]; + mark[node2] = scan[node2] = false; + } + /* Initialize labeling. */ + nlabel = 1; + label[1] = node; + mark[node] = true; + prdcsr[node] = 0; + /* Scan starting node. */ + scan[node] = true; + nscan = 1; + dm = dfct[node]; + delx = 0; + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc > 0) + { if (posit) + node2 = endn[arc]; + else + node2 = startn[arc]; + if (!mark[node2]) + { nlabel++; + label[nlabel] = node2; + prdcsr[node2] = arc; + mark[node2] = true; + delx += x[arc]; + } + } + else + { narc = -arc; + if (posit) + node2 = startn[narc]; + else + node2 = endn[narc]; + if (!mark[node2]) + { nlabel++; + label[nlabel] = node2; + prdcsr[node2] = arc; + mark[node2] = true; + delx += u[narc]; + } + } + } +L4120:/* Start scanning a labeled but unscanned node. */ + nscan++; + /* Check to see if switch needs to be set to true so to continue + * scanning even after a price change. */ + svitch = svitch || ((nscan > ts) && (numnz < ts)); + /* Scanning will continue until either an overestimate of the + * residual capacity across the cut corresponding to the scanned + * set of nodes (called delx) exceeds the absolute value of the + * total deficit of the scanned nodes (called dm), or else an + * augmenting path is found. Arcs that are in the tree but are not + * balanced are removed as part of the scanning process. */ + i = label[nscan]; + scan[i] = true; + naugnod = 0; + if (posit) + { /* Scanning node i in case of positive deficit. */ + prvarc = 0; + arc = tfstou[i]; + while (arc > 0) + { /* arc is an outgoing arc from node. */ + if (rc[arc] == 0) + { if (x[arc] > 0) + { node2 = endn[arc]; + if (!mark[node2]) + { /* node2 is not labeled, so add node2 to the + labeled set. */ + prdcsr[node2] = arc; + if (dfct[node2] < 0) + { naugnod++; + save[naugnod] = node2; + } + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + delx += x[arc]; + } + } + prvarc = arc; + arc = tnxtou[arc]; + } + else + { tmparc = arc; + arc = tnxtou[arc]; + tnxtou[tmparc] = -1; + if (prvarc == 0) + tfstou[i] = arc; + else + tnxtou[prvarc] = arc; + } + } + prvarc = 0; + arc = tfstin[i]; + while (arc > 0) + { /* arc is an incoming arc into node. */ + if (rc[arc] == 0) + { if (u[arc] > 0) + { node2 = startn[arc]; + if (!mark[node2]) + { /* node2 is not labeled, so add node2 to the + * labeled set. */ + prdcsr[node2] = -arc; + if (dfct[node2] < 0) + { naugnod++; + save[naugnod] = node2; + } + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + delx += u[arc]; + } + } + prvarc = arc; + arc = tnxtin[arc]; + } + else + { tmparc = arc; + arc = tnxtin[arc]; + tnxtin[tmparc] = -1; + if (prvarc == 0) + tfstin[i] = arc; + else + tnxtin[prvarc] = arc; + } + } + /* Correct the residual capacity of the scanned node cut. */ + arc = prdcsr[i]; + if (arc > 0) + delx -= x[arc]; + else + delx -= u[-arc]; + /* End of scanning of node i for positive deficit case. */ + } + else + { /* Scanning node i for negative deficit case. */ + prvarc = 0; + arc = tfstin[i]; + while (arc > 0) + { if (rc[arc] == 0) + { if (x[arc] > 0) + { node2 = startn[arc]; + if (!mark[node2]) + { prdcsr[node2] = arc; + if (dfct[node2] > 0) + { naugnod++; + save[naugnod] = node2; + } + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + delx += x[arc]; + } + } + prvarc = arc; + arc = tnxtin[arc]; + } + else + { tmparc = arc; + arc = tnxtin[arc]; + tnxtin[tmparc] = -1; + if (prvarc == 0) + tfstin[i] = arc; + else + tnxtin[prvarc] = arc; + } + } + prvarc = 0; + arc = tfstou[i]; + while (arc > 0) + { if (rc[arc] == 0) + { if (u[arc] > 0) + { node2 = endn[arc]; + if (!mark[node2]) + { prdcsr[node2] = -arc; + if (dfct[node2] > 0) + { naugnod++; + save[naugnod] = node2; + } + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + delx += u[arc]; + } + } + prvarc = arc; + arc = tnxtou[arc]; + } + else + { tmparc = arc; + arc = tnxtou[arc]; + tnxtou[tmparc] = -1; + if (prvarc == 0) + tfstou[i] = arc; + else + tnxtou[prvarc] = arc; + } + } + arc = prdcsr[i]; + if (arc > 0) + delx -= x[arc]; + else + delx -= u[-arc]; + } + /* Add deficit of node scanned to dm. */ + dm += dfct[i]; + /* Check if the set of scanned nodes correspond to a dual ascent + * direction; if yes, perform a price adjustment step, otherwise + * continue labeling. */ + if (nscan < nlabel) + { if (svitch) + goto L4210; + if ((delx >= dm) && (delx >= -dm)) + goto L4210; + } + /* Try a price change. + * [Note that since delx - abs(dm) is an overestimate of ascent + * slope, we may occasionally try a direction that is not an + * ascent direction. In this case the ascnt routines return with + * quit = false, so we continue labeling nodes.] */ + if (posit) + { ascnt1(csa, dm, &delx, &nlabel, &feasbl, &svitch, nscan, node, + &prevnode); + num_ascnt++; + } + else + { ascnt2(csa, dm, &delx, &nlabel, &feasbl, &svitch, nscan, node, + &prevnode); + num_ascnt++; + } + if (!feasbl) + return 8; + if (!svitch) + goto L100; + /* Store those newly labeled nodes to which flow augmentation is + * possible. */ + naugnod = 0; + for (j = nscan + 1; j <= nlabel; j++) + { node2 = label[j]; + if (posit && (dfct[node2] < 0)) + { naugnod++; + save[naugnod] = node2; + } + else if ((!posit) && (dfct[node2] > 0)) + { naugnod++; + save[naugnod] = node2; + } + } +L4210:/* Check if flow augmentation is possible. If not, return to scan + * another node. */ + if (naugnod == 0) + goto L4120; + for (j = 1; j <= naugnod; j++) + { num_augm++; + augnod = save[j]; + if (posit) + { /* Do the augmentation from node with positive deficit. */ + dx = -dfct[augnod]; + ib = augnod; + while (ib != node) + { arc = prdcsr[ib]; + if (arc > 0) + { if (dx > x[arc]) dx = x[arc]; + ib = startn[arc]; + } + else + { if (dx > u[-arc]) dx = u[-arc]; + ib = endn[-arc]; + } + } + if (dx > dfct[node]) dx = dfct[node]; + if (dx > 0) + { /* Increase (decrease) the flow of all forward (backward) + * arcs in the flow augmenting path. Adjust node deficit + * accordingly. */ + if (nxtqueue[augnod] == 0) + { nxtqueue[prevnode] = augnod; + nxtqueue[augnod] = node; + prevnode = augnod; + } + dfct[augnod] += dx; + dfct[node] -= dx; + ib = augnod; + while (ib != node) + { arc = prdcsr[ib]; + if (arc > 0) + { x[arc] -= dx; + u[arc] += dx; + ib = startn[arc]; + } + else + { narc = -arc; + x[narc] += dx; + u[narc] -= dx; + ib = endn[narc]; + } + } + } + } + else + { /* Do the augmentation from node with negative deficit. */ + dx = dfct[augnod]; + ib = augnod; + while (ib != node) + { arc = prdcsr[ib]; + if (arc > 0) + { if (dx > x[arc]) dx = x[arc]; + ib = endn[arc]; + } + else + { if (dx > u[-arc]) dx = u[-arc]; + ib = startn[-arc]; + } + } + if (dx > -dfct[node]) dx = -dfct[node]; + if (dx > 0) + { /* Update the flow and deficits. */ + if (nxtqueue[augnod] == 0) + { nxtqueue[prevnode] = augnod; + nxtqueue[augnod] = node; + prevnode = augnod; + } + dfct[augnod] -= dx; + dfct[node] += dx; + ib = augnod; + while (ib != node) + { arc = prdcsr[ib]; + if (arc > 0) + { x[arc] -= dx; + u[arc] += dx; + ib = endn[arc]; + } + else + { narc = -arc; + x[narc] += dx; + u[narc] -= dx; + ib = startn[narc]; + } + } + } + } + if (dfct[node] == 0) + goto L100; + if (dfct[augnod] != 0) + svitch = false; + } + /* If node still has nonzero deficit and all newly labeled nodes + * have same sign for their deficit as node, we can continue + * labeling. In this case, continue labeling only when flow + * augmentation is done relatively infrequently. */ + if (svitch && (iter > 8 * num_augm)) + goto L4120; + /* Return to do another relaxation iteration. */ + goto L100; +# undef nmultinode +# undef iter +# undef num_augm +# undef num_ascnt +# undef nsp +} + +/*********************************************************************** +* NAME +* +* relax4_inidat - construct linked lists for network topology +* +* PURPOSE +* +* This routine constructs two linked lists for the network topology: +* one list (given by fou, nxtou) for the outgoing arcs of nodes and +* one list (given by fin, nxtin) for the incoming arcs of nodes. These +* two lists are required by RELAX4. +* +* INPUT PARAMETERS +* +* n = number of nodes +* na = number of arcs +* startn[j] = starting node for arc j, j = 1,...,na +* endn[j] = ending node for arc j, j = 1,...,na +* +* OUTPUT PARAMETERS +* +* fou[i] = first arc out of node i, i = 1,...,n +* nxtou[j] = next arc out of the starting node of arc j, j = 1,...,na +* fin[i] = first arc into node i, i = 1,...,n +* nxtin[j] = next arc into the ending node of arc j, j = 1,...,na +* +* WORKING PARAMETERS +* +* tempin[1+n], tempou[1+n] */ + +void relax4_inidat(struct relax4_csa *csa) +{ /* input parameters */ + int n = csa->n; + int na = csa->na; + int *startn = csa->startn; + int *endn = csa->endn; + /* output parameters */ + int *fou = csa->fou; + int *nxtou = csa->nxtou; + int *fin = csa->fin; + int *nxtin = csa->nxtin; + /* working parameters */ + int *tempin = csa->label; + int *tempou = csa->prdcsr; + /* local variables */ + int i, i1, i2; + for (i = 1; i <= n; i++) + { fin[i] = fou[i] = 0; + tempin[i] = tempou[i] = 0; + } + for (i = 1; i <= na; i++) + { nxtin[i] = nxtou[i] = 0; + i1 = startn[i]; + i2 = endn[i]; + if (fou[i1] != 0) + nxtou[tempou[i1]] = i; + else + fou[i1] = i; + tempou[i1] = i; + if (fin[i2] != 0) + nxtin[tempin[i2]] = i; + else + fin[i2] = i; + tempin[i2] = i; + } + return; +} + +/*********************************************************************** +* NAME +* +* ascnt1 - multi-node price adjustment for positive deficit case +* +* PURPOSE +* +* This subroutine performs the multi-node price adjustment step for +* the case where the scanned nodes have positive deficit. It first +* checks if decreasing the price of the scanned nodes increases the +* dual cost. If yes, then it decreases the price of all scanned nodes. +* There are two possibilities for price decrease: if switch = true, +* then the set of scanned nodes corresponds to an elementary direction +* of maximal rate of ascent, in which case the price of all scanned +* nodes are decreased until the next breakpoint in the dual cost is +* encountered. At this point, some arc becomes balanced and more +* node(s) are added to the labeled set and the subroutine is exited. +* If switch = false, then the price of all scanned nodes are decreased +* until the rate of ascent becomes negative (this corresponds to the +* price adjustment step in which both the line search and the +* degenerate ascent iteration are implemented). +* +* INPUT PARAMETERS +* +* dm = total deficit of scanned nodes +* switch = true if labeling is to continue after price change +* nscan = number of scanned nodes +* curnode = most recently scanned node +* n = number of nodes +* na = number of arcs +* large = a very large integer to represent infinity (see note 3) +* startn[i] = starting node for the i-th arc, i = 1,...,na +* endn[i] = ending node for the i-th arc, i = 1,...,na +* fou[i] = first arc leaving i-th node, i = 1,...,n +* nxtou[i] = next arc leaving the starting node of j-th arc, +* i = 1,...,na +* fin[i] = first arc entering i-th node, i = 1,...,n +* nxtin[i] = next arc entering the ending node of j-th arc, +* i = 1,...,na +* +* UPDATED PARAMETERS +* +* delx = a lower estimate of the total flow on balanced arcs in +* the scanned-nodes cut +* nlabel = number of labeled nodes +* feasbl = false if problem is found to be infeasible +* prevnode = the node before curnode in queue +* rc[j] = reduced cost of arc j, j = 1,...,na +* u[j] = residual capacity of arc j, j = 1,...,na +* x[j] = flow on arc j, j = 1,...,na +* dfct[i] = deficit at node i, i = 1,...,n +* label[k] = k-th node labeled, k = 1,...,nlabel +* prdcsr[i] = predecessor of node i in tree of labeled nodes (0 if i +* is unlabeled), i = 1,...,n +* tfstou[i] = first balanced arc out of node i, i = 1,...,n +* tnxtou[j] = next balanced arc out of the starting node of arc j, +* j = 1,...,na +* tfstin[i] = first balanced arc into node i, i = 1,...,n +* tnxtin[j] = next balanced arc into the ending node of arc j, +* j = 1,...,na +* nxtqueue[i] = node following node i in the fifo queue (0 if node is +* not in the queue), i = 1,...,n +* scan[i] = true if node i is scanned, i = 1,...,n +* mark[i] = true if node i is labeled, i = 1,...,n +* +* WORKING PARAMETERS +* +* save[1+na] */ + +static void ascnt1(struct relax4_csa *csa, int dm, int *delx, + int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, + int *prevnode) +{ /* input parameters */ + int n = csa->n; + /* int na = csa->na; */ + int large = csa->large; + int *startn = csa->startn; + int *endn = csa->endn; + int *fou = csa->fou; + int *nxtou = csa->nxtou; + int *fin = csa->fin; + int *nxtin = csa->nxtin; + /* updated parameters */ +# define delx (*delx) +# define nlabel (*nlabel) +# define feasbl (*feasbl) +# define svitch (*svitch) +# define prevnode (*prevnode) + int *rc = csa->rc; + int *u = csa->u; + int *x = csa->x; + int *dfct = csa->dfct; + int *label = csa->label; + int *prdcsr = csa->prdcsr; + int *tfstou = csa->tfstou; + int *tnxtou = csa->tnxtou; + int *tfstin = csa->tfstin; + int *tnxtin = csa->tnxtin; + int *nxtqueue = csa->nxtqueue; + char *scan = csa->scan; + char *mark = csa->mark; + int *save = csa->save; + /* local variables */ + int arc, delprc, dlx, i, j, nb, node, node2, nsave, rdcost, t1, + t2, t3; + /* Store the arcs between the set of scanned nodes and its + * complement in save and compute delprc, the stepsize to the next + * breakpoint in the dual cost in the direction of decreasing + * prices of the scanned nodes. + * [The arcs are stored into save by looking at the arcs incident + * to either the set of scanned nodes or its complement, depending + * on whether nscan > n/2 or not. This improves the efficiency of + * storing.] */ + delprc = large; + dlx = 0; + nsave = 0; + if (nscan <= n / 2) + { for (i = 1; i <= nscan; i++) + { node = label[i]; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { /* arc points from scanned node to an unscanned node. */ + node2 = endn[arc]; + if (!scan[node2]) + { nsave++; + save[nsave] = arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node2] != arc)) + dlx += x[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { /* arc points from unscanned node to scanned node. */ + node2 = startn[arc]; + if (!scan[node2]) + { nsave++; + save[nsave] = -arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node2] != -arc)) + dlx += u[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + } + } + else + { for (node = 1; node <= n; node++) + { if (scan[node]) + continue; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { node2 = startn[arc]; + if (scan[node2]) + { nsave++; + save[nsave] = arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node] != arc)) + dlx += x[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + } + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { node2 = endn[arc]; + if (scan[node2]) + { nsave++; + save[nsave] = -arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node] != -arc)) + dlx += u[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + } + } + /* Check if the set of scanned nodes truly corresponds to a dual + * ascent direction. [Here delx + dlx is the exact sum of the flow + * on arcs from the scanned set to the unscanned set plus the + * (capacity - flow) on arcs from the unscanned set to the scanned + * set.] If this were not the case, set switch to true and exit + * subroutine. */ + if ((!svitch) && (delx + dlx >= dm)) + { svitch = true; + return; + } + delx += dlx; +L4: /* Check that the problem is feasible. */ + if (delprc == large) + { /* We can increase the dual cost without bound, so the primal + * problem is infeasible. */ + feasbl = false; + return; + } + /* Decrease the prices of the scanned nodes, add more nodes to + * the labeled set and check if a newly labeled node has negative + * deficit. */ + if (svitch) + { for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { rc[arc] += delprc; + if (rc[arc] == 0) + { node2 = endn[arc]; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[startn[arc]]; + tfstou[startn[arc]] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[node2]; + tfstin[node2] = arc; + } + if (!mark[node2]) + { prdcsr[node2] = arc; + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + } + } + } + else + { arc = -arc; + rc[arc] -= delprc; + if (rc[arc] == 0) + { node2 = startn[arc]; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[node2]; + tfstou[node2] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[endn[arc]]; + tfstin[endn[arc]] = arc; + } + if (!mark[node2]) + { prdcsr[node2] = -arc; + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + } + } + } + } + return; + } + else + { /* Decrease the prices of the scanned nodes by delprc. Adjust + * flow to maintain complementary slackness with the prices. */ + nb = 0; + for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { t1 = rc[arc]; + if (t1 == 0) + { t2 = x[arc]; + t3 = startn[arc]; + dfct[t3] -= t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + t3 = endn[arc]; + dfct[t3] += t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + u[arc] += t2; + x[arc] = 0; + } + rc[arc] = t1 + delprc; +#if 0 /* by mao; 26/IV-2013 */ + if (rc[arc] == 0) +#else + if (rc[arc] == 0 && nb < n) +#endif + { delx += x[arc]; + nb++; + prdcsr[nb] = arc; + } + } + else + { arc = -arc; + t1 = rc[arc]; + if (t1 == 0) + { t2 = u[arc]; + t3 = startn[arc]; + dfct[t3] += t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + t3 = endn[arc]; + dfct[t3] -= t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + x[arc] += t2; + u[arc] = 0; + } + rc[arc] = t1 - delprc; +#if 0 /* by mao; 26/IV-2013 */ + if (rc[arc] == 0) +#else + if (rc[arc] == 0 && nb < n) +#endif + { delx += u[arc]; + nb++; + prdcsr[nb] = arc; + } + } + } + } + if (delx <= dm) + { /* The set of scanned nodes still corresponds to a dual + * (possibly degenerate) ascent direction. Compute the stepsize + * delprc to the next breakpoint in the dual cost. */ + delprc = large; + for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { rdcost = rc[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + else + { arc = -arc; + rdcost = rc[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + if ((delprc != large) || (delx < dm)) + goto L4; + } + /* Add new balanced arcs to the superset of balanced arcs. */ + for (i = 1; i <= nb; i++) + { arc = prdcsr[i]; + if (tnxtin[arc] == -1) + { j = endn[arc]; + tnxtin[arc] = tfstin[j]; + tfstin[j] = arc; + } + if (tnxtou[arc] == -1) + { j = startn[arc]; + tnxtou[arc] = tfstou[j]; + tfstou[j] = arc; + } + } + return; +# undef delx +# undef nlabel +# undef feasbl +# undef svitch +# undef prevnode +} + +/*********************************************************************** +* NAME +* +* ascnt2 - multi-node price adjustment for negative deficit case +* +* PURPOSE +* +* This routine is analogous to ascnt1 but for the case where the +* scanned nodes have negative deficit. */ + +static void ascnt2(struct relax4_csa *csa, int dm, int *delx, + int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, + int *prevnode) +{ /* input parameters */ + int n = csa->n; + /* int na = csa->na; */ + int large = csa->large; + int *startn = csa->startn; + int *endn = csa->endn; + int *fou = csa->fou; + int *nxtou = csa->nxtou; + int *fin = csa->fin; + int *nxtin = csa->nxtin; + /* updated parameters */ +# define delx (*delx) +# define nlabel (*nlabel) +# define feasbl (*feasbl) +# define svitch (*svitch) +# define prevnode (*prevnode) + int *rc = csa->rc; + int *u = csa->u; + int *x = csa->x; + int *dfct = csa->dfct; + int *label = csa->label; + int *prdcsr = csa->prdcsr; + int *tfstou = csa->tfstou; + int *tnxtou = csa->tnxtou; + int *tfstin = csa->tfstin; + int *tnxtin = csa->tnxtin; + int *nxtqueue = csa->nxtqueue; + char *scan = csa->scan; + char *mark = csa->mark; + int *save = csa->save; + /* local variables */ + int arc, delprc, dlx, i, j, nb, node, node2, nsave, rdcost, t1, + t2, t3; + /* Store the arcs between the set of scanned nodes and its + * complement in save and compute delprc, the stepsize to the next + * breakpoint in the dual cost in the direction of increasing + * prices of the scanned nodes. */ + delprc = large; + dlx = 0; + nsave = 0; + if (nscan <= n / 2) + { for (i = 1; i <= nscan; i++) + { node = label[i]; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { node2 = startn[arc]; + if (!scan[node2]) + { nsave++; + save[nsave] = arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node2] != arc)) + dlx += x[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + } + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { node2 = endn[arc]; + if (!scan[node2]) + { nsave++; + save[nsave] = -arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node2] != -arc)) + dlx += u[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + } + } + else + { for (node = 1; node <= n; node++) + { if (scan[node]) + continue; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { node2 = endn[arc]; + if (scan[node2]) + { nsave++; + save[nsave] = arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node] != arc)) + dlx += x[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { node2 = startn[arc]; + if (scan[node2]) + { nsave++; + save[nsave] = -arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node] != -arc)) + dlx += u[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + } + } + if ((!svitch) && (delx + dlx >= -dm)) + { svitch = true; + return; + } + delx += dlx; + /* Check that the problem is feasible. */ +L4: if (delprc == large) + { feasbl = false; + return; + } + /* Increase the prices of the scanned nodes, add more nodes to + * the labeled set and check if a newly labeled node has positive + * deficit. */ + if (svitch) + { for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { rc[arc] += delprc; + if (rc[arc] == 0) + { node2 = startn[arc]; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[node2]; + tfstou[node2] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[endn[arc]]; + tfstin[endn[arc]] = arc; + } + if (!mark[node2]) + { prdcsr[node2] = arc; + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + } + } + } + else + { arc = -arc; + rc[arc] -= delprc; + if (rc[arc] == 0) + { node2 = endn[arc]; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[startn[arc]]; + tfstou[startn[arc]] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[node2]; + tfstin[node2] = arc; + } + if (!mark[node2]) + { prdcsr[node2] = -arc; + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + } + } + } + } + return; + } + else + { nb = 0; + for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { t1 = rc[arc]; + if (t1 == 0) + { t2 = x[arc]; + t3 = startn[arc]; + dfct[t3] -= t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + t3 = endn[arc]; + dfct[t3] += t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + u[arc] += t2; + x[arc] = 0; + } + rc[arc] = t1 + delprc; +#if 0 /* by mao; 26/IV-2013 */ + if (rc[arc] == 0) +#else + if (rc[arc] == 0 && nb < n) +#endif + { delx += x[arc]; + nb++; + prdcsr[nb] = arc; + } + } + else + { arc = -arc; + t1 = rc[arc]; + if (t1 == 0) + { t2 = u[arc]; + t3 = startn[arc]; + dfct[t3] += t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + t3 = endn[arc]; + dfct[t3] -= t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + x[arc] += t2; + u[arc] = 0; + } + rc[arc] = t1 - delprc; +#if 0 /* by mao; 26/IV-2013 */ + if (rc[arc] == 0) +#else + if (rc[arc] == 0 && nb < n) +#endif + { delx += u[arc]; + nb++; + prdcsr[nb] = arc; + } + } + } + } + if (delx <= -dm) + { delprc = large; + for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { rdcost = rc[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + else + { arc = -arc; + rdcost = rc[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + if ((delprc != large) || (delx < -dm)) + goto L4; + } + /* Add new balanced arcs to the superset of balanced arcs. */ + for (i = 1; i <= nb; i++) + { arc = prdcsr[i]; + if (tnxtin[arc] == -1) + { j = endn[arc]; + tnxtin[arc] = tfstin[j]; + tfstin[j] = arc; + } + if (tnxtou[arc] == -1) + { j = startn[arc]; + tnxtou[arc] = tfstou[j]; + tfstou[j] = arc; + } + } + return; +# undef delx +# undef nlabel +# undef feasbl +# undef svitch +# undef prevnode +} + +/*********************************************************************** +* NAME +* +* auction - compute good initial flow and prices +* +* PURPOSE +* +* This subroutine uses a version of the auction algorithm for min +* cost network flow to compute a good initial flow and prices for the +* problem. +* +* INPUT PARAMETERS +* +* n = number of nodes +* na = number of arcs +* large = a very large integer to represent infinity (see note 3) +* startn[i] = starting node for the i-th arc, i = 1,...,na +* endn[i] = ending node for the i-th arc, i = 1,...,na +* fou[i] = first arc leaving i-th node, i = 1,...,n +* nxtou[i] = next arc leaving the starting node of j-th arc, +* i = 1,...,na +* fin[i] = first arc entering i-th node, i = 1,...,n +* nxtin[i] = next arc entering the ending node of j-th arc, +* i = 1,...,na +* +* UPDATED PARAMETERS +* +* rc[j] = reduced cost of arc j, j = 1,...,na +* u[j] = residual capacity of arc j, j = 1,...,na +* x[j] = flow on arc j, j = 1,...,na +* dfct[i] = deficit at node i, i = 1,...,n +* +* OUTPUT PARAMETERS +* +* nsp = number of auction/shortest path iterations +* +* WORKING PARAMETERS +* +* p[1+n], prdcsr[1+n], save[1+na], fpushf[1+n], nxtpushf[1+na], +* fpushb[1+n], nxtpushb[1+na], nxtqueue[1+n], extend_arc[1+n], +* sb_level[1+n], sb_arc[1+n], path_id[1+n] +* +* RETURNS +* +* 0 = normal return +* 1 = problem is found to be infeasible */ + +static int auction(struct relax4_csa *csa) +{ /* input parameters */ + int n = csa->n; + int na = csa->na; + int large = csa->large; + int *startn = csa->startn; + int *endn = csa->endn; + int *fou = csa->fou; + int *nxtou = csa->nxtou; + int *fin = csa->fin; + int *nxtin = csa->nxtin; + /* updated parameters */ +# define crash (csa->crash) + int *rc = csa->rc; + int *u = csa->u; + int *x = csa->x; + int *dfct = csa->dfct; + /* output parameters */ +# define nsp (csa->nsp) + /* working parameters */ + int *p = csa->label; + int *prdcsr = csa->prdcsr; + int *save = csa->save; + int *fpushf = csa->tfstou; + int *nxtpushf = csa->tnxtou; + int *fpushb = csa->tfstin; + int *nxtpushb = csa->tnxtin; + int *nxtqueue = csa->nxtqueue; + int *extend_arc = csa->extend_arc; + int *sb_level = csa->sb_level; + int *sb_arc = csa->sb_arc; + char *path_id = csa->mark; + /* local variables */ + int arc, bstlevel, end, eps, extarc, factor, flow, i, incr, + last, lastqueue, maxcost, mincost, nas, naug, new_level, node, + nolist, num_passes, nxtnode, pass, pend, pr_term, prd, + prevarc, prevlevel, prevnode, pstart, pterm, rdcost, red_cost, + resid, root, secarc, seclevel, start, term, thresh_dfct; + /* start initialization using auction */ + naug = 0; + pass = 0; + thresh_dfct = 0; + /* factor determines by how much epsilon is reduced at each + * minimization */ + factor = 3; + /* num_passes determines how many auction scaling phases are + * performed */ + num_passes = 1; + /* set arc flows to satisfy cs and calculate maxcost and + * mincost */ + maxcost = -large; + mincost = large; + for (arc = 1; arc <= na; arc++) + { start = startn[arc]; + end = endn[arc]; + rdcost = rc[arc]; + if (maxcost < rdcost) + maxcost = rdcost; + if (mincost > rdcost) + mincost = rdcost; + if (rdcost < 0) + { dfct[start] += u[arc]; + dfct[end] -= u[arc]; + x[arc] = u[arc]; + u[arc] = 0; + } + else + x[arc] = 0; + } + /* set initial epsilon */ + if ((maxcost - mincost) >= 8) + eps = (maxcost - mincost) / 8; + else + eps = 1; + /* set initial prices to zero */ + for (node = 1; node <= n; node++) + p[node] = 0; + /* Initialization using auction/shortest paths. */ +L100: /* Start of the first scaling phase. */ + pass++; + if ((pass == num_passes) || (eps == 1)) + crash = 0; + nolist = 0; + /* construct list of positive surplus nodes and queue of negative + * surplus nodes */ + for (node = 1; node <= n; node++) + { prdcsr[node] = 0; + path_id[node] = false; + extend_arc[node] = 0; + sb_level[node] = -large; + nxtqueue[node] = node + 1; + if (dfct[node] > 0) + { nolist++; + save[nolist] = node; + } + } + nxtqueue[n] = 1; + root = 1; + prevnode = lastqueue = n; + /* initialization with down iterations for negative surplus + * nodes */ + for (i = 1; i <= nolist; i++) + { node = save[i]; + nsp++; + /* build the list of arcs w/ room for pushing flow and find + * proper price for down iteration */ + bstlevel = -large; + fpushf[node] = 0; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { if (u[arc] > 0) + { if (fpushf[node] == 0) + { fpushf[node] = arc; + nxtpushf[arc] = 0; + last = arc; + } + else + { nxtpushf[last] = arc; + nxtpushf[arc] = 0; + last = arc; + } + } + if (x[arc] > 0) + { new_level = p[endn[arc]] + rc[arc]; + if (new_level > bstlevel) + { bstlevel = new_level; + extarc = arc; + } + } + } + fpushb[node] = 0; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { if (x[arc] > 0) + { if (fpushb[node] == 0) + { fpushb[node] = arc; + nxtpushb[arc] = 0; + last = arc; + } + else + { nxtpushb[last] = arc; + nxtpushb[arc] = 0; + last = arc; + } + } + if (u[arc] > 0) + { new_level = p[startn[arc]] - rc[arc]; + if (new_level > bstlevel) + { bstlevel = new_level; + extarc = -arc; + } + } + } + extend_arc[node] = extarc; + p[node] = bstlevel - eps; + } +L200: /* Start the augmentation cycles of the new scaling phase. */ + if (dfct[root] >= thresh_dfct) + goto L3000; + term = root; + path_id[root] = true; +L500: /* Main forward algorithm with root as origin. */ + /* start of a new forward iteration */ + pterm = p[term]; + extarc = extend_arc[term]; + if (extarc == 0) + { /* build the list of arcs w/ room for pushing flow */ + fpushf[term] = 0; + for (arc = fou[term]; arc > 0; arc = nxtou[arc]) + { if (u[arc] > 0) + { if (fpushf[term] == 0) + { fpushf[term] = arc; + nxtpushf[arc] = 0; + last = arc; + } + else + { nxtpushf[last] = arc; + nxtpushf[arc] = 0; + last = arc; + } + } + } + fpushb[term] = 0; + for (arc = fin[term]; arc > 0; arc = nxtin[arc]) + { if (x[arc] > 0) + { if (fpushb[term] == 0) + { fpushb[term] = arc; + nxtpushb[arc] = 0; + last = arc; + } + else + { nxtpushb[last] = arc; + nxtpushb[arc] = 0; + last = arc; + } + } + } + goto L600; + } + /* speculative path extension attempt */ + /* note: arc > 0 means that arc is oriented from the root to the + * destinations + * arc < 0 means that arc is oriented from the destinations to the + * root + * extarc = 0 or prdarc = 0, means the extension arc or the + * predecessor arc, respectively, has not been established */ + if (extarc > 0) + { if (u[extarc] == 0) + { seclevel = sb_level[term]; + goto L580; + } + end = endn[extarc]; + bstlevel = p[end] + rc[extarc]; + if (pterm >= bstlevel) + { if (path_id[end]) + goto L1200; + term = end; + prdcsr[term] = extarc; + path_id[term] = true; + /* if negative surplus node is found, do an augmentation */ + if (dfct[term] > 0) + goto L2000; + /* return for another iteration */ + goto L500; + } + } + else + { extarc = -extarc; + if (x[extarc] == 0) + { seclevel = sb_level[term]; + goto L580; + } + start = startn[extarc]; + bstlevel = p[start] - rc[extarc]; + if (pterm >= bstlevel) + { if (path_id[start]) + goto L1200; + term = start; + prdcsr[term] = -extarc; + path_id[term] = true; + /* if negative surplus node is found, do an augmentation */ + if (dfct[term] > 0) + goto L2000; + /* return for another iteration */ + goto L500; + } + } +L550: /* second best logic test applied to save a full node scan + * if old best level continues to be best go for another + * contraction */ + seclevel = sb_level[term]; + if (bstlevel <= seclevel) + goto L800; +L580: /* if second best can be used do either a contraction or start + * over with a speculative extension */ + if (seclevel > -large) + { extarc = sb_arc[term]; + if (extarc > 0) + { if (u[extarc] == 0) + goto L600; + bstlevel = p[endn[extarc]] + rc[extarc]; + } + else + { if (x[-extarc] == 0) + goto L600; + bstlevel = p[startn[-extarc]] - rc[-extarc]; + } + if (bstlevel == seclevel) + { sb_level[term] = -large; + extend_arc[term] = extarc; + goto L800; + } + } +L600: /* extension/contraction attempt was unsuccessful, so scan + * terminal node */ + nsp++; + bstlevel = seclevel = large; + for (arc = fpushf[term]; arc > 0; arc = nxtpushf[arc]) + { new_level = p[endn[arc]] + rc[arc]; + if (new_level < seclevel) + { if (new_level < bstlevel) + { seclevel = bstlevel; + bstlevel = new_level; + secarc = extarc; + extarc = arc; + } + else + { seclevel = new_level; + secarc = arc; + } + } + } + for (arc = fpushb[term]; arc > 0; arc = nxtpushb[arc]) + { new_level = p[startn[arc]] - rc[arc]; + if (new_level < seclevel) + { if (new_level < bstlevel) + { seclevel = bstlevel; + bstlevel = new_level; + secarc = extarc; + extarc = -arc; + } + else + { seclevel = new_level; + secarc = -arc; + } + } + } + sb_level[term] = seclevel; + sb_arc[term] = secarc; + extend_arc[term] = extarc; +L800: /* End of node scan. */ + /* if the terminal node is the root, adjust its price and change + * root */ + if (term == root) + { p[term] = bstlevel + eps; + if (p[term] >= large) + { /* no path to the destination */ + /* problem is found to be infeasible */ + return 1; + } + path_id[root] = false; + prevnode = root; + root = nxtqueue[root]; + goto L200; + } + /* check whether extension or contraction */ + prd = prdcsr[term]; + if (prd > 0) + { pr_term = startn[prd]; + prevlevel = p[pr_term] - rc[prd]; + } + else + { pr_term = endn[-prd]; + prevlevel = p[pr_term] + rc[-prd]; + } + if (prevlevel > bstlevel) + { /* path extension */ + if (prevlevel >= bstlevel + eps) + p[term] = bstlevel + eps; + else + p[term] = prevlevel; + if (extarc > 0) + { end = endn[extarc]; + if (path_id[end]) + goto L1200; + term = end; + } + else + { start = startn[-extarc]; + if (path_id[start]) + goto L1200; + term = start; + } + prdcsr[term] = extarc; + path_id[term] = true; + /* if negative surplus node is found, do an augmentation */ + if (dfct[term] > 0) + goto L2000; + /* return for another iteration */ + goto L500; + } + else + { /* path contraction */ + p[term] = bstlevel + eps; + path_id[term] = false; + term = pr_term; + if (pr_term != root) + { if (bstlevel <= pterm + eps) + goto L2000; + } + pterm = p[term]; + extarc = prd; + if (prd > 0) + bstlevel += eps + rc[prd]; + else + bstlevel += eps - rc[-prd]; + /* do a second best test and if that fails, do a full node + * scan */ + goto L550; + } +L1200:/* A cycle is about to form; do a retreat sequence. */ + node = term; +L1600:if (node != root) + { path_id[node] = false; + prd = prdcsr[node]; + if (prd > 0) + { pr_term = startn[prd]; + if (p[pr_term] == p[node] + rc[prd] + eps) + { node = pr_term; + goto L1600; + } + } + else + { pr_term = endn[-prd]; + if (p[pr_term] == p[node] - rc[-prd] + eps) + { node = pr_term; + goto L1600; + } + } + /* do a full scan and price rise at pr_term */ + nsp++; + bstlevel = seclevel = large; + for (arc = fpushf[pr_term]; arc > 0; arc = nxtpushf[arc]) + { new_level = p[endn[arc]] + rc[arc]; + if (new_level < seclevel) + { if (new_level < bstlevel) + { seclevel = bstlevel; + bstlevel = new_level; + secarc = extarc; + extarc = arc; + } + else + { seclevel = new_level; + secarc = arc; + } + } + } + for (arc = fpushb[pr_term]; arc > 0; arc = nxtpushb[arc]) + { new_level = p[startn[arc]] - rc[arc]; + if (new_level < seclevel) + { if (new_level < bstlevel) + { seclevel = bstlevel; + bstlevel = new_level; + secarc = extarc; + extarc = -arc; + } + else + { seclevel = new_level; + secarc = -arc; + } + } + } + sb_level[pr_term] = seclevel; + sb_arc[pr_term] = secarc; + extend_arc[pr_term] = extarc; + p[pr_term] = bstlevel + eps; + if (pr_term == root) + { prevnode = root; + path_id[root] = false; + root = nxtqueue[root]; + goto L200; + } + path_id[pr_term] = false; + prd = prdcsr[pr_term]; + if (prd > 0) + term = startn[prd]; + else + term = endn[-prd]; + if (term == root) + { prevnode = root; + path_id[root] = false; + root = nxtqueue[root]; + goto L200; + } + else + goto L2000; + } +L2000:/* End of auction/shortest path routine. */ + /* do augmentation from root and correct the push lists */ + incr = -dfct[root]; + for (node = root;;) + { extarc = extend_arc[node]; + path_id[node] = false; + if (extarc > 0) + { node = endn[extarc]; + if (incr > u[extarc]) + incr = u[extarc]; + } + else + { node = startn[-extarc]; + if (incr > x[-extarc]) + incr = x[-extarc]; + } + if (node == term) + break; + } + path_id[term] = false; + if (dfct[term] > 0) + { if (incr > dfct[term]) + incr = dfct[term]; + } + for (node = root;;) + { extarc = extend_arc[node]; + if (extarc > 0) + { end = endn[extarc]; + /* add arc to the reduced graph */ + if (x[extarc] == 0) + { nxtpushb[extarc] = fpushb[end]; + fpushb[end] = extarc; + new_level = p[node] - rc[extarc]; + if (sb_level[end] > new_level) + { sb_level[end] = new_level; + sb_arc[end] = -extarc; + } + } + x[extarc] += incr; + u[extarc] -= incr; + /* remove arc from the reduced graph */ + if (u[extarc] == 0) + { nas++; + arc = fpushf[node]; + if (arc == extarc) + fpushf[node] = nxtpushf[arc]; + else + { prevarc = arc; + arc = nxtpushf[arc]; + while (arc > 0) + { if (arc == extarc) + { nxtpushf[prevarc] = nxtpushf[arc]; + break; + } + prevarc = arc; + arc = nxtpushf[arc]; + } + } + } + node = end; + } + else + { extarc = -extarc; + start = startn[extarc]; + /* add arc to the reduced graph */ + if (u[extarc] == 0) + { nxtpushf[extarc] = fpushf[start]; + fpushf[start] = extarc; + new_level = p[node] + rc[extarc]; + if (sb_level[start] > new_level) + { sb_level[start] = new_level; + sb_arc[start] = extarc; + } + } + u[extarc] += incr; + x[extarc] -= incr; + /* remove arc from the reduced graph */ + if (x[extarc] == 0) + { nas++; + arc = fpushb[node]; + if (arc == extarc) + fpushb[node] = nxtpushb[arc]; + else + { prevarc = arc; + arc = nxtpushb[arc]; + while (arc > 0) + { if (arc == extarc) + { nxtpushb[prevarc] = nxtpushb[arc]; + break; + } + prevarc = arc; + arc = nxtpushb[arc]; + } + } + } + node = start; + } + if (node == term) + break; + } + dfct[term] -= incr; + dfct[root] += incr; + /* insert term in the queue if it has a large enough surplus */ + if (dfct[term] < thresh_dfct) + { if (nxtqueue[term] == 0) + { nxtnode = nxtqueue[root]; + if ((p[term] >= p[nxtnode]) && (root != nxtnode)) + { nxtqueue[root] = term; + nxtqueue[term] = nxtnode; + } + else + { nxtqueue[prevnode] = term; + nxtqueue[term] = root; + prevnode = term; + } + } + } + /* if root has a large enough surplus, keep it in the queue and + * return for another iteration */ + if (dfct[root] < thresh_dfct) + { prevnode = root; + root = nxtqueue[root]; + goto L200; + } +L3000:/* end of augmentation cycle */ + /* Check for termination of scaling phase. If scaling phase is not + * finished, advance the queue and return to take another node. */ + nxtnode = nxtqueue[root]; + if (root != nxtnode) + { nxtqueue[root] = 0; + nxtqueue[prevnode] = nxtnode; + root = nxtnode; + goto L200; + } + /* End of subproblem (scaling phase). */ + /* Reduce epsilon. */ + eps /= factor; + if (eps < 1) eps = 1; + thresh_dfct /= factor; + if (eps == 1) thresh_dfct = 0; + /* if another auction scaling phase remains, reset the flows & + * the push lists; else reset arc flows to satisfy cs and compute + * reduced costs */ + if (crash == 1) + { for (arc = 1; arc <= na; arc++) + { start = startn[arc]; + end = endn[arc]; + pstart = p[start]; + pend = p[end]; + if (pstart > pend + eps + rc[arc]) + { resid = u[arc]; + if (resid > 0) + { dfct[start] += resid; + dfct[end] -= resid; + x[arc] += resid; + u[arc] = 0; + } + } + else if (pstart < pend - eps + rc[arc]) + { flow = x[arc]; + if (flow > 0) + { dfct[start] -= flow; + dfct[end] += flow; + x[arc] = 0; + u[arc] += flow; + } + } + } + /* return for another phase */ + goto L100; + } + else + { crash = 1; + for (arc = 1; arc <= na; arc++) + { start = startn[arc]; + end = endn[arc]; + red_cost = rc[arc] + p[end] - p[start]; + if (red_cost < 0) + { resid = u[arc]; + if (resid > 0) + { dfct[start] += resid; + dfct[end] -= resid; + x[arc] += resid; + u[arc] = 0; + } + } + else if (red_cost > 0) + { flow = x[arc]; + if (flow > 0) + { dfct[start] -= flow; + dfct[end] += flow; + x[arc] = 0; + u[arc] += flow; + } + } + rc[arc] = red_cost; + } + } + return 0; +# undef crash +# undef nsp +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/relax4.h b/resources/3rdparty/glpk-4.53/src/misc/relax4.h new file mode 100644 index 000000000..44991fc55 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/relax4.h @@ -0,0 +1,102 @@ +/* relax4.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef RELAX4_H +#define RELAX4_H + +struct relax4_csa +{ /* common storage area */ + /* input parameters --------------------------------------------*/ + int n; + /* number of nodes */ + int na; + /* number of arcs */ + int large; + /* very large int to represent infinity */ + int repeat; + /* true if initialization is to be skipped (false otherwise) */ + int crash; + /* 0 if default initialization is used + * 1 if auction initialization is used */ + int *startn; /* int startn[1+na]; */ + /* startn[j] = starting node for arc j, j = 1,...,na */ + int *endn; /* int endn[1+na] */ + /* endn[j] = ending node for arc j, j = 1,...,na */ + int *fou; /* int fou[1+n]; */ + /* fou[i] = first arc out of node i, i = 1,...,n */ + int *nxtou; /* int nxtou[1+na]; */ + /* nxtou[j] = next arc out of the starting node of arc j, + * j = 1,...,na */ + int *fin; /* int fin[1+n]; */ + /* fin[i] = first arc into node i, i = 1,...,n */ + int *nxtin; /* int nxtin[1+na]; */ + /* nxtin[j] = next arc into the ending node of arc j, + * j = 1,...,na */ + /* updated parameters ------------------------------------------*/ + int *rc; /* int rc[1+na]; */ + /* rc[j] = reduced cost of arc j, j = 1,...,na */ + int *u; /* int u[1+na]; */ + /* u[j] = capacity of arc j on input + * and (capacity of arc j) - x(j) on output, j = 1,...,na */ + int *dfct; /* int dfct[1+n]; */ + /* dfct[i] = demand at node i on input + * and zero on output, i = 1,...,n */ + /* output parameters -------------------------------------------*/ + int *x; /* int x[1+na]; */ + /* x[j] = flow on arc j, j = 1,...,na */ + int nmultinode; + /* number of multinode relaxation iterations in RELAX4 */ + int iter; + /* number of relaxation iterations in RELAX4 */ + int num_augm; + /* number of flow augmentation steps in RELAX4 */ + int num_ascnt; + /* number of multinode ascent steps in RELAX4 */ + int nsp; + /* number of auction/shortest path iterations */ + /* working parameters ------------------------------------------*/ + int *label; /* int label, tempin, p[1+n]; */ + int *prdcsr; /* int prdcsr, tempou, price[1+n]; */ + int *save; /* int save[1+na]; */ + int *tfstou; /* int tfstou, fpushf[1+n]; */ + int *tnxtou; /* int tnxtou, nxtpushf[1+na]; */ + int *tfstin; /* int tfstin, fpushb[1+n]; */ + int *tnxtin; /* int tnxtin, nxtpushb[1+na]; */ + int *nxtqueue; /* int nxtqueue[1+n]; */ + char *scan; /* bool scan[1+n]; */ + char *mark; /* bool mark, path_id[1+n]; */ + /* working parameters used by routine auction only -------------*/ + int *extend_arc; /* int extend_arc[1+n]; */ + int *sb_level; /* int sb_level[1+n]; */ + int *sb_arc; /* int sb_arc[1+n]; */ +}; + +#define relax4 _glp_relax4 +int relax4(struct relax4_csa *csa); + +#define relax4_inidat _glp_relax4_inidat +void relax4_inidat(struct relax4_csa *csa); + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/rng.c b/resources/3rdparty/glpk-4.53/src/misc/rng.c new file mode 100644 index 000000000..e0acb53a2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/rng.c @@ -0,0 +1,227 @@ +/* rng.c (pseudo-random number generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is a modified version of the module GB_FLIP, a portable +* pseudo-random number generator. The original version of GB_FLIP is +* a part of The Stanford GraphBase developed by Donald E. Knuth (see +* http://www-cs-staff.stanford.edu/~knuth/sgb.html). +* +* Note that all changes concern only external names, so this modified +* version produces exactly the same results as the original version. +* +* Changes were made by Andrew Makhorin <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "rng.h" + +#if 0 +int A[56] = { -1 }; +#else +#define A (rand->A) +#endif +/* pseudo-random values */ + +#if 0 +int *fptr = A; +#else +#define fptr (rand->fptr) +#endif +/* the next A value to be exported */ + +#define mod_diff(x, y) (((x) - (y)) & 0x7FFFFFFF) +/* difference modulo 2^31 */ + +static int flip_cycle(RNG *rand) +{ /* this is an auxiliary routine to do 55 more steps of the basic + * recurrence, at high speed, and to reset fptr */ + int *ii, *jj; + for (ii = &A[1], jj = &A[32]; jj <= &A[55]; ii++, jj++) + *ii = mod_diff(*ii, *jj); + for (jj = &A[1]; ii <= &A[55]; ii++, jj++) + *ii = mod_diff(*ii, *jj); + fptr = &A[54]; + return A[55]; +} + +/*********************************************************************** +* NAME +* +* rng_create_rand - create pseudo-random number generator +* +* SYNOPSIS +* +* #include "rng.h" +* RNG *rng_create_rand(void); +* +* DESCRIPTION +* +* The routine rng_create_rand creates and initializes a pseudo-random +* number generator. +* +* RETURNS +* +* The routine returns a pointer to the generator created. */ + +RNG *rng_create_rand(void) +{ RNG *rand; + int i; + rand = talloc(1, RNG); + A[0] = -1; + for (i = 1; i <= 55; i++) A[i] = 0; + fptr = A; + rng_init_rand(rand, 1); + return rand; +} + +/*********************************************************************** +* NAME +* +* rng_init_rand - initialize pseudo-random number generator +* +* SYNOPSIS +* +* #include "rng.h" +* void rng_init_rand(RNG *rand, int seed); +* +* DESCRIPTION +* +* The routine rng_init_rand initializes the pseudo-random number +* generator. The parameter seed may be any integer number. Note that +* on creating the generator this routine is called with the parameter +* seed equal to 1. */ + +void rng_init_rand(RNG *rand, int seed) +{ int i; + int prev = seed, next = 1; + seed = prev = mod_diff(prev, 0); + A[55] = prev; + for (i = 21; i; i = (i + 21) % 55) + { A[i] = next; + next = mod_diff(prev, next); + if (seed & 1) + seed = 0x40000000 + (seed >> 1); + else + seed >>= 1; + next = mod_diff(next, seed); + prev = A[i]; + } + flip_cycle(rand); + flip_cycle(rand); + flip_cycle(rand); + flip_cycle(rand); + flip_cycle(rand); + return; +} + +/*********************************************************************** +* NAME +* +* rng_next_rand - obtain pseudo-random integer in the range [0, 2^31-1] +* +* SYNOPSIS +* +* #include "rng.h" +* int rng_next_rand(RNG *rand); +* +* RETURNS +* +* The routine rng_next_rand returns a next pseudo-random integer which +* is uniformly distributed between 0 and 2^31-1, inclusive. The period +* length of the generated numbers is 2^85 - 2^30. The low order bits of +* the generated numbers are just as random as the high-order bits. */ + +int rng_next_rand(RNG *rand) +{ return + *fptr >= 0 ? *fptr-- : flip_cycle(rand); +} + +/*********************************************************************** +* NAME +* +* rng_unif_rand - obtain pseudo-random integer in the range [0, m-1] +* +* SYNOPSIS +* +* #include "rng.h" +* int rng_unif_rand(RNG *rand, int m); +* +* RETURNS +* +* The routine rng_unif_rand returns a next pseudo-random integer which +* is uniformly distributed between 0 and m-1, inclusive, where m is any +* positive integer less than 2^31. */ + +#define two_to_the_31 ((unsigned int)0x80000000) + +int rng_unif_rand(RNG *rand, int m) +{ unsigned int t = two_to_the_31 - (two_to_the_31 % m); + int r; + xassert(m > 0); + do { r = rng_next_rand(rand); } while (t <= (unsigned int)r); + return r % m; +} + +/*********************************************************************** +* NAME +* +* rng_delete_rand - delete pseudo-random number generator +* +* SYNOPSIS +* +* #include "rng.h" +* void rng_delete_rand(RNG *rand); +* +* DESCRIPTION +* +* The routine rng_delete_rand frees all the memory allocated to the +* specified pseudo-random number generator. */ + +void rng_delete_rand(RNG *rand) +{ tfree(rand); + return; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +/* To be sure that this modified version produces the same results as + * the original version, run this validation program. */ + +int main(void) +{ RNG *rand; + int j; + rand = rng_create_rand(); + rng_init_rand(rand, -314159); + if (rng_next_rand(rand) != 119318998) + { fprintf(stderr, "Failure on the first try!\n"); + return -1; + } + for (j = 1; j <= 133; j++) rng_next_rand(rand); + if (rng_unif_rand(rand, 0x55555555) != 748103812) + { fprintf(stderr, "Failure on the second try!\n"); + return -2; + } + fprintf(stderr, "OK, the random-number generator routines seem to" + " work!\n"); + rng_delete_rand(rand); + return 0; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/rng.h b/resources/3rdparty/glpk-4.53/src/misc/rng.h new file mode 100644 index 000000000..9747b4490 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/rng.h @@ -0,0 +1,67 @@ +/* rng.h (pseudo-random number generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2003, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef RNG_H +#define RNG_H + +typedef struct RNG RNG; + +struct RNG +{ /* Knuth's portable pseudo-random number generator */ + int A[56]; + /* pseudo-random values */ + int *fptr; + /* the next A value to be exported */ +}; + +#define rng_create_rand _glp_rng_create_rand +RNG *rng_create_rand(void); +/* create pseudo-random number generator */ + +#define rng_init_rand _glp_rng_init_rand +void rng_init_rand(RNG *rand, int seed); +/* initialize pseudo-random number generator */ + +#define rng_next_rand _glp_rng_next_rand +int rng_next_rand(RNG *rand); +/* obtain pseudo-random integer in the range [0, 2^31-1] */ + +#define rng_unif_rand _glp_rng_unif_rand +int rng_unif_rand(RNG *rand, int m); +/* obtain pseudo-random integer in the range [0, m-1] */ + +#define rng_delete_rand _glp_rng_delete_rand +void rng_delete_rand(RNG *rand); +/* delete pseudo-random number generator */ + +#define rng_unif_01 _glp_rng_unif_01 +double rng_unif_01(RNG *rand); +/* obtain pseudo-random number in the range [0, 1] */ + +#define rng_uniform _glp_rng_uniform +double rng_uniform(RNG *rand, double a, double b); +/* obtain pseudo-random number in the range [a, b] */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/rng1.c b/resources/3rdparty/glpk-4.53/src/misc/rng1.c new file mode 100644 index 000000000..567c79eb8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/rng1.c @@ -0,0 +1,73 @@ +/* rng1.c (pseudo-random number generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2003, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "rng.h" + +/*********************************************************************** +* NAME +* +* rng_unif_01 - obtain pseudo-random number in the range [0, 1] +* +* SYNOPSIS +* +* #include "rng.h" +* double rng_unif_01(RNG *rand); +* +* RETURNS +* +* The routine rng_unif_01 returns a next pseudo-random number which is +* uniformly distributed in the range [0, 1]. */ + +double rng_unif_01(RNG *rand) +{ double x; + x = (double)rng_next_rand(rand) / 2147483647.0; + xassert(0.0 <= x && x <= 1.0); + return x; +} + +/*********************************************************************** +* NAME +* +* rng_uniform - obtain pseudo-random number in the range [a, b] +* +* SYNOPSIS +* +* #include "rng.h" +* double rng_uniform(RNG *rand, double a, double b); +* +* RETURNS +* +* The routine rng_uniform returns a next pseudo-random number which is +* uniformly distributed in the range [a, b]. */ + +double rng_uniform(RNG *rand, double a, double b) +{ double x; + xassert(a < b); + x = rng_unif_01(rand); + x = a * (1.0 - x) + b * x; + xassert(a <= x && x <= b); + return x; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/round2n.c b/resources/3rdparty/glpk-4.53/src/misc/round2n.c new file mode 100644 index 000000000..126d638c1 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/round2n.c @@ -0,0 +1,64 @@ +/* round2n.c (round floating-point number to nearest power of two) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* round2n - round floating-point number to nearest power of two +* +* SYNOPSIS +* +* #include "misc.h" +* double round2n(double x); +* +* RETURNS +* +* Given a positive floating-point value x the routine round2n returns +* 2^n such that |x - 2^n| is minimal. +* +* EXAMPLES +* +* round2n(10.1) = 2^3 = 8 +* round2n(15.3) = 2^4 = 16 +* round2n(0.01) = 2^(-7) = 0.0078125 +* +* BACKGROUND +* +* Let x = f * 2^e, where 0.5 <= f < 1 is a normalized fractional part, +* e is an integer exponent. Then, obviously, 0.5 * 2^e <= x < 2^e, so +* if x - 0.5 * 2^e <= 2^e - x, we choose 0.5 * 2^e = 2^(e-1), and 2^e +* otherwise. The latter condition can be written as 2 * x <= 1.5 * 2^e +* or 2 * f * 2^e <= 1.5 * 2^e or, finally, f <= 0.75. */ + +double round2n(double x) +{ int e; + double f; + xassert(x > 0.0); + f = frexp(x, &e); + return ldexp(1.0, f <= 0.75 ? e-1 : e); +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/str2int.c b/resources/3rdparty/glpk-4.53/src/misc/str2int.c new file mode 100644 index 000000000..5d8117a55 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/str2int.c @@ -0,0 +1,92 @@ +/* str2int.c (convert string to int) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "misc.h" +#include "stdc.h" + +/*********************************************************************** +* NAME +* +* str2int - convert character string to value of int type +* +* SYNOPSIS +* +* #include "misc.h" +* int str2int(const char *str, int *val); +* +* DESCRIPTION +* +* The routine str2int converts the character string str to a value of +* integer type and stores the value into location, which the parameter +* val points to (in the case of error content of this location is not +* changed). +* +* RETURNS +* +* The routine returns one of the following error codes: +* +* 0 - no error; +* 1 - value out of range; +* 2 - character string is syntactically incorrect. */ + +int str2int(const char *str, int *val_) +{ int d, k, s, val = 0; + /* scan optional sign */ + if (str[0] == '+') + s = +1, k = 1; + else if (str[0] == '-') + s = -1, k = 1; + else + s = +1, k = 0; + /* check for the first digit */ + if (!isdigit((unsigned char)str[k])) + return 2; + /* scan digits */ + while (isdigit((unsigned char)str[k])) + { d = str[k++] - '0'; + if (s > 0) + { if (val > INT_MAX / 10) + return 1; + val *= 10; + if (val > INT_MAX - d) + return 1; + val += d; + } + else /* s < 0 */ + { if (val < INT_MIN / 10) + return 1; + val *= 10; + if (val < INT_MIN + d) + return 1; + val -= d; + } + } + /* check for terminator */ + if (str[k] != '\0') + return 2; + /* conversion has been done */ + *val_ = val; + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/str2num.c b/resources/3rdparty/glpk-4.53/src/misc/str2num.c new file mode 100644 index 000000000..f67c2fc17 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/str2num.c @@ -0,0 +1,110 @@ +/* str2num.c (convert string to double) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "misc.h" +#include "stdc.h" + +/*********************************************************************** +* NAME +* +* str2num - convert character string to value of double type +* +* SYNOPSIS +* +* #include "misc.h" +* int str2num(const char *str, double *val); +* +* DESCRIPTION +* +* The routine str2num converts the character string str to a value of +* double type and stores the value into location, which the parameter +* val points to (in the case of error content of this location is not +* changed). +* +* RETURNS +* +* The routine returns one of the following error codes: +* +* 0 - no error; +* 1 - value out of range; +* 2 - character string is syntactically incorrect. */ + +int str2num(const char *str, double *val_) +{ int k; + double val; + /* scan optional sign */ + k = (str[0] == '+' || str[0] == '-' ? 1 : 0); + /* check for decimal point */ + if (str[k] == '.') + { k++; + /* a digit should follow it */ + if (!isdigit((unsigned char)str[k])) + return 2; + k++; + goto frac; + } + /* integer part should start with a digit */ + if (!isdigit((unsigned char)str[k])) + return 2; + /* scan integer part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for decimal point */ + if (str[k] == '.') k++; +frac: /* scan optional fraction part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for decimal exponent */ + if (str[k] == 'E' || str[k] == 'e') + { k++; + /* scan optional sign */ + if (str[k] == '+' || str[k] == '-') + k++; + /* a digit should follow E, E+ or E- */ + if (!isdigit((unsigned char)str[k])) + return 2; + } + /* scan optional exponent part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for terminator */ + if (str[k] != '\0') + return 2; + /* perform conversion */ + { char *endptr; + val = strtod(str, &endptr); + if (*endptr != '\0') + return 2; + } + /* check for overflow */ + if (!(-DBL_MAX <= val && val <= +DBL_MAX)) + return 1; + /* check for underflow */ + if (-DBL_MIN < val && val < +DBL_MIN) + val = 0.0; + /* conversion has been done */ + *val_ = val; + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/strspx.c b/resources/3rdparty/glpk-4.53/src/misc/strspx.c new file mode 100644 index 000000000..f0702f9ce --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/strspx.c @@ -0,0 +1,60 @@ +/* strspx.c (remove all spaces from string) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "misc.h" + +/*********************************************************************** +* NAME +* +* strspx - remove all spaces from character string +* +* SYNOPSIS +* +* #include "misc.h" +* char *strspx(char *str); +* +* DESCRIPTION +* +* The routine strspx removes all spaces from the character string str. +* +* RETURNS +* +* The routine returns a pointer to the character string. +* +* EXAMPLES +* +* strspx(" Errare humanum est ") => "Errarehumanumest" +* +* strspx(" ") => "" */ + +char *strspx(char *str) +{ char *s, *t; + for (s = t = str; *s; s++) + { if (*s != ' ') + *t++ = *s; + } + *t = '\0'; + return str; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/strtrim.c b/resources/3rdparty/glpk-4.53/src/misc/strtrim.c new file mode 100644 index 000000000..a9b782359 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/strtrim.c @@ -0,0 +1,62 @@ +/* strtrim.c (remove trailing spaces from string) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "misc.h" +#include "stdc.h" + +/*********************************************************************** +* NAME +* +* strtrim - remove trailing spaces from character string +* +* SYNOPSIS +* +* #include "misc.h" +* char *strtrim(char *str); +* +* DESCRIPTION +* +* The routine strtrim removes trailing spaces from the character +* string str. +* +* RETURNS +* +* The routine returns a pointer to the character string. +* +* EXAMPLES +* +* strtrim("Errare humanum est ") => "Errare humanum est" +* +* strtrim(" ") => "" */ + +char *strtrim(char *str) +{ char *t; + for (t = strrchr(str, '\0') - 1; t >= str; t--) + { if (*t != ' ') + break; + *t = '\0'; + } + return str; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/triang.c b/resources/3rdparty/glpk-4.53/src/misc/triang.c new file mode 100644 index 000000000..bb95ecc3a --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/triang.c @@ -0,0 +1,311 @@ +/* triang.c (find maximal triangular part of rectangular matrix) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "triang.h" + +/*********************************************************************** +* triang - find maximal triangular part of rectangular matrix +* +* Given a mxn sparse matrix A this routine finds permutation matrices +* P and Q such that matrix A' = P * A * Q has the following structure: +* +* 1 s n +* 1 * . . . . . x x x x x +* * * . . . . x x x x x +* * * * . . . x x x x x +* * * * * . . x x x x x +* * * * * * . x x x x x +* s * * * * * * x x x x x +* x x x x x x x x x x x +* x x x x x x x x x x x +* m x x x x x x x x x x x +* +* where '*' are elements of the triangular part, '.' are structural +* zeros, 'x' are other elements. +* +* The formal routine mat specifies the original matrix A in both row- +* and column-wise format. If the routine mat is called with k = +i, +* 1 <= i <= m, it should store column indices and values of non-zero +* elements of i-th row of A in locations ind[1], ..., ind[len] and +* val[1], ..., val[len], resp., where len is the returned number of +* non-zeros in the row, 0 <= len <= n. Similarly, if the routine mat +* is called with k = -j, 1 <= j <= n, it should store row indices and +* values of non-zero elements of j-th column of A and return len, the +* number of non-zeros in the column, 0 <= len <= m. Should note that +* duplicate indices are not allowed. +* +* The parameter info is a transit pointer passed to the routine mat. +* +* The parameter tol is a tolerance. The routine triang guarantees that +* each diagonal element in the triangular part of matrix A' is not +* less in magnitude than tol * max, where max is the maximal magnitude +* of elements in corresponding column. +* +* On exit the routine triang stores information on the triangular part +* found in the arrays rn and cn. Elements rn[1], ..., rn[s] specify +* row numbers and elements cn[1], ..., cn[s] specify column numbers +* of the original matrix A, which correspond to rows/columns 1, ..., s +* of matrix A', where s is the size of the triangular part returned by +* the routine, 0 <= s <= min(m, n). The order of rows and columns that +* are not included in the triangular part remains unspecified. +* +* ALGORITHM +* +* The routine triang uses a simple greedy heuristic. +* +* At some step the matrix A' = P * A * Q has the following structure: +* +* 1 n +* 1 * . . . . . . . x x x +* * * . . . . . . x x x +* * * * . . . . . x x x +* * * * * . . . . x x x +* x x x x # # # # x x x +* x x x x # # # # x x x +* x x x x # # # # x x x +* x x x x # # # # x x x +* m x x x x # # # # x x x +* +* where '#' are elements of active submatrix. Initially P = Q = I, so +* the active submatrix is the original matrix A = A'. +* +* If some row has exactly one non-zero in the active submatrix (row +* singleton), the routine includes this row and corresponding column +* in the triangular part, and removes the column from the active +* submatrix. Otherwise, the routine simply removes a column having +* maximal number of non-zeros from the active submatrix in the hope +* that new row singleton(s) will appear. +* +* COMPLEXITY +* +* The time complexity of the routine triang is O(nnz), where nnz is +* number of non-zeros in the original matrix A. */ + +int triang(int m, int n, int (*mat)(void *info, int k, int ind[], + double val[]), void *info, double tol, int rn[], int cn[]) +{ int head, i, j, jj, k, kk, ks, len, len2, next_j, ns, size; + int *cind, *rind, *cnt, *ptr, *list, *prev, *next; + double *cval, *rval, *big; + char *flag; + /* allocate working arrays */ + cind = talloc(1+m, int); + cval = talloc(1+m, double); + rind = talloc(1+n, int); + rval = talloc(1+n, double); + cnt = ptr = talloc(1+m, int); + list = talloc(1+n, int); + prev = talloc(1+n, int); + next = talloc(1+n, int); + big = talloc(1+n, double); + flag = talloc(1+n, char); + /*--------------------------------------------------------------*/ + /* build linked lists of columns having equal lengths */ + /*--------------------------------------------------------------*/ + /* ptr[len], 0 <= len <= m, is number of first column of length + * len; + * next[j], 1 <= j <= n, is number of next column having the same + * length as column j; + * big[j], 1 <= j <= n, is maximal magnitude of elements in j-th + * column */ + for (len = 0; len <= m; len++) + ptr[len] = 0; + for (j = 1; j <= n; j++) + { /* get j-th column */ + len = mat(info, -j, cind, cval); + xassert(0 <= len && len <= m); + /* add this column to beginning of list ptr[len] */ + next[j] = ptr[len]; + ptr[len] = j; + /* determine maximal magnitude of elements in this column */ + big[j] = 0.0; + for (k = 1; k <= len; k++) + { if (big[j] < fabs(cval[k])) + big[j] = fabs(cval[k]); + } + } + /*--------------------------------------------------------------*/ + /* build doubly linked list of columns ordered by decreasing */ + /* column lengths */ + /*--------------------------------------------------------------*/ + /* head is number of first column in the list; + * prev[j], 1 <= j <= n, is number of column that precedes j-th + * column in the list; + * next[j], 1 <= j <= n, is number of column that follows j-th + * column in the list */ + head = 0; + for (len = 0; len <= m; len++) + { /* walk thru list of columns of length len */ + for (j = ptr[len]; j != 0; j = next_j) + { next_j = next[j]; + /* add j-th column to beginning of the column list */ + prev[j] = 0; + next[j] = head; + if (head != 0) + prev[head] = j; + head = j; + } + } + /*--------------------------------------------------------------*/ + /* build initial singleton list */ + /*--------------------------------------------------------------*/ + /* there are used two list of columns: + * 1) doubly linked list of active columns, in which all columns + * are ordered by decreasing column lengths; + * 2) singleton list; an active column is included in this list + * if it has at least one row singleton in active submatrix */ + /* flag[j], 1 <= j <= n, is a flag of j-th column: + * 0 j-th column is inactive; + * 1 j-th column is active; + * 2 j-th column is active and has row singleton(s) */ + /* initially all columns are active */ + for (j = 1; j <= n; j++) + flag[j] = 1; + /* initialize row counts and build initial singleton list */ + /* cnt[i], 1 <= i <= m, is number of non-zeros, which i-th row + * has in active submatrix; + * ns is size of singleton list; + * list[1], ..., list[ns] are numbers of active columns included + * in the singleton list */ + ns = 0; + for (i = 1; i <= m; i++) + { /* get i-th row */ + len = cnt[i] = mat(info, +i, rind, rval); + xassert(0 <= len && len <= n); + if (len == 1) + { /* a[i,j] is row singleton */ + j = rind[1]; + xassert(1 <= j && j <= n); + if (flag[j] != 2) + { /* include j-th column in singleton list */ + flag[j] = 2; + list[++ns] = j; + } + } + } + /*--------------------------------------------------------------*/ + /* main loop */ + /*--------------------------------------------------------------*/ + size = 0; /* size of triangular part */ + /* loop until active column list is non-empty, i.e. until the + * active submatrix has at least one column */ + while (head != 0) + { if (ns == 0) + { /* singleton list is empty */ + /* remove from the active submatrix a column of maximal + * length in the hope that some row singletons appear */ + j = head; + len = mat(info, -j, cind, cval); + xassert(0 <= len && len <= m); + goto drop; + } + /* take column j from the singleton list */ + j = list[ns--]; + xassert(flag[j] == 2); + /* j-th column has at least one row singleton in the active + * submatrix; choose one having maximal magnitude */ + len = mat(info, -j, cind, cval); + xassert(0 <= len && len <= m); + kk = 0; + for (k = 1; k <= len; k++) + { i = cind[k]; + xassert(1 <= i && i <= m); + if (cnt[i] == 1) + { /* a[i,j] is row singleton */ + if (kk == 0 || fabs(cval[kk]) < fabs(cval[k])) + kk = k; + } + } + xassert(kk > 0); + /* check magnitude of the row singleton chosen */ + if (fabs(cval[kk]) < tol * big[j]) + { /* all row singletons are too small in magnitude; drop j-th + * column */ + goto drop; + } + /* row singleton a[i,j] is ok; add i-th row and j-th column to + * the triangular part */ + size++; + rn[size] = cind[kk]; + cn[size] = j; +drop: /* remove j-th column from the active submatrix */ + xassert(flag[j]); + flag[j] = 0; + if (prev[j] == 0) + head = next[j]; + else + next[prev[j]] = next[j]; + if (next[j] == 0) + ; + else + prev[next[j]] = prev[j]; + /* decrease row counts */ + for (k = 1; k <= len; k++) + { i = cind[k]; + xassert(1 <= i && i <= m); + xassert(cnt[i] > 0); + cnt[i]--; + if (cnt[i] == 1) + { /* new singleton appeared in i-th row; determine number + * of corresponding column (it is the only active column + * in this row) */ + len2 = mat(info, +i, rind, rval); + xassert(0 <= len2 && len2 <= n); + ks = 0; + for (kk = 1; kk <= len2; kk++) + { jj = rind[kk]; + xassert(1 <= jj && jj <= n); + if (flag[jj]) + { xassert(ks == 0); + ks = kk; + } + } + xassert(ks > 0); + /* a[i,jj] is new row singleton */ + jj = rind[ks]; + if (flag[jj] != 2) + { /* include jj-th column in the singleton list */ + flag[jj] = 2; + list[++ns] = jj; + } + } + } + } + /* now all row counts should be zero */ + for (i = 1; i <= m; i++) + xassert(cnt[i] == 0); + /* deallocate working arrays */ + tfree(cind); + tfree(cval); + tfree(rind); + tfree(rval); + tfree(ptr); + tfree(list); + tfree(prev); + tfree(next); + tfree(big); + tfree(flag); + return size; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/triang.h b/resources/3rdparty/glpk-4.53/src/misc/triang.h new file mode 100644 index 000000000..1d5f484d7 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/triang.h @@ -0,0 +1,34 @@ +/* triang.h (find maximal triangular part of rectangular matrix) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef TRIANG_H +#define TRIANG_H + +#define triang _glp_triang +int triang(int m, int n, int (*mat)(void *info, int k, int ind[], + double val[]), void *info, double tol, int rn[], int cn[]); +/* find maximal triangular part of rectangular matrix */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/wclique.c b/resources/3rdparty/glpk-4.53/src/misc/wclique.c new file mode 100644 index 000000000..5daa69cff --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/wclique.c @@ -0,0 +1,242 @@ +/* wclique.c (maximum weight clique, Ostergard's algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Two subroutines sub() and wclique() below are intended to find a +* maximum weight clique in a given undirected graph. These subroutines +* are slightly modified version of the program WCLIQUE developed by +* Patric Ostergard <http://www.tcs.hut.fi/~pat/wclique.html> and based +* on ideas from the article "P. R. J. Ostergard, A new algorithm for +* the maximum-weight clique problem, submitted for publication", which +* in turn is a generalization of the algorithm for unweighted graphs +* presented in "P. R. J. Ostergard, A fast algorithm for the maximum +* clique problem, submitted for publication". +* +* USED WITH PERMISSION OF THE AUTHOR OF THE ORIGINAL CODE. +* +* Changes were made by Andrew Makhorin <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "wclique.h" + +/*********************************************************************** +* NAME +* +* wclique - find maximum weight clique with Ostergard's algorithm +* +* SYNOPSIS +* +* #include "wclique.h" +* int wclique(int n, const int w[], const unsigned char a[], +* int ind[]); +* +* DESCRIPTION +* +* The routine wclique finds a maximum weight clique in an undirected +* graph with Ostergard's algorithm. +* +* INPUT PARAMETERS +* +* n is the number of vertices, n > 0. +* +* w[i], i = 1,...,n, is a weight of vertex i. +* +* a[*] is the strict (without main diagonal) lower triangle of the +* graph adjacency matrix in packed format. +* +* OUTPUT PARAMETER +* +* ind[k], k = 1,...,size, is the number of a vertex included in the +* clique found, 1 <= ind[k] <= n, where size is the number of vertices +* in the clique returned on exit. +* +* RETURNS +* +* The routine returns the clique size, i.e. the number of vertices in +* the clique. */ + +struct csa +{ /* common storage area */ + int n; + /* number of vertices */ + const int *wt; /* int wt[0:n-1]; */ + /* weights */ + const unsigned char *a; + /* adjacency matrix (packed lower triangle without main diag.) */ + int record; + /* weight of best clique */ + int rec_level; + /* number of vertices in best clique */ + int *rec; /* int rec[0:n-1]; */ + /* best clique so far */ + int *clique; /* int clique[0:n-1]; */ + /* table for pruning */ + int *set; /* int set[0:n-1]; */ + /* current clique */ +}; + +#define n (csa->n) +#define wt (csa->wt) +#define a (csa->a) +#define record (csa->record) +#define rec_level (csa->rec_level) +#define rec (csa->rec) +#define clique (csa->clique) +#define set (csa->set) + +#if 0 +static int is_edge(struct csa *csa, int i, int j) +{ /* if there is arc (i,j), the routine returns true; otherwise + * false; 0 <= i, j < n */ + int k; + xassert(0 <= i && i < n); + xassert(0 <= j && j < n); + if (i == j) return 0; + if (i < j) k = i, i = j, j = k; + k = (i * (i - 1)) / 2 + j; + return a[k / CHAR_BIT] & + (unsigned char)(1 << ((CHAR_BIT - 1) - k % CHAR_BIT)); +} +#else +#define is_edge(csa, i, j) ((i) == (j) ? 0 : \ + (i) > (j) ? is_edge1(i, j) : is_edge1(j, i)) +#define is_edge1(i, j) is_edge2(((i) * ((i) - 1)) / 2 + (j)) +#define is_edge2(k) (a[(k) / CHAR_BIT] & \ + (unsigned char)(1 << ((CHAR_BIT - 1) - (k) % CHAR_BIT))) +#endif + +static void sub(struct csa *csa, int ct, int table[], int level, + int weight, int l_weight) +{ int i, j, k, curr_weight, left_weight, *p1, *p2, *newtable; + newtable = xcalloc(n, sizeof(int)); + if (ct <= 0) + { /* 0 or 1 elements left; include these */ + if (ct == 0) + { set[level++] = table[0]; + weight += l_weight; + } + if (weight > record) + { record = weight; + rec_level = level; + for (i = 0; i < level; i++) rec[i] = set[i]; + } + goto done; + } + for (i = ct; i >= 0; i--) + { if ((level == 0) && (i < ct)) goto done; + k = table[i]; + if ((level > 0) && (clique[k] <= (record - weight))) + goto done; /* prune */ + set[level] = k; + curr_weight = weight + wt[k]; + l_weight -= wt[k]; + if (l_weight <= (record - curr_weight)) + goto done; /* prune */ + p1 = newtable; + p2 = table; + left_weight = 0; + while (p2 < table + i) + { j = *p2++; + if (is_edge(csa, j, k)) + { *p1++ = j; + left_weight += wt[j]; + } + } + if (left_weight <= (record - curr_weight)) continue; + sub(csa, p1 - newtable - 1, newtable, level + 1, curr_weight, + left_weight); + } +done: xfree(newtable); + return; +} + +int wclique(int n_, const int w[], const unsigned char a_[], int ind[]) +{ struct csa csa_, *csa = &csa_; + int i, j, p, max_wt, max_nwt, wth, *used, *nwt, *pos; + double timer; + n = n_; + xassert(n > 0); + wt = &w[1]; + a = a_; + record = 0; + rec_level = 0; + rec = &ind[1]; + clique = xcalloc(n, sizeof(int)); + set = xcalloc(n, sizeof(int)); + used = xcalloc(n, sizeof(int)); + nwt = xcalloc(n, sizeof(int)); + pos = xcalloc(n, sizeof(int)); + /* start timer */ + timer = xtime(); + /* order vertices */ + for (i = 0; i < n; i++) + { nwt[i] = 0; + for (j = 0; j < n; j++) + if (is_edge(csa, i, j)) nwt[i] += wt[j]; + } + for (i = 0; i < n; i++) + used[i] = 0; + for (i = n-1; i >= 0; i--) + { max_wt = -1; + max_nwt = -1; + for (j = 0; j < n; j++) + { if ((!used[j]) && ((wt[j] > max_wt) || (wt[j] == max_wt + && nwt[j] > max_nwt))) + { max_wt = wt[j]; + max_nwt = nwt[j]; + p = j; + } + } + pos[i] = p; + used[p] = 1; + for (j = 0; j < n; j++) + if ((!used[j]) && (j != p) && (is_edge(csa, p, j))) + nwt[j] -= wt[p]; + } + /* main routine */ + wth = 0; + for (i = 0; i < n; i++) + { wth += wt[pos[i]]; + sub(csa, i, pos, 0, 0, wth); + clique[pos[i]] = record; + if (xdifftime(xtime(), timer) >= 5.0 - 0.001) + { /* print current record and reset timer */ + xprintf("level = %d (%d); best = %d\n", i+1, n, record); + timer = xtime(); + } + } + xfree(clique); + xfree(set); + xfree(used); + xfree(nwt); + xfree(pos); + /* return the solution found */ + for (i = 1; i <= rec_level; i++) ind[i]++; + return rec_level; +} + +#undef n +#undef wt +#undef a +#undef record +#undef rec_level +#undef rec +#undef clique +#undef set + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/wclique.h b/resources/3rdparty/glpk-4.53/src/misc/wclique.h new file mode 100644 index 000000000..bc6853899 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/wclique.h @@ -0,0 +1,33 @@ +/* wclique.h (maximum weight clique, Ostergard's algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef WCLIQUE_H +#define WCLIQUE_H + +#define wclique _glp_wclique +int wclique(int n, const int w[], const unsigned char a[], int ind[]); +/* find maximum weight clique with Ostergard's algorithm */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/wclique1.c b/resources/3rdparty/glpk-4.53/src/misc/wclique1.c new file mode 100644 index 000000000..ea36ddd73 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/wclique1.c @@ -0,0 +1,317 @@ +/* wclique1.c (maximum weight clique, greedy heuristic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#include "env.h" +#include "wclique1.h" + +/*********************************************************************** +* NAME +* +* wclique1 - find maximum weight clique with greedy heuristic +* +* SYNOPSIS +* +* #include "wclique1.h" +* int wclique1(int n, const double w[], +* int (*func)(void *info, int i, int ind[]), void *info, int c[]); +* +* DESCRIPTION +* +* The routine wclique1 implements a sequential greedy heuristic to +* find maximum weight clique in a given (undirected) graph G = (V, E). +* +* The parameter n specifies the number of vertices |V| in the graph, +* n >= 0. +* +* The array w specifies vertex weights in locations w[i], i = 1,...,n. +* All weights must be non-negative. +* +* The formal routine func specifies the graph. For a given vertex i, +* 1 <= i <= n, it stores indices of all vertices adjacent to vertex i +* in locations ind[1], ..., ind[deg], where deg is the degree of +* vertex i, 0 <= deg < n, returned on exit. Note that self-loops and +* multiple edges are not allowed. +* +* The parameter info is a cookie passed to the routine func. +* +* On exit the routine wclique1 stores vertex indices included in +* the clique found to locations c[1], ..., c[size], where size is the +* clique size returned by the routine, 0 <= size <= n. +* +* RETURNS +* +* The routine wclique1 returns the size of the clique found. */ + +struct vertex { int i; double cw; }; + +static int fcmp(const void *xx, const void *yy) +{ const struct vertex *x = xx, *y = yy; + if (x->cw > y->cw) return -1; + if (x->cw < y->cw) return +1; + return 0; +} + +int wclique1(int n, const double w[], + int (*func)(void *info, int i, int ind[]), void *info, int c[]) +{ struct vertex *v_list; + int deg, c_size, d_size, i, j, k, kk, l, *ind, *c_list, *d_list, + size = 0; + double c_wght, d_wght, *sw, best = 0.0; + char *d_flag, *skip; + /* perform sanity checks */ + xassert(n >= 0); + for (i = 1; i <= n; i++) + xassert(w[i] >= 0.0); + /* if the graph is empty, nothing to do */ + if (n == 0) goto done; + /* allocate working arrays */ + ind = xcalloc(1+n, sizeof(int)); + v_list = xcalloc(1+n, sizeof(struct vertex)); + c_list = xcalloc(1+n, sizeof(int)); + d_list = xcalloc(1+n, sizeof(int)); + d_flag = xcalloc(1+n, sizeof(char)); + skip = xcalloc(1+n, sizeof(char)); + sw = xcalloc(1+n, sizeof(double)); + /* build the vertex list */ + for (i = 1; i <= n; i++) + { v_list[i].i = i; + /* compute the cumulative weight of each vertex i, which is + * cw[i] = w[i] + sum{j : (i,j) in E} w[j] */ + v_list[i].cw = w[i]; + deg = func(info, i, ind); + xassert(0 <= deg && deg < n); + for (k = 1; k <= deg; k++) + { j = ind[k]; + xassert(1 <= j && j <= n && j != i); + v_list[i].cw += w[j]; + } + } + /* sort the vertex list to access vertices in descending order of + * cumulative weights */ + qsort(&v_list[1], n, sizeof(struct vertex), fcmp); + /* initially all vertices are unmarked */ + memset(&skip[1], 0, sizeof(char) * n); + /* clear flags of all vertices */ + memset(&d_flag[1], 0, sizeof(char) * n); + /* look through all vertices of the graph */ + for (l = 1; l <= n; l++) + { /* take vertex i */ + i = v_list[l].i; + /* if this vertex was already included in one of previosuly + * constructed cliques, skip it */ + if (skip[i]) continue; + /* use vertex i as the initial clique vertex */ + c_size = 1; /* size of current clique */ + c_list[1] = i; /* list of vertices in current clique */ + c_wght = w[i]; /* weight of current clique */ + /* determine the candidate set D = { j : (i,j) in E } */ + d_size = func(info, i, d_list); + xassert(0 <= d_size && d_size < n); + d_wght = 0.0; /* weight of set D */ + for (k = 1; k <= d_size; k++) + { j = d_list[k]; + xassert(1 <= j && j <= n && j != i); + xassert(!d_flag[j]); + d_flag[j] = 1; + d_wght += w[j]; + } + /* check an upper bound to the final clique weight */ + if (c_wght + d_wght < best + 1e-5 * (1.0 + fabs(best))) + { /* skip constructing the current clique */ + goto next; + } + /* compute the summary weight of each vertex i in D, which is + * sw[i] = w[i] + sum{j in D and (i,j) in E} w[j] */ + for (k = 1; k <= d_size; k++) + { i = d_list[k]; + sw[i] = w[i]; + /* consider vertices adjacent to vertex i */ + deg = func(info, i, ind); + xassert(0 <= deg && deg < n); + for (kk = 1; kk <= deg; kk++) + { j = ind[kk]; + xassert(1 <= j && j <= n && j != i); + if (d_flag[j]) sw[i] += w[j]; + } + } + /* grow the current clique by adding vertices from D */ + while (d_size > 0) + { /* check an upper bound to the final clique weight */ + if (c_wght + d_wght < best + 1e-5 * (1.0 + fabs(best))) + { /* skip constructing the current clique */ + goto next; + } + /* choose vertex i in D having maximal summary weight */ + i = d_list[1]; + for (k = 2; k <= d_size; k++) + { j = d_list[k]; + if (sw[i] < sw[j]) i = j; + } + /* include vertex i in the current clique */ + c_size++; + c_list[c_size] = i; + c_wght += w[i]; + /* remove all vertices not adjacent to vertex i, including + * vertex i itself, from the candidate set D */ + deg = func(info, i, ind); + xassert(0 <= deg && deg < n); + for (k = 1; k <= deg; k++) + { j = ind[k]; + xassert(1 <= j && j <= n && j != i); + /* vertex j is adjacent to vertex i */ + if (d_flag[j]) + { xassert(d_flag[j] == 1); + /* mark vertex j to keep it in D */ + d_flag[j] = 2; + } + } + kk = d_size, d_size = 0; + for (k = 1; k <= kk; k++) + { j = d_list[k]; + if (d_flag[j] == 1) + { /* remove vertex j from D */ + d_flag[j] = 0; + d_wght -= w[j]; + } + else if (d_flag[j] == 2) + { /* keep vertex j in D */ + d_list[++d_size] = j; + d_flag[j] = 1; + } + else + xassert(d_flag != d_flag); + } + } + /* the current clique has been completely constructed */ + if (best < c_wght) + { best = c_wght; + size = c_size; + xassert(1 <= size && size <= n); + memcpy(&c[1], &c_list[1], size * sizeof(int)); + } +next: /* mark the current clique vertices in order not to use them + * as initial vertices anymore */ + for (k = 1; k <= c_size; k++) + skip[c_list[k]] = 1; + /* set D can be non-empty, so clean up vertex flags */ + for (k = 1; k <= d_size; k++) + d_flag[d_list[k]] = 0; + } + /* free working arrays */ + xfree(ind); + xfree(v_list); + xfree(c_list); + xfree(d_list); + xfree(d_flag); + xfree(skip); + xfree(sw); +done: /* return to the calling program */ + return size; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +#include "glpk.h" +#include "rng.h" + +typedef struct { double w; } v_data; + +#define weight(v) (((v_data *)((v)->data))->w) + +glp_graph *G; + +char *flag; + +int func(void *info, int i, int ind[]) +{ glp_arc *e; + int j, k, deg = 0; + xassert(info == NULL); + xassert(1 <= i && i <= G->nv); + /* look through incoming arcs */ + for (e = G->v[i]->in; e != NULL; e = e->h_next) + { j = e->tail->i; /* j->i */ + if (j != i && !flag[j]) ind[++deg] = j, flag[j] = 1; + } + /* look through outgoing arcs */ + for (e = G->v[i]->out; e != NULL; e = e->t_next) + { j = e->head->i; /* i->j */ + if (j != i && !flag[j]) ind[++deg] = j, flag[j] = 1; + } + /* clear the flag array */ + xassert(deg < G->nv); + for (k = 1; k <= deg; k++) flag[ind[k]] = 0; + return deg; +} + +int main(int argc, char *argv[]) +{ RNG *rand; + int i, k, kk, size, *c, *ind, deg; + double *w, sum, t; + /* read graph in DIMACS format */ + G = glp_create_graph(sizeof(v_data), 0); + xassert(argc == 2); + xassert(glp_read_ccdata(G, offsetof(v_data, w), argv[1]) == 0); + /* print the number of connected components */ + xprintf("nc = %d\n", glp_weak_comp(G, -1)); + /* assign random weights unformly distributed in [1,100] */ + w = xcalloc(1+G->nv, sizeof(double)); + rand = rng_create_rand(); + for (i = 1; i <= G->nv; i++) +#if 0 + w[i] = weight(G->v[i]) = 1.0; +#else + w[i] = weight(G->v[i]) = rng_unif_rand(rand, 100) + 1; +#endif + /* write graph in DIMACS format */ + xassert(glp_write_ccdata(G, offsetof(v_data, w), "graph") == 0); + /* find maximum weight clique */ + c = xcalloc(1+G->nv, sizeof(int)); + flag = xcalloc(1+G->nv, sizeof(char)); + memset(&flag[1], 0, G->nv); + t = xtime(); + size = wclique1(G->nv, w, func, NULL, c); + xprintf("Time used: %.1f s\n", xdifftime(xtime(), t)); + /* check the clique found */ + ind = xcalloc(1+G->nv, sizeof(int)); + for (k = 1; k <= size; k++) + { i = c[k]; + deg = func(NULL, i, ind); + for (kk = 1; kk <= size; kk++) + flag[c[kk]] = 1; + flag[i] = 0; + for (kk = 1; kk <= deg; kk++) + flag[ind[kk]] = 0; + for (kk = 1; kk <= size; kk++) + xassert(flag[c[kk]] == 0); + } + /* compute the clique weight */ + sum = 0.0; + for (i = 1; i <= size; i++) + sum += w[c[i]]; + xprintf("size = %d; sum = %g\n", size, sum); + return 0; +} +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/misc/wclique1.h b/resources/3rdparty/glpk-4.53/src/misc/wclique1.h new file mode 100644 index 000000000..14e10cba5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/misc/wclique1.h @@ -0,0 +1,34 @@ +/* wclique1.h (maximum weight clique, greedy heuristic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef WCLIQUE1_H +#define WCLIQUE1_H + +#define wclique1 _glp_wclique1 +int wclique1(int n, const double w[], + int (*func)(void *info, int i, int ind[]), void *info, int c[]); +/* find maximum weight clique with greedy heuristic */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/prob.h b/resources/3rdparty/glpk-4.53/src/prob.h new file mode 100644 index 000000000..1b9236114 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/prob.h @@ -0,0 +1,276 @@ +/* prob.h (LP/MIP problem object) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef PROB_H +#define PROB_H + +#include "avl.h" +#include "bfd.h" +#include "dmp.h" +#include "glpk.h" + +typedef struct GLPROW GLPROW; +typedef struct GLPCOL GLPCOL; +typedef struct GLPAIJ GLPAIJ; + +#define GLP_PROB_MAGIC 0xD7D9D6C2 + +struct glp_prob +{ /* LP/MIP problem object */ + unsigned magic; + /* magic value used for debugging */ + DMP *pool; + /* memory pool to store problem object components */ + glp_tree *tree; + /* pointer to the search tree; set by the MIP solver when this + object is used in the tree as a core MIP object */ + void *parms; + /* reserved for backward compatibility */ + /*--------------------------------------------------------------*/ + /* LP/MIP data */ + char *name; + /* problem name (1 to 255 chars); NULL means no name is assigned + to the problem */ + char *obj; + /* objective function name (1 to 255 chars); NULL means no name + is assigned to the objective function */ + int dir; + /* optimization direction flag (objective "sense"): + GLP_MIN - minimization + GLP_MAX - maximization */ + double c0; + /* constant term of the objective function ("shift") */ + int m_max; + /* length of the array of rows (enlarged automatically) */ + int n_max; + /* length of the array of columns (enlarged automatically) */ + int m; + /* number of rows, 0 <= m <= m_max */ + int n; + /* number of columns, 0 <= n <= n_max */ + int nnz; + /* number of non-zero constraint coefficients, nnz >= 0 */ + GLPROW **row; /* GLPROW *row[1+m_max]; */ + /* row[i], 1 <= i <= m, is a pointer to i-th row */ + GLPCOL **col; /* GLPCOL *col[1+n_max]; */ + /* col[j], 1 <= j <= n, is a pointer to j-th column */ + AVL *r_tree; + /* row index to find rows by their names; NULL means this index + does not exist */ + AVL *c_tree; + /* column index to find columns by their names; NULL means this + index does not exist */ + /*--------------------------------------------------------------*/ + /* basis factorization (LP) */ + int valid; + /* the factorization is valid only if this flag is set */ + int *head; /* int head[1+m_max]; */ + /* basis header (valid only if the factorization is valid); + head[i] = k is the ordinal number of auxiliary (1 <= k <= m) + or structural (m+1 <= k <= m+n) variable which corresponds to + i-th basic variable xB[i], 1 <= i <= m */ + glp_bfcp *bfcp; + /* basis factorization control parameters; may be NULL */ + BFD *bfd; /* BFD bfd[1:m,1:m]; */ + /* basis factorization driver; may be NULL */ + /*--------------------------------------------------------------*/ + /* basic solution (LP) */ + int pbs_stat; + /* primal basic solution status: + GLP_UNDEF - primal solution is undefined + GLP_FEAS - primal solution is feasible + GLP_INFEAS - primal solution is infeasible + GLP_NOFEAS - no primal feasible solution exists */ + int dbs_stat; + /* dual basic solution status: + GLP_UNDEF - dual solution is undefined + GLP_FEAS - dual solution is feasible + GLP_INFEAS - dual solution is infeasible + GLP_NOFEAS - no dual feasible solution exists */ + double obj_val; + /* objective function value */ + int it_cnt; + /* simplex method iteration count; increased by one on performing + one simplex iteration */ + int some; + /* ordinal number of some auxiliary or structural variable having + certain property, 0 <= some <= m+n */ + /*--------------------------------------------------------------*/ + /* interior-point solution (LP) */ + int ipt_stat; + /* interior-point solution status: + GLP_UNDEF - interior solution is undefined + GLP_OPT - interior solution is optimal + GLP_INFEAS - interior solution is infeasible + GLP_NOFEAS - no feasible solution exists */ + double ipt_obj; + /* objective function value */ + /*--------------------------------------------------------------*/ + /* integer solution (MIP) */ + int mip_stat; + /* integer solution status: + GLP_UNDEF - integer solution is undefined + GLP_OPT - integer solution is optimal + GLP_FEAS - integer solution is feasible + GLP_NOFEAS - no integer solution exists */ + double mip_obj; + /* objective function value */ +}; + +struct GLPROW +{ /* LP/MIP row (auxiliary variable) */ + int i; + /* ordinal number (1 to m) assigned to this row */ + char *name; + /* row name (1 to 255 chars); NULL means no name is assigned to + this row */ + AVLNODE *node; + /* pointer to corresponding node in the row index; NULL means + that either the row index does not exist or this row has no + name assigned */ +#if 1 /* 20/IX-2008 */ + int level; + unsigned char origin; + unsigned char klass; +#endif + int type; + /* type of the auxiliary variable: + GLP_FR - free variable + GLP_LO - variable with lower bound + GLP_UP - variable with upper bound + GLP_DB - double-bounded variable + GLP_FX - fixed variable */ + double lb; /* non-scaled */ + /* lower bound; if the row has no lower bound, lb is zero */ + double ub; /* non-scaled */ + /* upper bound; if the row has no upper bound, ub is zero */ + /* if the row type is GLP_FX, ub is equal to lb */ + GLPAIJ *ptr; /* non-scaled */ + /* pointer to doubly linked list of constraint coefficients which + are placed in this row */ + double rii; + /* diagonal element r[i,i] of scaling matrix R for this row; + if the scaling is not used, r[i,i] is 1 */ + int stat; + /* status of the auxiliary variable: + GLP_BS - basic variable + GLP_NL - non-basic variable on lower bound + GLP_NU - non-basic variable on upper bound + GLP_NF - non-basic free variable + GLP_NS - non-basic fixed variable */ + int bind; + /* if the auxiliary variable is basic, head[bind] refers to this + row, otherwise, bind is 0; this attribute is valid only if the + basis factorization is valid */ + double prim; /* non-scaled */ + /* primal value of the auxiliary variable in basic solution */ + double dual; /* non-scaled */ + /* dual value of the auxiliary variable in basic solution */ + double pval; /* non-scaled */ + /* primal value of the auxiliary variable in interior solution */ + double dval; /* non-scaled */ + /* dual value of the auxiliary variable in interior solution */ + double mipx; /* non-scaled */ + /* primal value of the auxiliary variable in integer solution */ +}; + +struct GLPCOL +{ /* LP/MIP column (structural variable) */ + int j; + /* ordinal number (1 to n) assigned to this column */ + char *name; + /* column name (1 to 255 chars); NULL means no name is assigned + to this column */ + AVLNODE *node; + /* pointer to corresponding node in the column index; NULL means + that either the column index does not exist or the column has + no name assigned */ + int kind; + /* kind of the structural variable: + GLP_CV - continuous variable + GLP_IV - integer or binary variable */ + int type; + /* type of the structural variable: + GLP_FR - free variable + GLP_LO - variable with lower bound + GLP_UP - variable with upper bound + GLP_DB - double-bounded variable + GLP_FX - fixed variable */ + double lb; /* non-scaled */ + /* lower bound; if the column has no lower bound, lb is zero */ + double ub; /* non-scaled */ + /* upper bound; if the column has no upper bound, ub is zero */ + /* if the column type is GLP_FX, ub is equal to lb */ + double coef; /* non-scaled */ + /* objective coefficient at the structural variable */ + GLPAIJ *ptr; /* non-scaled */ + /* pointer to doubly linked list of constraint coefficients which + are placed in this column */ + double sjj; + /* diagonal element s[j,j] of scaling matrix S for this column; + if the scaling is not used, s[j,j] is 1 */ + int stat; + /* status of the structural variable: + GLP_BS - basic variable + GLP_NL - non-basic variable on lower bound + GLP_NU - non-basic variable on upper bound + GLP_NF - non-basic free variable + GLP_NS - non-basic fixed variable */ + int bind; + /* if the structural variable is basic, head[bind] refers to + this column; otherwise, bind is 0; this attribute is valid only + if the basis factorization is valid */ + double prim; /* non-scaled */ + /* primal value of the structural variable in basic solution */ + double dual; /* non-scaled */ + /* dual value of the structural variable in basic solution */ + double pval; /* non-scaled */ + /* primal value of the structural variable in interior solution */ + double dval; /* non-scaled */ + /* dual value of the structural variable in interior solution */ + double mipx; /* non-scaled */ + /* primal value of the structural variable in integer solution */ +}; + +struct GLPAIJ +{ /* constraint coefficient a[i,j] */ + GLPROW *row; + /* pointer to row, where this coefficient is placed */ + GLPCOL *col; + /* pointer to column, where this coefficient is placed */ + double val; + /* numeric (non-zero) value of this coefficient */ + GLPAIJ *r_prev; + /* pointer to previous coefficient in the same row */ + GLPAIJ *r_next; + /* pointer to next coefficient in the same row */ + GLPAIJ *c_prev; + /* pointer to previous coefficient in the same column */ + GLPAIJ *c_next; + /* pointer to next coefficient in the same column */ +}; + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/proxy/main.c b/resources/3rdparty/glpk-4.53/src/proxy/main.c new file mode 100644 index 000000000..a7d1e2b87 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/proxy/main.c @@ -0,0 +1,87 @@ +/* Last update: 08-May-2013 */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "glpk.h" +#include "proxy.h" + +/**********************************************************************/ +int main(int argc, char **argv) +/**********************************************************************/ +{ + glp_prob *lp; + int ncols, status; + double *initsol, zstar, *xstar; + + /* check arguments */ + if ( (argc == 1) || (argc > 3) ) { + printf("ERROR: Usage: ts <instance> <(possibly) xml initsols>\n" + ); + exit(1); + } + + /* creating the problem */ + lp = glp_create_prob(); + glp_set_prob_name(lp, "Proxy"); + + /* reading the problem */ + glp_term_out(GLP_OFF); +#if 0 /* by mao */ + status = glp_read_lp(lp, NULL, argv[1]); +#else + status = glp_read_mps(lp, GLP_MPS_FILE, NULL, argv[1]); +#endif + glp_term_out(GLP_ON); + if ( status ) { + printf("Problem %s does not exist!!!, status %d\n", + argv[1], status); + exit(1); + } + + ncols = glp_get_num_cols(lp); + + initsol = (double *) calloc(ncols+1, sizeof(double)); + + if (argc == 3) { + FILE *fp=fopen(argv[2],"r"); + char tmp[256]={0x0}; + int counter = 1; + while(fp!=NULL && fgets(tmp, sizeof(tmp),fp)!=NULL) + { + char *valini = strstr(tmp, "value"); + if (valini!=NULL){ + int num; + double dnum; + valini +=7; + sscanf(valini, "%d%*s",&num); + dnum = (double)num; + initsol[counter] = dnum; + counter++; + } + } + fclose(fp); + } + + xstar = (double *) calloc(ncols+1, sizeof(double)); + + if (argc == 3) { + status = proxy(lp, &zstar, xstar, initsol, 0.0, 0, 1); + } + else { + status = proxy(lp, &zstar, xstar, NULL, 0.0, 0, 1); + } + + printf("Status = %d; ZSTAR = %f\n",status,zstar); + /* + int i; + for (i=1; i< ncols+1; i++) { + printf("XSTAR[%d] = %f\n",i, xstar[i]); + } + */ + + glp_delete_prob(lp); + + return 0; +} diff --git a/resources/3rdparty/glpk-4.53/src/proxy/proxy.c b/resources/3rdparty/glpk-4.53/src/proxy/proxy.c new file mode 100644 index 000000000..31502a7f7 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/proxy/proxy.c @@ -0,0 +1,1061 @@ +/* proxy.c (proximity search heuristic algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Author: Giorgio Sartor <0gioker0@gmail.com>. +* +* Copyright (C) 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +* +************************************************************************ +* +* THIS CODE IS AN IMPLEMENTATION OF THE ALGORITHM PROPOSED IN +* +* M. Fischetti, M. Monaci, +* "Proximity Search for 0-1 Mixed-Integer Convex Programming" +* Technical Report DEI, University of Padua, March 2013. +* +* AVAILABLE AT +* http://www.dei.unipd.it/~fisch/papers/proximity_search.pdf +* +* THE CODE HAS BEEN WRITTEN BY GIORGIO SARTOR, " 0gioker0@gmail.com " +* +* BASIC IDEA: +* +* The initial feasible solution x_tilde is defined. This initial +* solution can be found by an ad-hoc heuristic and proxy can be used to +* refine it by exploiting an underlying MIP model whose solution from +* scratch turned out to be problematic. Otherwise, x_tilde can be found +* by running the GLPK mip solver until a first feasible solution is +* found, setting a conservative time limit of 10 minutes (by default). +* Time limit can be modified passing variable tlim [ms]. +* +* Then the cutoff tolerance "delta" is defined. The default tolerance +* is 1% of the last feasible solution obj value--rounded to integer if +* all the variables and obj coefficients are integer. +* +* Next, the objective function c' x is replaced by the Hamming distance +* between x (the actual obj coefficients) and x_tilde (the given +* solution). Distance is only computed wrt the binary variables. +* +* The GLPK solver is then invoked to hopefully find a new incumbent +* x_star with cost c' x_star <= c' x_tilde - delta. A crucial property +* here is that the root-node solution of the LP relaxation is expected +* to be not too different from x_tilde, as this latter solution would +* be optimal without the cutoff constraint, that for a small delta can +* typically be fulfilled with just local adjustments. +* +* If no new solution x_star is found within the time limit the +* algorithm stops. Of course, if the MIP solver proved infeasibility +* for the given delta, we have that c' x_tilde - delta is a valid lower +* bound (in case of minimazation) on the optimal value of the original +* MIP. +* +* The new solution x_star, if any, is possibly improved by solving a +* simplified problem (refinement) where all binary variables have been +* fixed to their value in x_star so as to find the best solution within +* the neighborhood. +* +* Finally, the approach is reapplied on x_star (that replaces x_tilde) +* so as to recenter the distance Hamming function and by modifying the +* cutoff tolerance delta. +* +* In this way, there will be a series of hopefully not-too-difficult +* sub-MIPs to solve, each leading to an improvement of the incumbent. +* More aggressive policies on the definition of tolerance delta can +* lead to a better performance, but would require an ad-hoc tuning. +* +************************************************************************ +* +* int proxy(glp_prob *lp, double *zstar, double *xstar, +* const double[] initsol, double rel_impr, int tlim, +* int verbose) +* +* lp : GLPK problem pointer to a MIP with binary variables +* +* zstar : the value of objective function of the best solution found +* +* xstar : best solution with components xstar[1],...,xstar[ncols] +* +* initsol : pointer to a initial feasible solution, see +* glp_ios_heur_sol +* If initsol = NULL, the procedure finds the first solution +* by itself. +* +* rel_impr : minimum relative obj improvement to be achieved at each +* internal step; if <= 0.0 a default value of 0.01 (1%) is +* used; for some problems (e.g., set covering with small +* integer costs) a more-conservative choice of 0.001 (0.1%) +* can lead to a better final solution; values larger than +* 0.05 (5%) are typically too aggressive and do not work +* well. +* +* tlim : time limit to find a new solution, in ms. +* If tlim = 0, it is set to its default value, 600000 ms +* +* verbose : if 1 the output is activated. If 0 only errors are +* displayed +* +* The procedure returns -1 if an error occurred, 0 otherwise (possibly, +* time limit) +* +***********************************************************************/ + +/**********************************************************************/ +/* 1. INCLUDE */ +/**********************************************************************/ + +#include "glpk.h" +#include "env.h" +#include "proxy.h" + +/**********************************************************************/ +/* 2. PARAMETERS AND CONSTANTS */ +/**********************************************************************/ + +#define TDAY 86400.0 +#define TRUE 1 +#define FALSE 0 +#define EPS 1e-6 +#define RINF 1e38 +#define MAXVAL 1e20 +#define MINVAL -1e20 +#if 0 /* by gioker */ + #define PROXY_DEBUG +#endif + +/**********************************************************************/ +/* 3. GLOBAL VARIABLES */ +/**********************************************************************/ + +struct csa { + +int integer_obj; /* TRUE if each feasible solution has an + integral cost */ +int b_vars_exist; /* TRUE if there is at least one binary + variable in the problem */ +int i_vars_exist; /* TRUE if there is at least one general + integer variable in the problem */ +const double *startsol; /* Pointer to the initial solution */ + +int *ckind; /* Store the kind of the structural variables + of the problem */ +double *clb; /* Store the lower bound on the structural + variables of the problem */ +double *cub; /* Store the upper bound on the structural + variables of the problem */ +double *true_obj; /* Store the obj coefficients of the problem */ + +int dir; /* Minimization or maximization problem */ +int ncols; /* Number of structural variables of the + problem */ + +time_t GLOtstart; /* starting time of the algorithm */ + +glp_prob *lp_ref; /* glp problem for refining only*/ + +}; + +/**********************************************************************/ +/* 4. FUNCTIONS PROTOTYPES */ +/**********************************************************************/ + +static void callback(glp_tree *tree, void *info); +static void get_info(struct csa *csa, glp_prob *lp); +static int is_integer(struct csa *csa); +static void check_integrality(struct csa *csa); +static int check_ref(struct csa *csa, glp_prob *lp, double *xref); +static double second(void); +static int add_cutoff(struct csa *csa, glp_prob *lp); +static void get_sol(struct csa *csa, glp_prob *lp, double *xstar); +static double elapsed_time(struct csa *csa); +static void redefine_obj(glp_prob *lp, double *xtilde, int ncols, + int *ckind, double *clb, double *cub); +static double update_cutoff(struct csa *csa, glp_prob *lp, + double zstar, int index, double rel_impr); +static double compute_delta(struct csa *csa, double z, + double rel_impr); +static double objval(int ncols, double *x, double *true_obj); +static void array_copy(int begin, int end, double *source, + double *destination); +static int do_refine(struct csa *csa, glp_prob *lp_ref, int ncols, + int *ckind, double *xref, int *tlim, int tref_lim, + int verbose); +static void deallocate(struct csa *csa, int refine); + +/**********************************************************************/ +/* 5. FUNCTIONS */ +/**********************************************************************/ + +int proxy(glp_prob *lp, double *zfinal, double *xfinal, + const double initsol[], double rel_impr, int tlim, + int verbose) + +{ struct csa csa_, *csa = &csa_; + glp_iocp parm; + glp_smcp parm_lp; + size_t tpeak; + int refine, tref_lim, err, cutoff_row, niter, status, i, tout; + double *xref, *xstar, zstar, tela, cutoff, zz; + + memset(csa, 0, sizeof(struct csa)); + + + /********** **********/ + /********** RETRIEVING PROBLEM INFO **********/ + /********** **********/ + + /* getting problem direction (min or max) */ + csa->dir = glp_get_obj_dir(lp); + + /* getting number of variables */ + csa->ncols = glp_get_num_cols(lp); + + /* getting kind, bounds and obj coefficient of each variable + information is stored in ckind, cub, clb, true_obj */ + get_info(csa, lp); + + /* checking if the objective function is always integral */ + check_integrality(csa); + + /* Proximity search cannot be used if there are no binary + variables */ + if (csa->b_vars_exist == FALSE) { + if (verbose) { + xprintf("The problem has not binary variables. Proximity se" + "arch cannot be used.\n"); + } + tfree(csa->ckind); + tfree(csa->clb); + tfree(csa->cub); + tfree(csa->true_obj); + return -1; + } + + /* checking if the problem needs refinement, i.e., not all + variables are binary. If so, the routine creates a copy of the + lp problem named lp_ref and initializes the solution xref to + zero. */ + xref = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(xref, 0, sizeof(double)*(csa->ncols+1)); +#endif + refine = check_ref(csa, lp, xref); +#ifdef PROXY_DEBUG + xprintf("REFINE = %d\n",refine); +#endif + + /* Initializing the solution */ + xstar = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(xstar, 0, sizeof(double)*(csa->ncols+1)); +#endif + + /********** **********/ + /********** FINDING FIRST SOLUTION **********/ + /********** **********/ + + if (verbose) { + xprintf("Applying PROXY heuristic...\n"); + } + + /* get the initial time */ + csa->GLOtstart = second(); + + /* setting the optimization parameters */ + glp_init_iocp(&parm); + glp_init_smcp(&parm_lp); +#if 0 /* by gioker */ + /* Preprocessing should be disabled because the mip passed + to proxy is already preprocessed */ + parm.presolve = GLP_ON; +#endif +#if 1 /* by mao */ + /* best projection backtracking seems to be more efficient to find + any integer feasible solution */ + parm.bt_tech = GLP_BT_BPH; +#endif + + /* Setting the default value of the minimum relative improvement + to 1% */ + if ( rel_impr <= 0.0 ) { + rel_impr = 0.01; + } + + /* Setting the default value of time limit to 10 minutes */ + if (tlim <= 0) { + tlim = INT_MAX; + } + if (verbose) { + xprintf("Proxy's time limit set to %d seconds.\n",tlim/1000); + xprintf("Proxy's relative improvement " + "set to %2.2lf %c.\n",rel_impr*100,37); + } + + parm_lp.tm_lim = tlim; + + parm.mip_gap = 9999999.9; /* to stop the optimization at the first + feasible solution found */ + + /* finding the first solution */ + if (verbose) { + xprintf("Searching for a feasible solution...\n"); + } + + /* verifying the existence of an input starting solution */ + if (initsol != NULL) { + csa->startsol = initsol; + parm.cb_func = callback; + parm.cb_info = csa; + if (verbose) { + xprintf("Input solution found.\n"); + } + } + + tout = glp_term_out(GLP_OFF); + err = glp_simplex(lp,&parm_lp); + glp_term_out(tout); + + status = glp_get_status(lp); + + if (status != GLP_OPT) { + if (verbose) { + xprintf("Proxy heuristic terminated.\n"); + } +#ifdef PROXY_DEBUG + /* For debug only */ + xprintf("GLP_SIMPLEX status = %d\n",status); + xprintf("GLP_SIMPLEX error code = %d\n",err); +#endif + tfree(xref); + tfree(xstar); + deallocate(csa, refine); + return -1; + } + + tela = elapsed_time(csa); + if (tlim-tela*1000 <= 0) { + if (verbose) { + xprintf("Time limit exceeded. Proxy could not " + "find optimal solution to LP relaxation.\n"); + xprintf("Proxy heuristic aborted.\n"); + } + tfree(xref); + tfree(xstar); + deallocate(csa, refine); + return -1; + } + + parm.tm_lim = tlim - tela*1000; + tref_lim = (tlim - tela *1000) / 20; + + tout = glp_term_out(GLP_OFF); + err = glp_intopt(lp, &parm); + glp_term_out(tout); + + status = glp_mip_status(lp); + + /***** If no solution was found *****/ + + if (status == GLP_NOFEAS || status == GLP_UNDEF) { + if (err == GLP_ETMLIM) { + if (verbose) { + xprintf("Time limit exceeded. Proxy could not " + "find an initial integer feasible solution.\n"); + xprintf("Proxy heuristic aborted.\n"); + } + } + else { + if (verbose) { + xprintf("Proxy could not " + "find an initial integer feasible solution.\n"); + xprintf("Proxy heuristic aborted.\n"); + } + } + tfree(xref); + tfree(xstar); + deallocate(csa, refine); + return -1; + } + + /* getting the first solution and its value */ + get_sol(csa, lp,xstar); + zstar = glp_mip_obj_val(lp); + + if (verbose) { + xprintf(">>>>> first solution = %e;\n", zstar); + } + + /* If a feasible solution was found but the time limit is + exceeded */ + if (err == GLP_ETMLIM) { + if (verbose) { + xprintf("Time limit exceeded. Proxy heuristic terminated.\n"); + } + goto done; + } + + tela = elapsed_time(csa); + tpeak = 0; + glp_mem_usage(NULL, NULL, NULL, &tpeak); + if (verbose) { + xprintf("Time used: %3.1lf secs. Memory used: %2.1lf Mb\n", + tela,(double)tpeak/1048576); + xprintf("Starting proximity search...\n"); + } + + /********** **********/ + /********** PREPARING THE PROBLEM FOR PROXY **********/ + /********** **********/ + + /* adding a dummy cutoff constraint */ + cutoff_row = add_cutoff(csa, lp); + + /* proximity search needs minimization direction + even if the problem is a maximization one */ + if (csa->dir == GLP_MAX) { + glp_set_obj_dir(lp, GLP_MIN); + } + + /********** **********/ + /********** STARTING PROXIMITY SEARCH **********/ + /********** **********/ + + + niter = 0; + + while (TRUE) { + niter++; + + /********** CHANGING THE OBJ FUNCTION **********/ + + redefine_obj(lp,xstar, csa->ncols, csa->ckind, csa->clb, + csa->cub); + + /********** UPDATING THE CUTOFF CONSTRAINT **********/ + + cutoff = update_cutoff(csa, lp,zstar, cutoff_row, rel_impr); + +#ifdef PROXY_DEBUG + xprintf("TRUE_OBJ[0] = %f\n",csa->true_obj[0]); + xprintf("ZSTAR = %f\n",zstar); + xprintf("CUTOFF = %f\n",cutoff); +#endif + + /********** SEARCHING FOR A BETTER SOLUTION **********/ + + tela = elapsed_time(csa); + if (tlim-tela*1000 <= 0) { + if (verbose) { + xprintf("Time limit exceeded. Proxy heuristic " + "terminated.\n"); + } + goto done; + } +#ifdef PROXY_DEBUG + xprintf("TELA = %3.1lf\n",tela*1000); + xprintf("TLIM = %3.1lf\n",tlim - tela*1000); +#endif + parm_lp.tm_lim = tlim -tela*1000; + + tout = glp_term_out(GLP_OFF); + err = glp_simplex(lp,&parm_lp); + glp_term_out(tout); + + status = glp_get_status(lp); + + if (status != GLP_OPT) { + if (status == GLP_NOFEAS) { + if (verbose) { + xprintf("Bound exceeded = %f. ",cutoff); + } + } + if (verbose) { + xprintf("Proxy heuristic terminated.\n"); + } +#ifdef PROXY_DEBUG + xprintf("GLP_SIMPLEX status = %d\n",status); + xprintf("GLP_SIMPLEX error code = %d\n",err); +#endif + goto done; + } + + tela = elapsed_time(csa); + if (tlim-tela*1000 <= 0) { + if (verbose) { + xprintf("Time limit exceeded. Proxy heuristic " + "terminated.\n"); + } + goto done; + } + parm.tm_lim = tlim - tela*1000; + parm.cb_func = NULL; +#if 0 /* by gioker */ + /* Preprocessing should be disabled because the mip passed + to proxy is already preprocessed */ + parm.presolve = GLP_ON; +#endif + tout = glp_term_out(GLP_OFF); + err = glp_intopt(lp, &parm); + glp_term_out(tout); + + /********** MANAGEMENT OF THE SOLUTION **********/ + + status = glp_mip_status(lp); + + /***** No feasible solutions *****/ + + if (status == GLP_NOFEAS) { + if (verbose) { + xprintf("Bound exceeded = %f. Proxy heuristic " + "terminated.\n",cutoff); + } + goto done; + } + + /***** Undefined solution *****/ + + if (status == GLP_UNDEF) { + if (err == GLP_ETMLIM) { + if (verbose) { + xprintf("Time limit exceeded. Proxy heuristic " + "terminated.\n"); + } + } + else { + if (verbose) { + xprintf("Proxy terminated unexpectedly.\n"); +#ifdef PROXY_DEBUG + xprintf("GLP_INTOPT error code = %d\n",err); +#endif + } + } + goto done; + } + + /***** Feasible solution *****/ + + if ((status == GLP_FEAS) || (status == GLP_OPT)) { + + /* getting the solution and computing its value */ + get_sol(csa, lp,xstar); + zz = objval(csa->ncols, xstar, csa->true_obj); + + /* Comparing the incumbent solution with the current best + one */ +#ifdef PROXY_DEBUG + xprintf("ZZ = %f\n",zz); + xprintf("ZSTAR = %f\n",zstar); + xprintf("REFINE = %d\n",refine); +#endif + if (((zz<zstar) && (csa->dir == GLP_MIN)) || + ((zz>zstar) && (csa->dir == GLP_MAX))) { + + /* refining (possibly) the solution */ + if (refine) { + + /* copying the incumbent solution in the refinement + one */ + array_copy(1, csa->ncols +1, xstar, xref); + err = do_refine(csa, csa->lp_ref, csa->ncols, + csa->ckind, xref, &tlim, tref_lim, verbose); + if (!err) { + double zref = objval(csa->ncols, xref, + csa->true_obj); + if (((zref<zz) && (csa->dir == GLP_MIN)) || + ((zref>zz) && (csa->dir == GLP_MAX))) { + zz = zref; + /* copying the refinement solution in the + incumbent one */ + array_copy(1, csa->ncols +1, xref, xstar); + } + } + } + zstar = zz; + tela = elapsed_time(csa); + if (verbose) { + xprintf(">>>>> it: %3d: mip = %e; elapsed time " + "%3.1lf sec.s\n", niter,zstar,tela); + } + } + } + } + +done: + tela = elapsed_time(csa); + glp_mem_usage(NULL, NULL, NULL, &tpeak); + if (verbose) { + xprintf("Time used: %3.1lf. Memory used: %2.1lf Mb\n", + tela,(double)tpeak/1048576); + } + + + /* Exporting solution and obj val */ + *zfinal = zstar; + + for (i=1; i < (csa->ncols + 1); i++) { + xfinal[i]=xstar[i]; + } + + /* Freeing allocated memory */ + tfree(xref); + tfree(xstar); + deallocate(csa, refine); + + return 0; +} + +/**********************************************************************/ +static void callback(glp_tree *tree, void *info){ +/**********************************************************************/ + struct csa *csa = info; + switch(glp_ios_reason(tree)) { + case GLP_IHEUR: + glp_ios_heur_sol(tree, csa->startsol); + break; + default: break; + } +} + +/**********************************************************************/ +static void get_info(struct csa *csa, glp_prob *lp) +/**********************************************************************/ +{ + int i; + + /* Storing helpful info of the problem */ + + csa->ckind = talloc(csa->ncols+1, int); +#if 0 /* by mao */ + memset(csa->ckind, 0, sizeof(int)*(csa->ncols+1)); +#endif + csa->clb = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(csa->clb, 0, sizeof(double)*(csa->ncols+1)); +#endif + csa->cub = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(csa->cub, 0, sizeof(double)*(csa->ncols+1)); +#endif + csa->true_obj = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(csa->true_obj, 0, sizeof(double)*(csa->ncols+1)); +#endif + for( i = 1 ; i < (csa->ncols + 1); i++ ) { + csa->ckind[i] = glp_get_col_kind(lp, i); + csa->clb[i] = glp_get_col_lb(lp, i); + csa->cub[i] = glp_get_col_ub(lp, i); + csa->true_obj[i] = glp_get_obj_coef(lp, i); + } + csa->true_obj[0] = glp_get_obj_coef(lp, 0); +} + +/**********************************************************************/ +static int is_integer(struct csa *csa) +/**********************************************************************/ +{ + int i; + csa->integer_obj = TRUE; + for ( i = 1; i < (csa->ncols + 1); i++ ) { + if (fabs(csa->true_obj[i]) > INT_MAX ) { + csa->integer_obj = FALSE; + } + if (fabs(csa->true_obj[i]) <= INT_MAX) { + double tmp, rem; + if (fabs(csa->true_obj[i]) - floor(fabs(csa->true_obj[i])) + < 0.5) { + tmp = floor(fabs(csa->true_obj[i])); + } + else { + tmp = ceil(fabs(csa->true_obj[i])); + } + rem = fabs(csa->true_obj[i]) - tmp; + rem = fabs(rem); + if (rem > EPS) { + csa->integer_obj = FALSE; + } + + } + } + return csa->integer_obj; +} + +/**********************************************************************/ +static void check_integrality(struct csa *csa) +/**********************************************************************/ +{ + /* + Checking if the problem has binary, integer or continuos variables. + integer_obj is TRUE if the problem has no continuous variables + and all the obj coefficients are integer (and < INT_MAX). + */ + + int i; + csa->integer_obj = is_integer(csa); + csa->b_vars_exist = FALSE; + csa->i_vars_exist = FALSE; + for ( i = 1; i < (csa->ncols + 1); i++ ) { + if ( csa->ckind[i] == GLP_IV ){ + csa->i_vars_exist = TRUE; + continue; + } + if ( csa->ckind[i] == GLP_BV ){ + csa->b_vars_exist =TRUE; + continue; + } + csa->integer_obj = FALSE; + } +} + +/**********************************************************************/ +static int check_ref(struct csa *csa, glp_prob *lp, double *xref) +/**********************************************************************/ +{ + /* + checking if the problem has continuos or integer variables. If so, + refinement is prepared. + */ + int refine = FALSE; + int i; + for ( i = 1; i < (csa->ncols + 1); i++ ) { + if ( csa->ckind[i] != GLP_BV) { + refine = TRUE; + break; + } + } + + /* possibly creating a mip clone for refinement only */ + if ( refine ) { + csa->lp_ref = glp_create_prob(); + glp_copy_prob(csa->lp_ref, lp, GLP_ON); + } + + return refine; +} + +/**********************************************************************/ +static double second(void) +/**********************************************************************/ +{ +#if 0 /* by mao */ + return ((double)clock()/(double)CLOCKS_PER_SEC); +#else + return xtime() / 1000.0; +#endif +} + +/**********************************************************************/ +static int add_cutoff(struct csa *csa, glp_prob *lp) +/**********************************************************************/ +{ + /* + Adding a cutoff constraint to set an upper bound (in case of + minimaztion) on the obj value of the next solution, i.e., the next + value of the true obj function that we would like to find + */ + + /* store non-zero coefficients in the objective function */ + int *obj_index = talloc(csa->ncols+1, int); +#if 0 /* by mao */ + memset(obj_index, 0, sizeof(int)*(csa->ncols+1)); +#endif + double *obj_value = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(obj_value, 0, sizeof(double)*(csa->ncols+1)); +#endif + int obj_nzcnt = 0; + int i, irow; + const char *rowname; + for ( i = 1; i < (csa->ncols + 1); i++ ) { + if ( fabs(csa->true_obj[i]) > EPS ) { + obj_nzcnt++; + obj_index[obj_nzcnt] = i; + obj_value[obj_nzcnt] = csa->true_obj[i]; + } + } + + irow = glp_add_rows(lp, 1); + rowname = "Cutoff"; + glp_set_row_name(lp, irow, rowname); + if (csa->dir == GLP_MIN) { + /* minimization problem */ + glp_set_row_bnds(lp, irow, GLP_UP, MAXVAL, MAXVAL); + } + else { + /* maximization problem */ + glp_set_row_bnds(lp, irow, GLP_LO, MINVAL, MINVAL); + } + + glp_set_mat_row(lp, irow, obj_nzcnt, obj_index, obj_value); + + tfree(obj_index); + tfree(obj_value); + + return irow; +} + +/**********************************************************************/ +static void get_sol(struct csa *csa, glp_prob *lp, double *xstar) +/**********************************************************************/ +{ + /* Retrieving and storing the coefficients of the solution */ + + int i; + for (i = 1; i < (csa->ncols +1); i++) { + xstar[i] = glp_mip_col_val(lp, i); + } +} + +/**********************************************************************/ +static double elapsed_time(struct csa *csa) +/**********************************************************************/ +{ + double tela = second() - csa->GLOtstart; + if ( tela < 0 ) tela += TDAY; + return(tela); +} + +/**********************************************************************/ +static void redefine_obj(glp_prob *lp, double *xtilde, int ncols, + int *ckind, double *clb, double *cub) +/**********************************************************************/ + +/* + Redefine the lp objective function obj as the distance-to-integrality + (Hamming distance) from xtilde (the incumbent feasible solution), wrt + to binary vars only + */ + +{ + int j; + double *delta = talloc(ncols+1, double); +#if 0 /* by mao */ + memset(delta, 0, sizeof(double)*(ncols+1)); +#endif + + for ( j = 1; j < (ncols +1); j++ ) { + delta[j] = 0.0; + /* skip continuous variables */ + if ( ckind[j] == GLP_CV ) continue; + + /* skip integer variables that have been fixed */ + if ( cub[j]-clb[j] < 0.5 ) continue; + + /* binary variable */ + if ( ckind[j] == GLP_BV ) { + if ( xtilde[j] > 0.5 ) { + delta[j] = -1.0; + } + else { + delta[j] = 1.0; + } + } + } + + /* changing the obj coeff. for all variables, including continuous + ones */ + for ( j = 1; j < (ncols +1); j++ ) { + glp_set_obj_coef(lp, j, delta[j]); + } + glp_set_obj_coef(lp, 0, 0.0); + + tfree(delta); +} + +/**********************************************************************/ +static double update_cutoff(struct csa *csa, glp_prob *lp, + double zstar, int cutoff_row, + double rel_impr) +/**********************************************************************/ +{ + /* + Updating the cutoff constraint with the value we would like to + find during the next optimization + */ + double cutoff; + zstar -= csa->true_obj[0]; + if (csa->dir == GLP_MIN) { + cutoff = zstar - compute_delta(csa, zstar, rel_impr); + glp_set_row_bnds(lp, cutoff_row, GLP_UP, cutoff, cutoff); + } + else { + cutoff = zstar + compute_delta(csa, zstar, rel_impr); + glp_set_row_bnds(lp, cutoff_row, GLP_LO, cutoff, cutoff); + } + + return cutoff; +} + +/**********************************************************************/ +static double compute_delta(struct csa *csa, double z, double rel_impr) +/**********************************************************************/ +{ + /* Computing the offset for the next best solution */ + + double delta = rel_impr * fabs(z); + if ( csa->integer_obj ) delta = ceil(delta); + + return(delta); +} + +/**********************************************************************/ +static double objval(int ncols, double *x, double *true_obj) +/**********************************************************************/ +{ + /* Computing the true cost of x (using the original obj coeff.s) */ + + int j; + double z = 0.0; + for ( j = 1; j < (ncols +1); j++ ) { + z += x[j] * true_obj[j]; + } + return z + true_obj[0]; +} + +/**********************************************************************/ +static void array_copy(int begin, int end, double *source, + double *destination) +/**********************************************************************/ +{ + int i; + for (i = begin; i < end; i++) { + destination[i] = source[i]; + } +} +/**********************************************************************/ +static int do_refine(struct csa *csa, glp_prob *lp_ref, int ncols, + int *ckind, double *xref, int *tlim, int tref_lim, + int verbose) +/**********************************************************************/ +{ + /* + Refinement is applied when the variables of the problem are not + all binary. Binary variables are fixed to their value and + remaining ones are optimized. If there are only continuos + variables (in addition to those binary) the problem becomes just + an LP. Otherwise, it remains a MIP but of smaller size. + */ + + int j, tout; + double refineStart = second(); + double val, tela, tlimit; + + if ( glp_get_num_cols(lp_ref) != ncols ) { + if (verbose) { + xprintf("Error in Proxy refinement: "); + xprintf("wrong number of columns (%d vs %d).\n", + ncols, glp_get_num_cols(lp_ref)); + } + return 1; + } + + val = -1.0; + + /* fixing all binary variables to their current value in xref */ + for ( j = 1; j < (ncols + 1); j++ ) { + if ( ckind[j] == GLP_BV ) { + val = 0.0; + if ( xref[j] > 0.5 ) val = 1.0; + glp_set_col_bnds(lp_ref, j, GLP_FX, val, val); + } + } + + /* re-optimizing (refining) if some bound has been changed */ + if ( val > -1.0 ) { + glp_iocp parm_ref; + glp_smcp parm_ref_lp; + int err, status; + + glp_init_iocp(&parm_ref); + parm_ref.presolve = GLP_ON; + glp_init_smcp(&parm_ref_lp); + /* + If there are no general integer variable the problem becomes + an LP (after fixing the binary variables) and can be solved + quickly. Otherwise the problem is still a MIP problem and a + timelimit has to be set. + */ + parm_ref.tm_lim = tref_lim; + if (parm_ref.tm_lim > *tlim) { + parm_ref.tm_lim = *tlim; + } + parm_ref_lp.tm_lim = parm_ref.tm_lim; +#ifdef PROXY_DEBUG + xprintf("***** REFINING *****\n"); +#endif + tout = glp_term_out(GLP_OFF); + if (csa->i_vars_exist == TRUE) { + err = glp_intopt(lp_ref, &parm_ref); + } + else { + err = glp_simplex(lp_ref, &parm_ref_lp); + } + glp_term_out(tout); + + if (csa->i_vars_exist == TRUE) { + status = glp_mip_status(lp_ref); + } + else { + status = glp_get_status(lp_ref); + } +#ifdef PROXY_DEBUG + xprintf("STATUS REFINING = %d\n",status); +#endif + if (status == GLP_UNDEF) { + if (err == GLP_ETMLIM) { +#ifdef PROXY_DEBUG + xprintf("Time limit exceeded on Proxy refining.\n"); +#endif + return 1; + } + } + for( j = 1 ; j < (ncols + 1); j++ ){ + if (ckind[j] != GLP_BV) { + if (csa->i_vars_exist == TRUE) { + xref[j] = glp_mip_col_val(lp_ref, j); + } + else{ + xref[j] = glp_get_col_prim(lp_ref, j); + } + } + } + } + tela = second() - refineStart; +#ifdef PROXY_DEBUG + xprintf("REFINE TELA = %3.1lf\n",tela*1000); +#endif + return 0; +} +/**********************************************************************/ +static void deallocate(struct csa *csa, int refine) +/**********************************************************************/ +{ + /* Deallocating routine */ + + if (refine) { + glp_delete_prob(csa->lp_ref); + } + + tfree(csa->ckind); + tfree(csa->clb); + tfree(csa->cub); + tfree(csa->true_obj); + +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/proxy/proxy.h b/resources/3rdparty/glpk-4.53/src/proxy/proxy.h new file mode 100644 index 000000000..a91e36f2d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/proxy/proxy.h @@ -0,0 +1,36 @@ +/* proxy.h (proximity search heuristic algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Author: Giorgio Sartor <0gioker0@gmail.com>. +* +* Copyright (C) 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: <mao@gnu.org>. +* +* GLPK 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 3 of the License, or +* (at your option) any later version. +* +* GLPK 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 GLPK. If not, see <http://www.gnu.org/licenses/>. +***********************************************************************/ + +#ifndef PROXY_H +#define PROXY_H + +#define proxy _glp_proxy +int proxy(glp_prob *lp, double *zstar, double *xstar, + const double initsol[], double rel_impr, int tlim, + int verbose); + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/proxy/proxy1.c b/resources/3rdparty/glpk-4.53/src/proxy/proxy1.c new file mode 100644 index 000000000..ce96d9e80 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/proxy/proxy1.c @@ -0,0 +1,39 @@ +/* proxy1.c */ + +/* (reserved for copyright notice) */ + +#include "env.h" +#include "glpios.h" +#include "proxy.h" + +void ios_proxy_heur(glp_tree *T) +{ glp_prob *prob; + int j, status; + double *xstar, zstar; + /* this heuristic is applied only once on the root level */ + if (!(T->curr->level == 0 && T->curr->solved == 1)) + goto done; + prob = glp_create_prob(); + glp_copy_prob(prob, T->mip, 0); + xstar = xcalloc(1+prob->n, sizeof(double)); + for (j = 1; j <= prob->n; j++) + xstar[j] = 0.0; + if (T->mip->mip_stat != GLP_FEAS) + status = proxy(prob, &zstar, xstar, NULL, 0.0, + T->parm->ps_tm_lim, 1); + else + { double *xinit = xcalloc(1+prob->n, sizeof(double)); + for (j = 1; j <= prob->n; j++) + xinit[j] = T->mip->col[j]->mipx; + status = proxy(prob, &zstar, xstar, xinit, 0.0, + T->parm->ps_tm_lim, 1); + xfree(xinit); + } + if (status == 0) + glp_ios_heur_sol(T, xstar); + xfree(xstar); + glp_delete_prob(prob); +done: return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/zlib/README b/resources/3rdparty/glpk-4.53/src/zlib/README new file mode 100644 index 000000000..2796312f1 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/README @@ -0,0 +1,45 @@ +NOTE: Files in this subdirectory are NOT part of the GLPK package, but + are used with GLPK. + + The original code was modified according to GLPK requirements by + Andrew Makhorin <mao@gnu.org>. + + The following files were rewritten: + gzguts.h, zconf.h, zutil.h. + + The following files were added: + zio.h, zio.c. + + Other files were not changed. +************************************************************************ +zlib general purpose compression library +version 1.2.5, April 19th, 2010 + +Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would + be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + +The data format used by the zlib library is described by RFCs (Request +for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate +format) and rfc1952.txt (gzip format). diff --git a/resources/3rdparty/glpk-4.53/src/zlib/adler32.c b/resources/3rdparty/glpk-4.53/src/zlib/adler32.c new file mode 100644 index 000000000..65ad6a5ad --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/adler32.c @@ -0,0 +1,169 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2007 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#define local static + +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/compress.c b/resources/3rdparty/glpk-4.53/src/zlib/compress.c new file mode 100644 index 000000000..ea4dfbe9d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/compress.c @@ -0,0 +1,80 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/crc32.c b/resources/3rdparty/glpk-4.53/src/zlib/crc32.c new file mode 100644 index 000000000..91be372d2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include <stdio.h> +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include <limits.h> +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/crc32.h b/resources/3rdparty/glpk-4.53/src/zlib/crc32.h new file mode 100644 index 000000000..8053b6117 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/resources/3rdparty/glpk-4.53/src/zlib/deflate.c b/resources/3rdparty/glpk-4.53/src/zlib/deflate.c new file mode 100644 index 000000000..5c4022f3d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/deflate.c @@ -0,0 +1,1834 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > s->w_size) { + length = s->w_size; + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if ((strategy != s->strategy || func != configuration_table[level].func) && + strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_BLOCK); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong complen, wraplen; + Bytef *str; + + /* conservative upper bound for compressed data */ + complen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (strm == Z_NULL || strm->state == Z_NULL) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = 6 + (s->strstart ? 4 : 0); + break; + case 2: /* gzip wrapper */ + wraplen = 18; + if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + if (s->gzhead->extra != Z_NULL) + wraplen += 2 + s->gzhead->extra_len; + str = s->gzhead->name; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + str = s->gzhead->comment; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + if (s->gzhead->hcrc) + wraplen += 2; + } + break; + default: /* for compiler happiness */ + wraplen = 6; + } + + /* if not default parameters, return conservative bound */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return complen + wraplen; + + /* default settings: return tight bound for that case */ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_BLOCK || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + (s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush)); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0L; + } + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ + +#else /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for FASTEST only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#endif /* FASTEST */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (last)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt prev; /* byte at distance one to match */ + Bytef *scan, *strend; /* scan goes up to strend for length of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s->match_length = 0; + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + s->match_length = MAX_MATCH - (int)(strend - scan); + if (s->match_length > s->lookahead) + s->match_length = s->lookahead; + } + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, s->match_length); + + _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + s->strstart += s->match_length; + s->match_length = 0; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +local block_state deflate_huff(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s->match_length = 0; + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/deflate.h b/resources/3rdparty/glpk-4.53/src/zlib/deflate.h new file mode 100644 index 000000000..cbf0d1ea5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/deflate.h @@ -0,0 +1,342 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/resources/3rdparty/glpk-4.53/src/zlib/gzclose.c b/resources/3rdparty/glpk-4.53/src/zlib/gzclose.c new file mode 100644 index 000000000..caeb99a31 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/gzclose.c @@ -0,0 +1,25 @@ +/* gzclose.c -- zlib gzclose() function + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* gzclose() is in a separate file so that it is linked in only if it is used. + That way the other gzclose functions can be used instead to avoid linking in + unneeded compression or decompression routines. */ +int ZEXPORT gzclose(file) + gzFile file; +{ +#ifndef NO_GZCOMPRESS + gz_statep state; + + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); +#else + return gzclose_r(file); +#endif +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/gzguts.h b/resources/3rdparty/glpk-4.53/src/zlib/gzguts.h new file mode 100644 index 000000000..9d01ac7b7 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/gzguts.h @@ -0,0 +1,74 @@ +/* gzguts.h (zlib internal header definitions for gz* operations) */ + +/* Modified by Andrew Makhorin <mao@gnu.org>, April 2011 */ + +/* Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in + * zlib.h */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. */ + +#ifndef GZGUTS_H +#define GZGUTS_H + +#define ZLIB_INTERNAL + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "zio.h" +#include "zlib.h" + +#define local static + +#define zstrerror() strerror(errno) + +#define GZBUFSIZE 8192 + +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 + +#define LOOK 0 +#define COPY 1 +#define GZIP 2 + +typedef struct +{ int mode; + int fd; + char *path; + z_off64_t pos; + unsigned size; + unsigned want; + unsigned char *in; + unsigned char *out; + unsigned char *next; + unsigned have; + int eof; + z_off64_t start; + z_off64_t raw; + int how; + int direct; + int level; + int strategy; + z_off64_t skip; + int seek; + int err; + char *msg; + z_stream strm; +} gz_state; + +typedef gz_state *gz_statep; + +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); + +#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/zlib/gzlib.c b/resources/3rdparty/glpk-4.53/src/zlib/gzlib.c new file mode 100644 index 000000000..603e60ed5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/gzlib.c @@ -0,0 +1,537 @@ +/* gzlib.c -- zlib functions common to reading and writing gzip files + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define LSEEK lseek64 +#else +# define LSEEK lseek +#endif + +/* Local functions */ +local void gz_reset OF((gz_statep)); +local gzFile gz_open OF((const char *, int, const char *)); + +#if defined UNDER_CE + +/* Map the Windows error number in ERROR to a locale-dependent error message + string and return a pointer to it. Typically, the values for ERROR come + from GetLastError. + + The string pointed to shall not be modified by the application, but may be + overwritten by a subsequent call to gz_strwinerror + + The gz_strwinerror function does not change the current setting of + GetLastError. */ +char ZLIB_INTERNAL *gz_strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +#endif /* UNDER_CE */ + +/* Reset gzip file state */ +local void gz_reset(state) + gz_statep state; +{ + if (state->mode == GZ_READ) { /* for reading ... */ + state->have = 0; /* no output data available */ + state->eof = 0; /* not at end of file */ + state->how = LOOK; /* look for gzip header */ + state->direct = 1; /* default for empty file */ + } + state->seek = 0; /* no seek request pending */ + gz_error(state, Z_OK, NULL); /* clear error */ + state->pos = 0; /* no uncompressed data yet */ + state->strm.avail_in = 0; /* no input data yet */ +} + +/* Open a gzip file either by name or file descriptor. */ +local gzFile gz_open(path, fd, mode) + const char *path; + int fd; + const char *mode; +{ + gz_statep state; + + /* allocate gzFile structure to return */ + state = malloc(sizeof(gz_state)); + if (state == NULL) + return NULL; + state->size = 0; /* no buffers allocated yet */ + state->want = GZBUFSIZE; /* requested buffer size */ + state->msg = NULL; /* no error message yet */ + + /* interpret mode */ + state->mode = GZ_NONE; + state->level = Z_DEFAULT_COMPRESSION; + state->strategy = Z_DEFAULT_STRATEGY; + while (*mode) { + if (*mode >= '0' && *mode <= '9') + state->level = *mode - '0'; + else + switch (*mode) { + case 'r': + state->mode = GZ_READ; + break; +#ifndef NO_GZCOMPRESS + case 'w': + state->mode = GZ_WRITE; + break; + case 'a': + state->mode = GZ_APPEND; + break; +#endif + case '+': /* can't read and write at the same time */ + free(state); + return NULL; + case 'b': /* ignore -- will request binary anyway */ + break; + case 'f': + state->strategy = Z_FILTERED; + break; + case 'h': + state->strategy = Z_HUFFMAN_ONLY; + break; + case 'R': + state->strategy = Z_RLE; + break; + case 'F': + state->strategy = Z_FIXED; + default: /* could consider as an error, but just ignore */ + ; + } + mode++; + } + + /* must provide an "r", "w", or "a" */ + if (state->mode == GZ_NONE) { + free(state); + return NULL; + } + + /* save the path name for error messages */ + state->path = malloc(strlen(path) + 1); + if (state->path == NULL) { + free(state); + return NULL; + } + strcpy(state->path, path); + + /* open the file with the appropriate mode (or just use fd) */ + state->fd = fd != -1 ? fd : + open(path, +#ifdef O_LARGEFILE + O_LARGEFILE | +#endif +#ifdef O_BINARY + O_BINARY | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | ( + state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))), + 0666); + if (state->fd == -1) { + free(state->path); + free(state); + return NULL; + } + if (state->mode == GZ_APPEND) + state->mode = GZ_WRITE; /* simplify later checks */ + + /* save the current position for rewinding (only if reading) */ + if (state->mode == GZ_READ) { + state->start = LSEEK(state->fd, 0, SEEK_CUR); + if (state->start == -1) state->start = 0; + } + + /* initialize stream */ + gz_reset(state); + + /* return stream */ + return (gzFile)state; +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen64(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzdopen(fd, mode) + int fd; + const char *mode; +{ + char *path; /* identifier for error messages */ + gzFile gz; + + if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) + return NULL; + sprintf(path, "<fd:%d>", fd); /* for debugging */ + gz = gz_open(path, fd, mode); + free(path); + return gz; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzbuffer(file, size) + gzFile file; + unsigned size; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* make sure we haven't already allocated memory */ + if (state->size != 0) + return -1; + + /* check and set requested size */ + if (size == 0) + return -1; + state->want = size; + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzrewind(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* back up and start over */ + if (LSEEK(state->fd, state->start, SEEK_SET) == -1) + return -1; + gz_reset(state); + return 0; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzseek64(file, offset, whence) + gzFile file; + z_off64_t offset; + int whence; +{ + unsigned n; + z_off64_t ret; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* check that there's no error */ + if (state->err != Z_OK) + return -1; + + /* can only seek from start or relative to current position */ + if (whence != SEEK_SET && whence != SEEK_CUR) + return -1; + + /* normalize offset to a SEEK_CUR specification */ + if (whence == SEEK_SET) + offset -= state->pos; + else if (state->seek) + offset += state->skip; + state->seek = 0; + + /* if within raw area while reading, just go there */ + if (state->mode == GZ_READ && state->how == COPY && + state->pos + offset >= state->raw) { + ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); + if (ret == -1) + return -1; + state->have = 0; + state->eof = 0; + state->seek = 0; + gz_error(state, Z_OK, NULL); + state->strm.avail_in = 0; + state->pos += offset; + return state->pos; + } + + /* calculate skip amount, rewinding if needed for back seek when reading */ + if (offset < 0) { + if (state->mode != GZ_READ) /* writing -- can't go backwards */ + return -1; + offset += state->pos; + if (offset < 0) /* before start of file! */ + return -1; + if (gzrewind(file) == -1) /* rewind, then skip to offset */ + return -1; + } + + /* if reading, skip what's in output buffer (one less gzgetc() check) */ + if (state->mode == GZ_READ) { + n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? + (unsigned)offset : state->have; + state->have -= n; + state->next += n; + state->pos += n; + offset -= n; + } + + /* request skip (if not zero) */ + if (offset) { + state->seek = 1; + state->skip = offset; + } + return state->pos + offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzseek(file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + z_off64_t ret; + + ret = gzseek64(file, (z_off64_t)offset, whence); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gztell64(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* return position */ + return state->pos + (state->seek ? state->skip : 0); +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gztell(file) + gzFile file; +{ + z_off64_t ret; + + ret = gztell64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzoffset64(file) + gzFile file; +{ + z_off64_t offset; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* compute and return effective offset in file */ + offset = LSEEK(state->fd, 0, SEEK_CUR); + if (offset == -1) + return -1; + if (state->mode == GZ_READ) /* reading */ + offset -= state->strm.avail_in; /* don't count buffered input */ + return offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzoffset(file) + gzFile file; +{ + z_off64_t ret; + + ret = gzoffset64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzeof(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return 0; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return 0; + + /* return end-of-file state */ + return state->mode == GZ_READ ? + (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; +} + +/* -- see zlib.h -- */ +const char * ZEXPORT gzerror(file, errnum) + gzFile file; + int *errnum; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return NULL; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return NULL; + + /* return error information */ + if (errnum != NULL) + *errnum = state->err; + return state->msg == NULL ? "" : state->msg; +} + +/* -- see zlib.h -- */ +void ZEXPORT gzclearerr(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return; + + /* clear error and end-of-file */ + if (state->mode == GZ_READ) + state->eof = 0; + gz_error(state, Z_OK, NULL); +} + +/* Create an error message in allocated memory and set state->err and + state->msg accordingly. Free any previous error message already there. Do + not try to free or allocate space if the error is Z_MEM_ERROR (out of + memory). Simply save the error message as a static string. If there is an + allocation failure constructing the error message, then convert the error to + out of memory. */ +void ZLIB_INTERNAL gz_error(state, err, msg) + gz_statep state; + int err; + const char *msg; +{ + /* free previously allocated message and clear */ + if (state->msg != NULL) { + if (state->err != Z_MEM_ERROR) + free(state->msg); + state->msg = NULL; + } + + /* set error code, and if no message, then done */ + state->err = err; + if (msg == NULL) + return; + + /* for an out of memory error, save as static string */ + if (err == Z_MEM_ERROR) { + state->msg = (char *)msg; + return; + } + + /* construct error message with path */ + if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + state->err = Z_MEM_ERROR; + state->msg = (char *)"out of memory"; + return; + } + strcpy(state->msg, state->path); + strcat(state->msg, ": "); + strcat(state->msg, msg); + return; +} + +#ifndef INT_MAX +/* portably return maximum value for an int (when limits.h presumed not + available) -- we need to do this to cover cases where 2's complement not + used, since C standard permits 1's complement and sign-bit representations, + otherwise we could just use ((unsigned)-1) >> 1 */ +unsigned ZLIB_INTERNAL gz_intmax() +{ + unsigned p, q; + + p = 1; + do { + q = p; + p <<= 1; + p++; + } while (p > q); + return q >> 1; +} +#endif diff --git a/resources/3rdparty/glpk-4.53/src/zlib/gzread.c b/resources/3rdparty/glpk-4.53/src/zlib/gzread.c new file mode 100644 index 000000000..548201ab0 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/gzread.c @@ -0,0 +1,653 @@ +/* gzread.c -- zlib functions for reading gzip files + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); +local int gz_avail OF((gz_statep)); +local int gz_next4 OF((gz_statep, unsigned long *)); +local int gz_head OF((gz_statep)); +local int gz_decomp OF((gz_statep)); +local int gz_make OF((gz_statep)); +local int gz_skip OF((gz_statep, z_off64_t)); + +/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from + state->fd, and update state->eof, state->err, and state->msg as appropriate. + This function needs to loop on read(), since read() is not guaranteed to + read the number of bytes requested, depending on the type of descriptor. */ +local int gz_load(state, buf, len, have) + gz_statep state; + unsigned char *buf; + unsigned len; + unsigned *have; +{ + int ret; + + *have = 0; + do { + ret = read(state->fd, buf + *have, len - *have); + if (ret <= 0) + break; + *have += ret; + } while (*have < len); + if (ret < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (ret == 0) + state->eof = 1; + return 0; +} + +/* Load up input buffer and set eof flag if last data loaded -- return -1 on + error, 0 otherwise. Note that the eof flag is set when the end of the input + file is reached, even though there may be unused data in the buffer. Once + that data has been used, no more attempts will be made to read the file. + gz_avail() assumes that strm->avail_in == 0. */ +local int gz_avail(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + if (state->err != Z_OK) + return -1; + if (state->eof == 0) { + if (gz_load(state, state->in, state->size, + (unsigned *)&(strm->avail_in)) == -1) + return -1; + strm->next_in = state->in; + } + return 0; +} + +/* Get next byte from input, or -1 if end or error. */ +#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ + (strm->avail_in == 0 ? -1 : \ + (strm->avail_in--, *(strm->next_in)++))) + +/* Get a four-byte little-endian integer and return 0 on success and the value + in *ret. Otherwise -1 is returned and *ret is not modified. */ +local int gz_next4(state, ret) + gz_statep state; + unsigned long *ret; +{ + int ch; + unsigned long val; + z_streamp strm = &(state->strm); + + val = NEXT(); + val += (unsigned)NEXT() << 8; + val += (unsigned long)NEXT() << 16; + ch = NEXT(); + if (ch == -1) + return -1; + val += (unsigned long)ch << 24; + *ret = val; + return 0; +} + +/* Look for gzip header, set up for inflate or copy. state->have must be zero. + If this is the first time in, allocate required memory. state->how will be + left unchanged if there is no more input data available, will be set to COPY + if there is no gzip header and direct copying will be performed, or it will + be set to GZIP for decompression, and the gzip header will be skipped so + that the next available input data is the raw deflate stream. If direct + copying, then leftover input data from the input buffer will be copied to + the output buffer. In that case, all further file reads will be directly to + either the output buffer or a user buffer. If decompressing, the inflate + state and the check value will be initialized. gz_head() will return 0 on + success or -1 on failure. Failures may include read errors or gzip header + errors. */ +local int gz_head(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + int flags; + unsigned len; + + /* allocate read buffers and inflate memory */ + if (state->size == 0) { + /* allocate buffers */ + state->in = malloc(state->want); + state->out = malloc(state->want << 1); + if (state->in == NULL || state->out == NULL) { + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + state->size = state->want; + + /* allocate inflate memory */ + state->strm.zalloc = Z_NULL; + state->strm.zfree = Z_NULL; + state->strm.opaque = Z_NULL; + state->strm.avail_in = 0; + state->strm.next_in = Z_NULL; + if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ + free(state->out); + free(state->in); + state->size = 0; + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + } + + /* get some data in the input buffer */ + if (strm->avail_in == 0) { + if (gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) + return 0; + } + + /* look for the gzip magic header bytes 31 and 139 */ + if (strm->next_in[0] == 31) { + strm->avail_in--; + strm->next_in++; + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in && strm->next_in[0] == 139) { + /* we have a gzip header, woo hoo! */ + strm->avail_in--; + strm->next_in++; + + /* skip rest of header */ + if (NEXT() != 8) { /* compression method */ + gz_error(state, Z_DATA_ERROR, "unknown compression method"); + return -1; + } + flags = NEXT(); + if (flags & 0xe0) { /* reserved flag bits */ + gz_error(state, Z_DATA_ERROR, "unknown header flags set"); + return -1; + } + NEXT(); /* modification time */ + NEXT(); + NEXT(); + NEXT(); + NEXT(); /* extra flags */ + NEXT(); /* operating system */ + if (flags & 4) { /* extra field */ + len = (unsigned)NEXT(); + len += (unsigned)NEXT() << 8; + while (len--) + if (NEXT() < 0) + break; + } + if (flags & 8) /* file name */ + while (NEXT() > 0) + ; + if (flags & 16) /* comment */ + while (NEXT() > 0) + ; + if (flags & 2) { /* header crc */ + NEXT(); + NEXT(); + } + /* an unexpected end of file is not checked for here -- it will be + noticed on the first request for uncompressed data */ + + /* set up for decompression */ + inflateReset(strm); + strm->adler = crc32(0L, Z_NULL, 0); + state->how = GZIP; + state->direct = 0; + return 0; + } + else { + /* not a gzip file -- save first byte (31) and fall to raw i/o */ + state->out[0] = 31; + state->have = 1; + } + } + + /* doing raw i/o, save start of raw data for seeking, copy any leftover + input to output -- this assumes that the output buffer is larger than + the input buffer, which also assures space for gzungetc() */ + state->raw = state->pos; + state->next = state->out; + if (strm->avail_in) { + memcpy(state->next + state->have, strm->next_in, strm->avail_in); + state->have += strm->avail_in; + strm->avail_in = 0; + } + state->how = COPY; + state->direct = 1; + return 0; +} + +/* Decompress from input to the provided next_out and avail_out in the state. + If the end of the compressed data is reached, then verify the gzip trailer + check value and length (modulo 2^32). state->have and state->next are set + to point to the just decompressed data, and the crc is updated. If the + trailer is verified, state->how is reset to LOOK to look for the next gzip + stream or raw data, once state->have is depleted. Returns 0 on success, -1 + on failure. Failures may include invalid compressed data or a failed gzip + trailer verification. */ +local int gz_decomp(state) + gz_statep state; +{ + int ret; + unsigned had; + unsigned long crc, len; + z_streamp strm = &(state->strm); + + /* fill output buffer up to end of deflate stream */ + had = strm->avail_out; + do { + /* get more input for inflate() */ + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) { + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); + return -1; + } + + /* decompress and handle errors */ + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { + gz_error(state, Z_STREAM_ERROR, + "internal error: inflate stream corrupt"); + return -1; + } + if (ret == Z_MEM_ERROR) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ + gz_error(state, Z_DATA_ERROR, + strm->msg == NULL ? "compressed data error" : strm->msg); + return -1; + } + } while (strm->avail_out && ret != Z_STREAM_END); + + /* update available output and crc check value */ + state->have = had - strm->avail_out; + state->next = strm->next_out - state->have; + strm->adler = crc32(strm->adler, state->next, state->have); + + /* check gzip trailer if at end of deflate stream */ + if (ret == Z_STREAM_END) { + if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); + return -1; + } + if (crc != strm->adler) { + gz_error(state, Z_DATA_ERROR, "incorrect data check"); + return -1; + } + if (len != (strm->total_out & 0xffffffffL)) { + gz_error(state, Z_DATA_ERROR, "incorrect length check"); + return -1; + } + state->how = LOOK; /* ready for next stream, once have is 0 (leave + state->direct unchanged to remember how) */ + } + + /* good decompression */ + return 0; +} + +/* Make data and put in the output buffer. Assumes that state->have == 0. + Data is either copied from the input file or decompressed from the input + file depending on state->how. If state->how is LOOK, then a gzip header is + looked for (and skipped if found) to determine wither to copy or decompress. + Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY + or GZIP unless the end of the input file has been reached and all data has + been processed. */ +local int gz_make(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + if (state->how == LOOK) { /* look for gzip header */ + if (gz_head(state) == -1) + return -1; + if (state->have) /* got some data from gz_head() */ + return 0; + } + if (state->how == COPY) { /* straight copy */ + if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) + return -1; + state->next = state->out; + } + else if (state->how == GZIP) { /* decompress */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + return 0; +} + +/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ +local int gz_skip(state, len) + gz_statep state; + z_off64_t len; +{ + unsigned n; + + /* skip over len bytes or reach end-of-file, whichever comes first */ + while (len) + /* skip over whatever is in output buffer */ + if (state->have) { + n = GT_OFF(state->have) || (z_off64_t)state->have > len ? + (unsigned)len : state->have; + state->have -= n; + state->next += n; + state->pos += n; + len -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) + break; + + /* need more data to skip -- load up output buffer */ + else { + /* get more output, looking for header if required */ + if (gz_make(state) == -1) + return -1; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzread(file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + unsigned got, n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + return -1; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* get len bytes to buf, or less than len if at the end */ + got = 0; + do { + /* first just try copying data from the output buffer */ + if (state->have) { + n = state->have > len ? len : state->have; + memcpy(buf, state->next, n); + state->next += n; + state->have -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && strm->avail_in == 0) + break; + + /* need output data -- for small len or new stream load up our output + buffer */ + else if (state->how == LOOK || len < (state->size << 1)) { + /* get more output, looking for header if required */ + if (gz_make(state) == -1) + return -1; + continue; /* no progress yet -- go back to memcpy() above */ + /* the copy above assures that we will leave with space in the + output buffer, allowing at least one gzungetc() to succeed */ + } + + /* large len -- read directly into user buffer */ + else if (state->how == COPY) { /* read directly */ + if (gz_load(state, buf, len, &n) == -1) + return -1; + } + + /* large len -- decompress directly into user buffer */ + else { /* state->how == GZIP */ + strm->avail_out = len; + strm->next_out = buf; + if (gz_decomp(state) == -1) + return -1; + n = state->have; + state->have = 0; + } + + /* update progress */ + len -= n; + buf = (char *)buf + n; + got += n; + state->pos += n; + } while (len); + + /* return number of bytes read into user buffer (will fit in int) */ + return (int)got; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzgetc(file) + gzFile file; +{ + int ret; + unsigned char buf[1]; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* try output buffer (no need to check for skip request) */ + if (state->have) { + state->have--; + state->pos++; + return *(state->next)++; + } + + /* nothing there -- try gzread() */ + ret = gzread(file, buf, 1); + return ret < 1 ? -1 : buf[0]; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* can't push EOF */ + if (c < 0) + return -1; + + /* if output buffer empty, put byte at end (allows more pushing) */ + if (state->have == 0) { + state->have = 1; + state->next = state->out + (state->size << 1) - 1; + state->next[0] = c; + state->pos--; + return c; + } + + /* if no room, give up (must have already done a gzungetc()) */ + if (state->have == (state->size << 1)) { + gz_error(state, Z_BUF_ERROR, "out of room to push characters"); + return -1; + } + + /* slide output data if needed and insert byte before existing data */ + if (state->next == state->out) { + unsigned char *src = state->out + state->have; + unsigned char *dest = state->out + (state->size << 1); + while (src > state->out) + *--dest = *--src; + state->next = dest; + } + state->have++; + state->next--; + state->next[0] = c; + state->pos--; + return c; +} + +/* -- see zlib.h -- */ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + unsigned left, n; + char *str; + unsigned char *eol; + gz_statep state; + + /* check parameters and get internal structure */ + if (file == NULL || buf == NULL || len < 1) + return NULL; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return NULL; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return NULL; + } + + /* copy output bytes up to new line or len - 1, whichever comes first -- + append a terminating zero to the string (we don't check for a zero in + the contents, let the user worry about that) */ + str = buf; + left = (unsigned)len - 1; + if (left) do { + /* assure that something is in the output buffer */ + if (state->have == 0) { + if (gz_make(state) == -1) + return NULL; /* error */ + if (state->have == 0) { /* end of file */ + if (buf == str) /* got bupkus */ + return NULL; + break; /* got something -- return it */ + } + } + + /* look for end-of-line in current output buffer */ + n = state->have > left ? left : state->have; + eol = memchr(state->next, '\n', n); + if (eol != NULL) + n = (unsigned)(eol - state->next) + 1; + + /* copy through end-of-line, or remainder if not found */ + memcpy(buf, state->next, n); + state->have -= n; + state->next += n; + state->pos += n; + left -= n; + buf += n; + } while (left && eol == NULL); + + /* found end-of-line or out of space -- terminate string and return it */ + buf[0] = 0; + return str; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzdirect(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return 0; + + /* if the state is not known, but we can find out, then do so (this is + mainly for right after a gzopen() or gzdopen()) */ + if (state->how == LOOK && state->have == 0) + (void)gz_head(state); + + /* return 1 if reading direct, 0 if decompressing a gzip stream */ + return state->direct; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_r(file) + gzFile file; +{ + int ret; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return Z_STREAM_ERROR; + + /* free memory and close file */ + if (state->size) { + inflateEnd(&(state->strm)); + free(state->out); + free(state->in); + } + gz_error(state, Z_OK, NULL); + free(state->path); + ret = close(state->fd); + free(state); + return ret ? Z_ERRNO : Z_OK; +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/gzwrite.c b/resources/3rdparty/glpk-4.53/src/zlib/gzwrite.c new file mode 100644 index 000000000..13c5558e0 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/gzwrite.c @@ -0,0 +1,531 @@ +/* gzwrite.c -- zlib functions for writing gzip files + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_init OF((gz_statep)); +local int gz_comp OF((gz_statep, int)); +local int gz_zero OF((gz_statep, z_off64_t)); + +/* Initialize state for writing a gzip file. Mark initialization by setting + state->size to non-zero. Return -1 on failure or 0 on success. */ +local int gz_init(state) + gz_statep state; +{ + int ret; + z_streamp strm = &(state->strm); + + /* allocate input and output buffers */ + state->in = malloc(state->want); + state->out = malloc(state->want); + if (state->in == NULL || state->out == NULL) { + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + 15 + 16, 8, state->strategy); + if (ret != Z_OK) { + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* mark state as initialized */ + state->size = state->want; + + /* initialize write buffer */ + strm->avail_out = state->size; + strm->next_out = state->out; + state->next = strm->next_out; + return 0; +} + +/* Compress whatever is at avail_in and next_in and write to the output file. + Return -1 if there is an error writing to the output file, otherwise 0. + flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, + then the deflate() state is reset to start a new gzip stream. */ +local int gz_comp(state, flush) + gz_statep state; + int flush; +{ + int ret, got; + unsigned have; + z_streamp strm = &(state->strm); + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return -1; + + /* run deflate() on provided input until it produces no more output */ + ret = Z_OK; + do { + /* write out current buffer contents if full, or if flushing, but if + doing Z_FINISH then don't write until we get to Z_STREAM_END */ + if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && + (flush != Z_FINISH || ret == Z_STREAM_END))) { + have = (unsigned)(strm->next_out - state->next); + if (have && ((got = write(state->fd, state->next, have)) < 0 || + (unsigned)got != have)) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (strm->avail_out == 0) { + strm->avail_out = state->size; + strm->next_out = state->out; + } + state->next = strm->next_out; + } + + /* compress */ + have = strm->avail_out; + ret = deflate(strm, flush); + if (ret == Z_STREAM_ERROR) { + gz_error(state, Z_STREAM_ERROR, + "internal error: deflate stream corrupt"); + return -1; + } + have -= strm->avail_out; + } while (have); + + /* if that completed a deflate stream, allow another to start */ + if (flush == Z_FINISH) + deflateReset(strm); + + /* all done, no errors */ + return 0; +} + +/* Compress len zeros to output. Return -1 on error, 0 on success. */ +local int gz_zero(state, len) + gz_statep state; + z_off64_t len; +{ + int first; + unsigned n; + z_streamp strm = &(state->strm); + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + + /* compress len zeros (len guaranteed > 0) */ + first = 1; + while (len) { + n = GT_OFF(state->size) || (z_off64_t)state->size > len ? + (unsigned)len : state->size; + if (first) { + memset(state->in, 0, n); + first = 0; + } + strm->avail_in = n; + strm->next_in = state->in; + state->pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + len -= n; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + unsigned put = len; + unsigned n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + return 0; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* for small len, copy to input buffer, otherwise compress directly */ + if (len < state->size) { + /* copy to input buffer, compress when full */ + do { + if (strm->avail_in == 0) + strm->next_in = state->in; + n = state->size - strm->avail_in; + if (n > len) + n = len; + memcpy(strm->next_in + strm->avail_in, buf, n); + strm->avail_in += n; + state->pos += n; + buf = (char *)buf + n; + len -= n; + if (len && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } while (len); + } + else { + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* directly compress user buffer to file */ + strm->avail_in = len; + strm->next_in = (voidp)buf; + state->pos += len; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } + + /* input was all buffered or compressed (put will fit in int) */ + return (int)put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char buf[1]; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* try writing to input buffer for speed (state->size == 0 if buffer not + initialized) */ + if (strm->avail_in < state->size) { + if (strm->avail_in == 0) + strm->next_in = state->in; + strm->next_in[strm->avail_in++] = c; + state->pos++; + return c; + } + + /* no room in buffer or not initialized, use gz_write() */ + buf[0] = c; + if (gzwrite(file, buf, 1) != 1) + return -1; + return c; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputs(file, str) + gzFile file; + const char *str; +{ + int ret; + unsigned len; + + /* write string */ + len = (unsigned)strlen(str); + ret = gzwrite(file, str, len); + return ret == 0 && len != 0 ? -1 : ret; +} + +#ifdef STDC +#include <stdarg.h> + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) +{ + int size, len; + gz_statep state; + z_streamp strm; + va_list va; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(state->in, format, va); + va_end(va); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = vsprintf((char *)state->in, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(state->in, size, format, va); + va_end(va); + len = strlen(state->in); +# else + len = vsnprintf((char *)(state->in), size, format, va); + va_end(va); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->pos += len; + return len; +} + +#else /* !STDC */ + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + int size, len; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(state->in); +# else + len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->pos += len; + return len; +} + +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzflush(file, flush) + gzFile file; + int flush; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* check flush parameter */ + if (flush < 0 || flush > Z_FINISH) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* compress remaining data with requested flush */ + gz_comp(state, flush); + return state->err; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzsetparams(file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* if no change is requested, then do nothing */ + if (level == state->level && strategy == state->strategy) + return Z_OK; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* change compression parameters for subsequent input */ + if (state->size) { + /* flush previous input with previous parameters before changing */ + if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) + return state->err; + deflateParams(strm, level, strategy); + } + state->level = level; + state->strategy = strategy; + return Z_OK; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_w(file) + gzFile file; +{ + int ret = 0; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're writing */ + if (state->mode != GZ_WRITE) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + ret += gz_zero(state, state->skip); + } + + /* flush, free memory, and close file */ + ret += gz_comp(state, Z_FINISH); + (void)deflateEnd(&(state->strm)); + free(state->out); + free(state->in); + gz_error(state, Z_OK, NULL); + free(state->path); + ret += close(state->fd); + free(state); + return ret ? Z_ERRNO : Z_OK; +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inffast.c b/resources/3rdparty/glpk-4.53/src/zlib/inffast.c new file mode 100644 index 000000000..2f1d60b43 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/inffast.c @@ -0,0 +1,340 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2008, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + PUP(out) = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + PUP(out) = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + PUP(out) = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + PUP(out) = PUP(from); + } while (--len); + continue; + } +#endif + } + from = window - OFF; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inffast.h b/resources/3rdparty/glpk-4.53/src/zlib/inffast.h new file mode 100644 index 000000000..e5c1aa4ca --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inffixed.h b/resources/3rdparty/glpk-4.53/src/zlib/inffixed.h new file mode 100644 index 000000000..75ed4b597 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inflate.c b/resources/3rdparty/glpk-4.53/src/zlib/inflate.c new file mode 100644 index 000000000..a8431abea --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/inflate.c @@ -0,0 +1,1480 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->window = Z_NULL; + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include <stdio.h> + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + else if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->sane = !subvert; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + return Z_OK; +#else + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + state = (struct inflate_state FAR *)strm->state; + return ((long)(state->back) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inflate.h b/resources/3rdparty/glpk-4.53/src/zlib/inflate.h new file mode 100644 index 000000000..95f4986d4 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/inflate.h @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inftrees.c b/resources/3rdparty/glpk-4.53/src/zlib/inftrees.c new file mode 100644 index 000000000..11e9c52ac --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/inftrees.c @@ -0,0 +1,330 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + here.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = here; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inftrees.h b/resources/3rdparty/glpk-4.53/src/zlib/inftrees.h new file mode 100644 index 000000000..baa53a0b1 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/resources/3rdparty/glpk-4.53/src/zlib/trees.c b/resources/3rdparty/glpk-4.53/src/zlib/trees.c new file mode 100644 index 000000000..56e9bb1c1 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/trees.c @@ -0,0 +1,1244 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2010 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include <ctype.h> +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1<<extra_lbits[code]); n++) { + _length_code[length++] = (uch)code; + } + } + Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length-1] = (uch)code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<<extra_dbits[code]); n++) { + _dist_code[dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include <stdio.h> +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = bi_reverse(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + } +} + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +local void build_tree(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/trees.h b/resources/3rdparty/glpk-4.53/src/zlib/trees.h new file mode 100644 index 000000000..d35639d82 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/resources/3rdparty/glpk-4.53/src/zlib/uncompr.c b/resources/3rdparty/glpk-4.53/src/zlib/uncompr.c new file mode 100644 index 000000000..ad98be3a5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/uncompr.c @@ -0,0 +1,59 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zconf.h b/resources/3rdparty/glpk-4.53/src/zlib/zconf.h new file mode 100644 index 000000000..af6a4f0fe --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/zconf.h @@ -0,0 +1,168 @@ +/* zconf.h (configuration of the zlib compression library) */ + +/* Modified by Andrew Makhorin <mao@gnu.org>, April 2011 */ + +/* Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in + * zlib.h */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* (file adler32.c) */ +#define adler32 _glp_zlib_adler32 +#define adler32_combine _glp_zlib_adler32_combine +#define adler32_combine64 _glp_zlib_adler32_combine64 + +/* (file compress.c) */ +#define compress2 _glp_zlib_compress2 +#define compress _glp_zlib_compress +#define compressBound _glp_zlib_compressBound + +/* (file crc32.c) */ +#define get_crc_table _glp_zlib_get_crc_table +#define crc32 _glp_zlib_crc32 +#define crc32_combine _glp_zlib_crc32_combine +#define crc32_combine64 _glp_zlib_crc32_combine64 + +/* (file deflate.c) */ +#define deflateInit_ _glp_zlib_deflateInit_ +#define deflateInit2_ _glp_zlib_deflateInit2_ +#define deflateSetDictionary _glp_zlib_deflateSetDictionary +#define deflateReset _glp_zlib_deflateReset +#define deflateSetHeader _glp_zlib_deflateSetHeader +#define deflatePrime _glp_zlib_deflatePrime +#define deflateParams _glp_zlib_deflateParams +#define deflateTune _glp_zlib_deflateTune +#define deflateBound _glp_zlib_deflateBound +#define deflate _glp_zlib_deflate +#define deflateEnd _glp_zlib_deflateEnd +#define deflateCopy _glp_zlib_deflateCopy +#define deflate_copyright _glp_zlib_deflate_copyright + +/* (file gzclose.c) */ +#define gzclose _glp_zlib_gzclose + +/* (file gzlib.c) */ +#define gzopen _glp_zlib_gzopen +#define gzopen64 _glp_zlib_gzopen64 +#define gzdopen _glp_zlib_gzdopen +#define gzbuffer _glp_zlib_gzbuffer +#define gzrewind _glp_zlib_gzrewind +#define gzseek64 _glp_zlib_gzseek64 +#define gzseek _glp_zlib_gzseek +#define gztell64 _glp_zlib_gztell64 +#define gztell _glp_zlib_gztell +#define gzoffset64 _glp_zlib_gzoffset64 +#define gzoffset _glp_zlib_gzoffset +#define gzeof _glp_zlib_gzeof +#define gzerror _glp_zlib_gzerror +#define gzclearerr _glp_zlib_gzclearerr +#define gz_error _glp_zlib_gz_error + +/* (file gzread.c) */ +#define gzread _glp_zlib_gzread +#define gzgetc _glp_zlib_gzgetc +#define gzungetc _glp_zlib_gzungetc +#define gzgets _glp_zlib_gzgets +#define gzdirect _glp_zlib_gzdirect +#define gzclose_r _glp_zlib_gzclose_r + +/* (file gzwrite.c) */ +#define gzwrite _glp_zlib_gzwrite +#define gzputc _glp_zlib_gzputc +#define gzputs _glp_zlib_gzputs +#define gzprintf _glp_zlib_gzprintf +#define gzflush _glp_zlib_gzflush +#define gzsetparams _glp_zlib_gzsetparams +#define gzclose_w _glp_zlib_gzclose_w + +/* (file infback.c) */ +#define inflateBackInit_ _glp_zlib_inflateBackInit_ +#define inflateBack _glp_zlib_inflateBack +#define inflateBackEnd _glp_zlib_inflateBackEnd + +/* (file inffast.c) */ +#define inflate_fast _glp_zlib_inflate_fast + +/* (file inflate.c) */ +#define inflateReset _glp_zlib_inflateReset +#define inflateReset2 _glp_zlib_inflateReset2 +#define inflateInit2_ _glp_zlib_inflateInit2_ +#define inflateInit_ _glp_zlib_inflateInit_ +#define inflatePrime _glp_zlib_inflatePrime +#define inflate _glp_zlib_inflate +#define inflateEnd _glp_zlib_inflateEnd +#define inflateSetDictionary _glp_zlib_inflateSetDictionary +#define inflateGetHeader _glp_zlib_inflateGetHeader +#define inflateSync _glp_zlib_inflateSync +#define inflateSyncPoint _glp_zlib_inflateSyncPoint +#define inflateCopy _glp_zlib_inflateCopy +#define inflateUndermine _glp_zlib_inflateUndermine +#define inflateMark _glp_zlib_inflateMark + +/* (file inftrees.c) */ +#define inflate_table _glp_zlib_inflate_table +#define inflate_copyright _glp_zlib_inflate_copyright + +/* (file trees.c) */ +#define _tr_init _glp_zlib_tr_init +#define _tr_stored_block _glp_zlib_tr_stored_block +#define _tr_align _glp_zlib_tr_align +#define _tr_flush_block _glp_zlib_tr_flush_block +#define _tr_tally _glp_zlib_tr_tally +#define _dist_code _glp_zlib_dist_code +#define _length_code _glp_zlib_length_code + +/* (file uncompr.c) */ +#define uncompress _glp_zlib_uncompress + +/* (file zutil.c) */ +#define zlibVersion _glp_zlib_zlibVersion +#define zlibCompileFlags _glp_zlib_zlibCompileFlags +#define zError _glp_zlib_zError +#define zcalloc _glp_zlib_zcalloc +#define zcfree _glp_zlib_zcfree +#define z_errmsg _glp_zlib_z_errmsg + +#define STDC 1 + +#define MAX_MEM_LEVEL 9 + +#define MAX_WBITS 15 + +#define OF(args) args + +#define ZEXTERN extern +#define ZEXPORT +#define ZEXPORTVA + +#define FAR + +typedef unsigned char Byte; +typedef unsigned int uInt; +typedef unsigned long uLong; + +typedef Byte Bytef; +typedef char charf; +typedef int intf; +typedef uInt uIntf; +typedef uLong uLongf; + +typedef void const *voidpc; +typedef void *voidpf; +typedef void *voidp; + +#define z_off_t long + +#define z_off64_t z_off_t + +#define NO_vsnprintf 1 + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zio.c b/resources/3rdparty/glpk-4.53/src/zlib/zio.c new file mode 100644 index 000000000..a55b258a7 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/zio.c @@ -0,0 +1,92 @@ +/* zio.c (simulation of non-standard low-level i/o functions) */ + +/* Written by Andrew Makhorin <mao@gnu.org>, April 2011 + * For conditions of distribution and use, see copyright notice in + * zlib.h */ + +/* (reserved for copyright notice) */ + +#include <assert.h> +#include <stdio.h> +#include "zio.h" + +static FILE *file[FOPEN_MAX]; +static int initialized = 0; + +static void initialize(void) +{ int fd; + assert(!initialized); + file[0] = stdin; + file[1] = stdout; + file[2] = stderr; + for (fd = 3; fd < FOPEN_MAX; fd++) + file[fd] = NULL; + initialized = 1; + return; +} + +int open(const char *path, int oflag, ...) +{ FILE *fp; + int fd; + if (!initialized) initialize(); + /* see file gzlib.c, function gz_open */ + if (oflag == O_RDONLY) + fp = fopen(path, "rb"); + else if (oflag == (O_WRONLY | O_CREAT | O_TRUNC)) + fp = fopen(path, "wb"); + else if (oflag == (O_WRONLY | O_CREAT | O_APPEND)) + fp = fopen(path, "ab"); + else + assert(oflag != oflag); + if (fp == NULL) + return -1; + for (fd = 0; fd < FOPEN_MAX; fd++) + if (file[fd] == NULL) break; + assert(fd < FOPEN_MAX); + file[fd] = fp; + return fd; +} + +long read(int fd, void *buf, unsigned long nbyte) +{ unsigned long count; + if (!initialized) initialize(); + assert(0 <= fd && fd < FOPEN_MAX); + assert(file[fd] != NULL); + count = fread(buf, 1, nbyte, file[fd]); + if (ferror(file[fd])) + return -1; + return count; +} + +long write(int fd, const void *buf, unsigned long nbyte) +{ unsigned long count; + if (!initialized) initialize(); + assert(0 <= fd && fd < FOPEN_MAX); + assert(file[fd] != NULL); + count = fwrite(buf, 1, nbyte, file[fd]); + if (count != nbyte) + return -1; + if (fflush(file[fd]) != 0) + return -1; + return count; +} + +long lseek(int fd, long offset, int whence) +{ if (!initialized) initialize(); + assert(0 <= fd && fd < FOPEN_MAX); + assert(file[fd] != NULL); + if (fseek(file[fd], offset, whence) != 0) + return -1; + return ftell(file[fd]); +} + +int close(int fd) +{ if (!initialized) initialize(); + assert(0 <= fd && fd < FOPEN_MAX); + assert(file[fd] != NULL); + fclose(file[fd]); + file[fd] = NULL; + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zio.h b/resources/3rdparty/glpk-4.53/src/zlib/zio.h new file mode 100644 index 000000000..1626c4ae4 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/zio.h @@ -0,0 +1,37 @@ +/* zio.h (simulation of non-standard low-level i/o functions) */ + +/* Written by Andrew Makhorin <mao@gnu.org>, April 2011 + * For conditions of distribution and use, see copyright notice in + * zlib.h */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. */ + +#ifndef ZIO_H +#define ZIO_H + +#define O_RDONLY 0x00 +#define O_WRONLY 0x01 +#define O_CREAT 0x10 +#define O_TRUNC 0x20 +#define O_APPEND 0x30 + +#define open _glp_zlib_open +int open(const char *path, int oflag, ...); + +#define read _glp_zlib_read +long read(int fd, void *buf, unsigned long nbyte); + +#define write _glp_zlib_write +long write(int fd, const void *buf, unsigned long nbyte); + +#define lseek _glp_zlib_lseek +long lseek(int fd, long offset, int whence); + +#define close _glp_zlib_close +int close(int fd); + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zlib.h b/resources/3rdparty/glpk-4.53/src/zlib/zlib.h new file mode 100644 index 000000000..bfbba83e8 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/zlib.h @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zutil.c b/resources/3rdparty/glpk-4.53/src/zlib/zutil.c new file mode 100644 index 000000000..898ed345b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zutil.h b/resources/3rdparty/glpk-4.53/src/zlib/zutil.h new file mode 100644 index 000000000..737bd38f5 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/src/zlib/zutil.h @@ -0,0 +1,93 @@ +/* zutil.h (internal interface of the zlib compression library) */ + +/* Modified by Andrew Makhorin <mao@gnu.org>, April 2011 */ + +/* Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in + * zlib.h */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL + +#include "zlib.h" + +#include <stddef.h> +#include <string.h> +#include <stdlib.h> + +#define local static + +typedef unsigned char uch; +typedef uch uchf; +typedef unsigned short ush; +typedef ush ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm, err) \ + return (strm->msg = (char *)ERR_MSG(err), (err)) + +#define DEF_WBITS MAX_WBITS + +#if MAX_MEM_LEVEL >= 8 +#define DEF_MEM_LEVEL 8 +#else +#define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 + +#define MIN_MATCH 3 +#define MAX_MATCH 258 + +#define PRESET_DICT 0x20 + +#define OS_CODE 0x03 /* assume Unix */ + +#define HAVE_MEMCPY 1 +#define zmemcpy memcpy +#define zmemzero(dest, len) memset(dest, 0, len) + +#ifdef DEBUG +#include <stdio.h> +extern int ZLIB_INTERNAL z_verbose; +extern void ZLIB_INTERNAL z_error OF((char *m)); +#define Assert(cond, msg) { if(!(cond)) z_error(msg); } +#define Trace(x) { if (z_verbose >= 0) fprintf x; } +#define Tracev(x) { if (z_verbose > 0) fprintf x; } +#define Tracevv(x) {if (z_verbose > 1) fprintf x; } +#define Tracec(c, x) {if (z_verbose > 0 && (c)) fprintf x; } +#define Tracecv(c, x) {if (z_verbose > 1 && (c)) fprintf x; } +#else +#define Assert(cond, msg) +#define Trace(x) +#define Tracev(x) +#define Tracevv(x) +#define Tracec(c, x) +#define Tracecv(c, x) +#endif + +voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); +void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) \ + (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) { if (p) ZFREE(s, p); } + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10.bat b/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10.bat new file mode 100644 index 000000000..b0f693446 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Express 2010 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 10.0\VC" + +call %HOME%\vcvarsall.bat x86 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10_DLL.bat b/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10_DLL.bat new file mode 100644 index 000000000..e66f5cb39 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Express 2010 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 10.0\VC" + +call %HOME%\vcvarsall.bat x86 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9.bat b/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9.bat new file mode 100644 index 000000000..9c5e8f83d --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Express 2008 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 9.0\VC" + +call %HOME%\bin\vcvars32.bat +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9_DLL.bat b/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9_DLL.bat new file mode 100644 index 000000000..f334c04af --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Express 2008 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 9.0\VC" + +call %HOME%\bin\vcvars32.bat +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/resources/3rdparty/glpk-4.53/w32/Makefile_VC b/resources/3rdparty/glpk-4.53/w32/Makefile_VC new file mode 100644 index 000000000..c0c257ea2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w32/Makefile_VC @@ -0,0 +1,191 @@ +## Build GLPK with Microsoft Visual Studio Express ## + +CFLAGS = \ +/I. \ +/I..\src \ +/I..\src\amd \ +/I..\src\bflib \ +/I..\src\cglib \ +/I..\src\colamd \ +/I..\src\env \ +/I..\src\minisat \ +/I..\src\misc \ +/I..\src\proxy \ +/I..\src\zlib \ +/DHAVE_CONFIG_H=1 \ +/D_CRT_SECURE_NO_WARNINGS=1 \ +/nologo \ +/W3 \ +/O2 + +OBJSET = \ +..\src\avl.obj \ +..\src\bfd.obj \ +..\src\bfx.obj \ +..\src\glpapi01.obj \ +..\src\glpapi02.obj \ +..\src\glpapi03.obj \ +..\src\glpapi04.obj \ +..\src\glpapi05.obj \ +..\src\glpapi06.obj \ +..\src\glpapi07.obj \ +..\src\glpapi08.obj \ +..\src\glpapi09.obj \ +..\src\glpapi10.obj \ +..\src\glpapi11.obj \ +..\src\glpapi12.obj \ +..\src\glpapi13.obj \ +..\src\glpapi14.obj \ +..\src\glpapi15.obj \ +..\src\glpapi16.obj \ +..\src\glpapi17.obj \ +..\src\glpapi18.obj \ +..\src\glpapi19.obj \ +..\src\glpapi20.obj \ +..\src\glpapi21.obj \ +..\src\glpcpx.obj \ +..\src\glpdmx.obj \ +..\src\glpgmp.obj \ +..\src\glphbm.obj \ +..\src\glpini01.obj \ +..\src\glpini02.obj \ +..\src\glpios01.obj \ +..\src\glpios02.obj \ +..\src\glpios03.obj \ +..\src\glpios04.obj \ +..\src\glpios05.obj \ +..\src\glpios06.obj \ +..\src\glpios07.obj \ +..\src\glpios08.obj \ +..\src\glpios09.obj \ +..\src\glpios10.obj \ +..\src\glpios11.obj \ +..\src\glpios12.obj \ +..\src\glpipm.obj \ +..\src\glplpf.obj \ +..\src\glpmat.obj \ +..\src\glpmpl01.obj \ +..\src\glpmpl02.obj \ +..\src\glpmpl03.obj \ +..\src\glpmpl04.obj \ +..\src\glpmpl05.obj \ +..\src\glpmpl06.obj \ +..\src\glpmps.obj \ +..\src\glpnet03.obj \ +..\src\glpnet04.obj \ +..\src\glpnet05.obj \ +..\src\glpnpp01.obj \ +..\src\glpnpp02.obj \ +..\src\glpnpp03.obj \ +..\src\glpnpp04.obj \ +..\src\glpnpp05.obj \ +..\src\glpnpp06.obj \ +..\src\glprgr.obj \ +..\src\glpscl.obj \ +..\src\glpsdf.obj \ +..\src\glpspm.obj \ +..\src\glpspx01.obj \ +..\src\glpspx02.obj \ +..\src\glpsql.obj \ +..\src\glpssx01.obj \ +..\src\glpssx02.obj \ +..\src\glptsp.obj \ +..\src\lux.obj \ +..\src\amd\amd_1.obj \ +..\src\amd\amd_2.obj \ +..\src\amd\amd_aat.obj \ +..\src\amd\amd_control.obj \ +..\src\amd\amd_defaults.obj \ +..\src\amd\amd_dump.obj \ +..\src\amd\amd_info.obj \ +..\src\amd\amd_order.obj \ +..\src\amd\amd_post_tree.obj \ +..\src\amd\amd_postorder.obj \ +..\src\amd\amd_preprocess.obj \ +..\src\amd\amd_valid.obj \ +..\src\bflib\fhv.obj \ +..\src\bflib\fhvint.obj \ +..\src\bflib\ifu.obj \ +..\src\bflib\luf.obj \ +..\src\bflib\lufint.obj \ +..\src\bflib\sgf.obj \ +..\src\bflib\sva.obj \ +..\src\cglib\cfg.obj \ +..\src\cglib\cfg1.obj \ +..\src\colamd\colamd.obj \ +..\src\env\alloc.obj \ +..\src\env\dlsup.obj \ +..\src\env\env.obj \ +..\src\env\error.obj \ +..\src\env\stdout.obj \ +..\src\env\stream.obj \ +..\src\env\time.obj \ +..\src\env\tls.obj \ +..\src\minisat\minisat.obj \ +..\src\misc\bignum.obj \ +..\src\misc\dmp.obj \ +..\src\misc\ffalg.obj \ +..\src\misc\fp2rat.obj \ +..\src\misc\gcd.obj \ +..\src\misc\jd.obj \ +..\src\misc\keller.obj \ +..\src\misc\mc13d.obj \ +..\src\misc\mc21a.obj \ +..\src\misc\okalg.obj \ +..\src\misc\qmd.obj \ +..\src\misc\relax4.obj \ +..\src\misc\rng.obj \ +..\src\misc\rng1.obj \ +..\src\misc\round2n.obj \ +..\src\misc\str2int.obj \ +..\src\misc\str2num.obj \ +..\src\misc\strspx.obj \ +..\src\misc\strtrim.obj \ +..\src\misc\triang.obj \ +..\src\misc\wclique.obj \ +..\src\misc\wclique1.obj \ +..\src\proxy\proxy.obj \ +..\src\proxy\proxy1.obj \ +..\src\zlib\adler32.obj \ +..\src\zlib\compress.obj \ +..\src\zlib\crc32.obj \ +..\src\zlib\deflate.obj \ +..\src\zlib\gzclose.obj \ +..\src\zlib\gzlib.obj \ +..\src\zlib\gzread.obj \ +..\src\zlib\gzwrite.obj \ +..\src\zlib\inffast.obj \ +..\src\zlib\inflate.obj \ +..\src\zlib\inftrees.obj \ +..\src\zlib\trees.obj \ +..\src\zlib\uncompr.obj \ +..\src\zlib\zio.obj \ +..\src\zlib\zutil.obj + +.c.obj: + cl.exe $(CFLAGS) /Fo$*.obj /c $*.c + +all: glpk.lib glpsol.exe + +glpk.lib: $(OBJSET) + lib.exe /out:glpk.lib \ + ..\src\*.obj \ + ..\src\amd\*.obj \ + ..\src\bflib\*.obj \ + ..\src\cglib\*.obj \ + ..\src\colamd\*.obj \ + ..\src\env\*.obj \ + ..\src\minisat\*.obj \ + ..\src\misc\*.obj \ + ..\src\proxy\*.obj \ + ..\src\zlib\*.obj + +glpsol.exe: ..\examples\glpsol.obj glpk.lib + cl.exe $(CFLAGS) /Feglpsol.exe \ + ..\examples\glpsol.obj glpk.lib + +check: glpsol.exe + .\glpsol.exe --version + .\glpsol.exe --mps ..\examples\plan.mps + +## eof ## diff --git a/resources/3rdparty/glpk-4.53/w32/Makefile_VC_DLL b/resources/3rdparty/glpk-4.53/w32/Makefile_VC_DLL new file mode 100644 index 000000000..9eb7a6586 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w32/Makefile_VC_DLL @@ -0,0 +1,192 @@ +## Build GLPK DLL with Microsoft Visual Studio Express ## + +CFLAGS = \ +/I. \ +/I..\src \ +/I..\src\amd \ +/I..\src\bflib \ +/I..\src\cglib \ +/I..\src\colamd \ +/I..\src\env \ +/I..\src\minisat \ +/I..\src\misc \ +/I..\src\proxy \ +/I..\src\zlib \ +/DHAVE_CONFIG_H=1 \ +/D_CRT_SECURE_NO_WARNINGS=1 \ +/nologo \ +/W3 \ +/O2 + +OBJSET = \ +..\src\avl.obj \ +..\src\bfd.obj \ +..\src\bfx.obj \ +..\src\glpapi01.obj \ +..\src\glpapi02.obj \ +..\src\glpapi03.obj \ +..\src\glpapi04.obj \ +..\src\glpapi05.obj \ +..\src\glpapi06.obj \ +..\src\glpapi07.obj \ +..\src\glpapi08.obj \ +..\src\glpapi09.obj \ +..\src\glpapi10.obj \ +..\src\glpapi11.obj \ +..\src\glpapi12.obj \ +..\src\glpapi13.obj \ +..\src\glpapi14.obj \ +..\src\glpapi15.obj \ +..\src\glpapi16.obj \ +..\src\glpapi17.obj \ +..\src\glpapi18.obj \ +..\src\glpapi19.obj \ +..\src\glpapi20.obj \ +..\src\glpapi21.obj \ +..\src\glpcpx.obj \ +..\src\glpdmx.obj \ +..\src\glpgmp.obj \ +..\src\glphbm.obj \ +..\src\glpini01.obj \ +..\src\glpini02.obj \ +..\src\glpios01.obj \ +..\src\glpios02.obj \ +..\src\glpios03.obj \ +..\src\glpios04.obj \ +..\src\glpios05.obj \ +..\src\glpios06.obj \ +..\src\glpios07.obj \ +..\src\glpios08.obj \ +..\src\glpios09.obj \ +..\src\glpios10.obj \ +..\src\glpios11.obj \ +..\src\glpios12.obj \ +..\src\glpipm.obj \ +..\src\glplpf.obj \ +..\src\glpmat.obj \ +..\src\glpmpl01.obj \ +..\src\glpmpl02.obj \ +..\src\glpmpl03.obj \ +..\src\glpmpl04.obj \ +..\src\glpmpl05.obj \ +..\src\glpmpl06.obj \ +..\src\glpmps.obj \ +..\src\glpnet03.obj \ +..\src\glpnet04.obj \ +..\src\glpnet05.obj \ +..\src\glpnpp01.obj \ +..\src\glpnpp02.obj \ +..\src\glpnpp03.obj \ +..\src\glpnpp04.obj \ +..\src\glpnpp05.obj \ +..\src\glpnpp06.obj \ +..\src\glprgr.obj \ +..\src\glpscl.obj \ +..\src\glpsdf.obj \ +..\src\glpspm.obj \ +..\src\glpspx01.obj \ +..\src\glpspx02.obj \ +..\src\glpsql.obj \ +..\src\glpssx01.obj \ +..\src\glpssx02.obj \ +..\src\glptsp.obj \ +..\src\lux.obj \ +..\src\amd\amd_1.obj \ +..\src\amd\amd_2.obj \ +..\src\amd\amd_aat.obj \ +..\src\amd\amd_control.obj \ +..\src\amd\amd_defaults.obj \ +..\src\amd\amd_dump.obj \ +..\src\amd\amd_info.obj \ +..\src\amd\amd_order.obj \ +..\src\amd\amd_post_tree.obj \ +..\src\amd\amd_postorder.obj \ +..\src\amd\amd_preprocess.obj \ +..\src\amd\amd_valid.obj \ +..\src\bflib\fhv.obj \ +..\src\bflib\fhvint.obj \ +..\src\bflib\ifu.obj \ +..\src\bflib\luf.obj \ +..\src\bflib\lufint.obj \ +..\src\bflib\sgf.obj \ +..\src\bflib\sva.obj \ +..\src\cglib\cfg.obj \ +..\src\cglib\cfg1.obj \ +..\src\colamd\colamd.obj \ +..\src\env\alloc.obj \ +..\src\env\dlsup.obj \ +..\src\env\env.obj \ +..\src\env\error.obj \ +..\src\env\stdout.obj \ +..\src\env\stream.obj \ +..\src\env\time.obj \ +..\src\env\tls.obj \ +..\src\minisat\minisat.obj \ +..\src\misc\bignum.obj \ +..\src\misc\dmp.obj \ +..\src\misc\ffalg.obj \ +..\src\misc\fp2rat.obj \ +..\src\misc\gcd.obj \ +..\src\misc\jd.obj \ +..\src\misc\keller.obj \ +..\src\misc\mc13d.obj \ +..\src\misc\mc21a.obj \ +..\src\misc\okalg.obj \ +..\src\misc\qmd.obj \ +..\src\misc\relax4.obj \ +..\src\misc\rng.obj \ +..\src\misc\rng1.obj \ +..\src\misc\round2n.obj \ +..\src\misc\str2int.obj \ +..\src\misc\str2num.obj \ +..\src\misc\strspx.obj \ +..\src\misc\strtrim.obj \ +..\src\misc\triang.obj \ +..\src\misc\wclique.obj \ +..\src\misc\wclique1.obj \ +..\src\proxy\proxy.obj \ +..\src\proxy\proxy1.obj \ +..\src\zlib\adler32.obj \ +..\src\zlib\compress.obj \ +..\src\zlib\crc32.obj \ +..\src\zlib\deflate.obj \ +..\src\zlib\gzclose.obj \ +..\src\zlib\gzlib.obj \ +..\src\zlib\gzread.obj \ +..\src\zlib\gzwrite.obj \ +..\src\zlib\inffast.obj \ +..\src\zlib\inflate.obj \ +..\src\zlib\inftrees.obj \ +..\src\zlib\trees.obj \ +..\src\zlib\uncompr.obj \ +..\src\zlib\zio.obj \ +..\src\zlib\zutil.obj + +.c.obj: + cl.exe $(CFLAGS) /Fo$*.obj /c $*.c + +all: glpk_4_53.dll glpsol.exe + +glpk_4_53.dll: $(OBJSET) + cl.exe $(CFLAGS) /LD /Feglpk_4_53.dll \ + ..\src\*.obj \ + ..\src\amd\*.obj \ + ..\src\bflib\*.obj \ + ..\src\cglib\*.obj \ + ..\src\colamd\*.obj \ + ..\src\env\*.obj \ + ..\src\minisat\*.obj \ + ..\src\misc\*.obj \ + ..\src\proxy\*.obj \ + ..\src\zlib\*.obj \ + glpk_4_53.def + +glpsol.exe: ..\examples\glpsol.obj glpk_4_53.dll + cl.exe $(CFLAGS) /Feglpsol.exe \ + ..\examples\glpsol.obj glpk_4_53.lib + +check: glpsol.exe + .\glpsol.exe --version + .\glpsol.exe --mps ..\examples\plan.mps + +## eof ## diff --git a/resources/3rdparty/glpk-4.53/w32/config_VC b/resources/3rdparty/glpk-4.53/w32/config_VC new file mode 100644 index 000000000..581ab6e6e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w32/config_VC @@ -0,0 +1,13 @@ +/* GLPK configuration file (Microsoft Visual Studio Express) */ + +#define __WOE__ 1 + +#define ODBC_DLNAME "odbc32.dll" +/* ODBC shared library name if this feature is enabled */ + +#if 0 +#define MYSQL_DLNAME "libmysql.dll" +/* MySQL shared library name if this feature is enabled */ +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/w32/glpk_4_53.def b/resources/3rdparty/glpk-4.53/w32/glpk_4_53.def new file mode 100644 index 000000000..dc5ed7595 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w32/glpk_4_53.def @@ -0,0 +1,223 @@ +LIBRARY glpk_4_53 +VERSION 4.53 +DESCRIPTION "GNU Linear Programming Kit" +EXPORTS +glp_create_prob +glp_set_prob_name +glp_set_obj_name +glp_set_obj_dir +glp_add_rows +glp_add_cols +glp_set_row_name +glp_set_col_name +glp_set_row_bnds +glp_set_col_bnds +glp_set_obj_coef +glp_set_mat_row +glp_set_mat_col +glp_load_matrix +glp_check_dup +glp_sort_matrix +glp_del_rows +glp_del_cols +glp_copy_prob +glp_erase_prob +glp_delete_prob +glp_get_prob_name +glp_get_obj_name +glp_get_obj_dir +glp_get_num_rows +glp_get_num_cols +glp_get_row_name +glp_get_col_name +glp_get_row_type +glp_get_row_lb +glp_get_row_ub +glp_get_col_type +glp_get_col_lb +glp_get_col_ub +glp_get_obj_coef +glp_get_num_nz +glp_get_mat_row +glp_get_mat_col +glp_create_index +glp_find_row +glp_find_col +glp_delete_index +glp_set_rii +glp_set_sjj +glp_get_rii +glp_get_sjj +glp_scale_prob +glp_unscale_prob +glp_set_row_stat +glp_set_col_stat +glp_std_basis +glp_adv_basis +glp_cpx_basis +glp_simplex +glp_exact +glp_init_smcp +glp_get_status +glp_get_prim_stat +glp_get_dual_stat +glp_get_obj_val +glp_get_row_stat +glp_get_row_prim +glp_get_row_dual +glp_get_col_stat +glp_get_col_prim +glp_get_col_dual +glp_get_unbnd_ray +glp_get_it_cnt +glp_set_it_cnt +glp_interior +glp_init_iptcp +glp_ipt_status +glp_ipt_obj_val +glp_ipt_row_prim +glp_ipt_row_dual +glp_ipt_col_prim +glp_ipt_col_dual +glp_set_col_kind +glp_get_col_kind +glp_get_num_int +glp_get_num_bin +glp_intopt +glp_init_iocp +glp_mip_status +glp_mip_obj_val +glp_mip_row_val +glp_mip_col_val +glp_check_kkt +glp_print_sol +glp_read_sol +glp_write_sol +glp_print_ranges +glp_print_ipt +glp_read_ipt +glp_write_ipt +glp_print_mip +glp_read_mip +glp_write_mip +glp_bf_exists +glp_factorize +glp_bf_updated +glp_get_bfcp +glp_set_bfcp +glp_get_bhead +glp_get_row_bind +glp_get_col_bind +glp_ftran +glp_btran +glp_warm_up +glp_eval_tab_row +glp_eval_tab_col +glp_transform_row +glp_transform_col +glp_prim_rtest +glp_dual_rtest +glp_analyze_bound +glp_analyze_coef +glp_ios_reason +glp_ios_get_prob +glp_ios_tree_size +glp_ios_curr_node +glp_ios_next_node +glp_ios_prev_node +glp_ios_up_node +glp_ios_node_level +glp_ios_node_bound +glp_ios_best_node +glp_ios_mip_gap +glp_ios_node_data +glp_ios_row_attr +glp_ios_pool_size +glp_ios_add_row +glp_ios_del_row +glp_ios_clear_pool +glp_ios_can_branch +glp_ios_branch_upon +glp_ios_select_node +glp_ios_heur_sol +glp_ios_terminate +glp_init_mpscp +glp_read_mps +glp_write_mps +glp_init_cpxcp +glp_read_lp +glp_write_lp +glp_read_prob +glp_write_prob +glp_mpl_alloc_wksp +glp_mpl_read_model +glp_mpl_read_data +glp_mpl_generate +glp_mpl_build_prob +glp_mpl_postsolve +glp_mpl_free_wksp +glp_main +glp_read_cnfsat +glp_check_cnfsat +glp_write_cnfsat +glp_minisat1 +glp_intfeas1 +glp_init_env +glp_version +glp_free_env +glp_puts +glp_printf +glp_vprintf +glp_term_out +glp_term_hook +glp_open_tee +glp_close_tee +glp_error_ +glp_assert_ +glp_error_hook +glp_alloc +glp_realloc +glp_free +glp_mem_limit +glp_mem_usage +glp_create_graph +glp_set_graph_name +glp_add_vertices +glp_set_vertex_name +glp_add_arc +glp_del_vertices +glp_del_arc +glp_erase_graph +glp_delete_graph +glp_create_v_index +glp_find_vertex +glp_delete_v_index +glp_read_graph +glp_write_graph +glp_mincost_lp +glp_mincost_okalg +glp_mincost_relax4 +glp_maxflow_lp +glp_maxflow_ffalg +glp_check_asnprob +glp_asnprob_lp +glp_asnprob_okalg +glp_asnprob_hall +glp_cpp +glp_read_mincost +glp_write_mincost +glp_read_maxflow +glp_write_maxflow +glp_read_asnprob +glp_write_asnprob +glp_read_ccdata +glp_write_ccdata +glp_netgen +glp_netgen_prob +glp_gridgen +glp_rmfgen +glp_weak_comp +glp_strong_comp +glp_top_sort +glp_wclique_exact +;; end of file ;; diff --git a/resources/3rdparty/glpk-4.53/w32/readme.txt b/resources/3rdparty/glpk-4.53/w32/readme.txt new file mode 100644 index 000000000..10daeda4b --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w32/readme.txt @@ -0,0 +1,24 @@ +This directory contains batch files and other stuff which you can use +to build GLPK for 32-bit Windows with the native C/C++ compilers. + +Before running the batch file do the following: + +1. Make sure that you have installed the compiler you are going to use + to build GLPK. + +2. Look into corresponding batch file (just right-click it and choose + 'Edit' in the popup menu; DO NOT choose 'Open'). Make sure that HOME + variable specifies correct path to the compiler directory; if not, + make necessary changes. + +To run the batch file just double-click it and wait a bit while the +Make utility does its job. The message 'OPTIMAL SOLUTION FOUND' in the +MS-DOS window means that all is OK. If you do not see it, something is +wrong. + +Once GLPK has been successfully built, there must appear two files in +this directory: + +glpk.lib, which is the GLPK object library, and + +glpsol.exe, which is the stand-alone GLPK LP/MIP solver. diff --git a/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10.bat b/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10.bat new file mode 100644 index 000000000..8e8a3e1e7 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Express 2010 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC" + +call %HOME%\vcvarsall.bat x64 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10_DLL.bat b/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10_DLL.bat new file mode 100644 index 000000000..0bbe697b3 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Express 2010 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC" + +call %HOME%\vcvarsall.bat x64 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9.bat b/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9.bat new file mode 100644 index 000000000..9a32ef850 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Express 2008 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC" + +call %HOME%\bin\vcvars64.bat +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9_DLL.bat b/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9_DLL.bat new file mode 100644 index 000000000..4d7c19719 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Express 2008 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC" + +call %HOME%\bin\vcvars64.bat +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/resources/3rdparty/glpk-4.53/w64/config_VC b/resources/3rdparty/glpk-4.53/w64/config_VC new file mode 100644 index 000000000..581ab6e6e --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w64/config_VC @@ -0,0 +1,13 @@ +/* GLPK configuration file (Microsoft Visual Studio Express) */ + +#define __WOE__ 1 + +#define ODBC_DLNAME "odbc32.dll" +/* ODBC shared library name if this feature is enabled */ + +#if 0 +#define MYSQL_DLNAME "libmysql.dll" +/* MySQL shared library name if this feature is enabled */ +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/w64/glpk_4_53.def b/resources/3rdparty/glpk-4.53/w64/glpk_4_53.def new file mode 100644 index 000000000..dc5ed7595 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w64/glpk_4_53.def @@ -0,0 +1,223 @@ +LIBRARY glpk_4_53 +VERSION 4.53 +DESCRIPTION "GNU Linear Programming Kit" +EXPORTS +glp_create_prob +glp_set_prob_name +glp_set_obj_name +glp_set_obj_dir +glp_add_rows +glp_add_cols +glp_set_row_name +glp_set_col_name +glp_set_row_bnds +glp_set_col_bnds +glp_set_obj_coef +glp_set_mat_row +glp_set_mat_col +glp_load_matrix +glp_check_dup +glp_sort_matrix +glp_del_rows +glp_del_cols +glp_copy_prob +glp_erase_prob +glp_delete_prob +glp_get_prob_name +glp_get_obj_name +glp_get_obj_dir +glp_get_num_rows +glp_get_num_cols +glp_get_row_name +glp_get_col_name +glp_get_row_type +glp_get_row_lb +glp_get_row_ub +glp_get_col_type +glp_get_col_lb +glp_get_col_ub +glp_get_obj_coef +glp_get_num_nz +glp_get_mat_row +glp_get_mat_col +glp_create_index +glp_find_row +glp_find_col +glp_delete_index +glp_set_rii +glp_set_sjj +glp_get_rii +glp_get_sjj +glp_scale_prob +glp_unscale_prob +glp_set_row_stat +glp_set_col_stat +glp_std_basis +glp_adv_basis +glp_cpx_basis +glp_simplex +glp_exact +glp_init_smcp +glp_get_status +glp_get_prim_stat +glp_get_dual_stat +glp_get_obj_val +glp_get_row_stat +glp_get_row_prim +glp_get_row_dual +glp_get_col_stat +glp_get_col_prim +glp_get_col_dual +glp_get_unbnd_ray +glp_get_it_cnt +glp_set_it_cnt +glp_interior +glp_init_iptcp +glp_ipt_status +glp_ipt_obj_val +glp_ipt_row_prim +glp_ipt_row_dual +glp_ipt_col_prim +glp_ipt_col_dual +glp_set_col_kind +glp_get_col_kind +glp_get_num_int +glp_get_num_bin +glp_intopt +glp_init_iocp +glp_mip_status +glp_mip_obj_val +glp_mip_row_val +glp_mip_col_val +glp_check_kkt +glp_print_sol +glp_read_sol +glp_write_sol +glp_print_ranges +glp_print_ipt +glp_read_ipt +glp_write_ipt +glp_print_mip +glp_read_mip +glp_write_mip +glp_bf_exists +glp_factorize +glp_bf_updated +glp_get_bfcp +glp_set_bfcp +glp_get_bhead +glp_get_row_bind +glp_get_col_bind +glp_ftran +glp_btran +glp_warm_up +glp_eval_tab_row +glp_eval_tab_col +glp_transform_row +glp_transform_col +glp_prim_rtest +glp_dual_rtest +glp_analyze_bound +glp_analyze_coef +glp_ios_reason +glp_ios_get_prob +glp_ios_tree_size +glp_ios_curr_node +glp_ios_next_node +glp_ios_prev_node +glp_ios_up_node +glp_ios_node_level +glp_ios_node_bound +glp_ios_best_node +glp_ios_mip_gap +glp_ios_node_data +glp_ios_row_attr +glp_ios_pool_size +glp_ios_add_row +glp_ios_del_row +glp_ios_clear_pool +glp_ios_can_branch +glp_ios_branch_upon +glp_ios_select_node +glp_ios_heur_sol +glp_ios_terminate +glp_init_mpscp +glp_read_mps +glp_write_mps +glp_init_cpxcp +glp_read_lp +glp_write_lp +glp_read_prob +glp_write_prob +glp_mpl_alloc_wksp +glp_mpl_read_model +glp_mpl_read_data +glp_mpl_generate +glp_mpl_build_prob +glp_mpl_postsolve +glp_mpl_free_wksp +glp_main +glp_read_cnfsat +glp_check_cnfsat +glp_write_cnfsat +glp_minisat1 +glp_intfeas1 +glp_init_env +glp_version +glp_free_env +glp_puts +glp_printf +glp_vprintf +glp_term_out +glp_term_hook +glp_open_tee +glp_close_tee +glp_error_ +glp_assert_ +glp_error_hook +glp_alloc +glp_realloc +glp_free +glp_mem_limit +glp_mem_usage +glp_create_graph +glp_set_graph_name +glp_add_vertices +glp_set_vertex_name +glp_add_arc +glp_del_vertices +glp_del_arc +glp_erase_graph +glp_delete_graph +glp_create_v_index +glp_find_vertex +glp_delete_v_index +glp_read_graph +glp_write_graph +glp_mincost_lp +glp_mincost_okalg +glp_mincost_relax4 +glp_maxflow_lp +glp_maxflow_ffalg +glp_check_asnprob +glp_asnprob_lp +glp_asnprob_okalg +glp_asnprob_hall +glp_cpp +glp_read_mincost +glp_write_mincost +glp_read_maxflow +glp_write_maxflow +glp_read_asnprob +glp_write_asnprob +glp_read_ccdata +glp_write_ccdata +glp_netgen +glp_netgen_prob +glp_gridgen +glp_rmfgen +glp_weak_comp +glp_strong_comp +glp_top_sort +glp_wclique_exact +;; end of file ;; diff --git a/resources/3rdparty/glpk-4.53/w64/makefile_VC b/resources/3rdparty/glpk-4.53/w64/makefile_VC new file mode 100644 index 000000000..c0c257ea2 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w64/makefile_VC @@ -0,0 +1,191 @@ +## Build GLPK with Microsoft Visual Studio Express ## + +CFLAGS = \ +/I. \ +/I..\src \ +/I..\src\amd \ +/I..\src\bflib \ +/I..\src\cglib \ +/I..\src\colamd \ +/I..\src\env \ +/I..\src\minisat \ +/I..\src\misc \ +/I..\src\proxy \ +/I..\src\zlib \ +/DHAVE_CONFIG_H=1 \ +/D_CRT_SECURE_NO_WARNINGS=1 \ +/nologo \ +/W3 \ +/O2 + +OBJSET = \ +..\src\avl.obj \ +..\src\bfd.obj \ +..\src\bfx.obj \ +..\src\glpapi01.obj \ +..\src\glpapi02.obj \ +..\src\glpapi03.obj \ +..\src\glpapi04.obj \ +..\src\glpapi05.obj \ +..\src\glpapi06.obj \ +..\src\glpapi07.obj \ +..\src\glpapi08.obj \ +..\src\glpapi09.obj \ +..\src\glpapi10.obj \ +..\src\glpapi11.obj \ +..\src\glpapi12.obj \ +..\src\glpapi13.obj \ +..\src\glpapi14.obj \ +..\src\glpapi15.obj \ +..\src\glpapi16.obj \ +..\src\glpapi17.obj \ +..\src\glpapi18.obj \ +..\src\glpapi19.obj \ +..\src\glpapi20.obj \ +..\src\glpapi21.obj \ +..\src\glpcpx.obj \ +..\src\glpdmx.obj \ +..\src\glpgmp.obj \ +..\src\glphbm.obj \ +..\src\glpini01.obj \ +..\src\glpini02.obj \ +..\src\glpios01.obj \ +..\src\glpios02.obj \ +..\src\glpios03.obj \ +..\src\glpios04.obj \ +..\src\glpios05.obj \ +..\src\glpios06.obj \ +..\src\glpios07.obj \ +..\src\glpios08.obj \ +..\src\glpios09.obj \ +..\src\glpios10.obj \ +..\src\glpios11.obj \ +..\src\glpios12.obj \ +..\src\glpipm.obj \ +..\src\glplpf.obj \ +..\src\glpmat.obj \ +..\src\glpmpl01.obj \ +..\src\glpmpl02.obj \ +..\src\glpmpl03.obj \ +..\src\glpmpl04.obj \ +..\src\glpmpl05.obj \ +..\src\glpmpl06.obj \ +..\src\glpmps.obj \ +..\src\glpnet03.obj \ +..\src\glpnet04.obj \ +..\src\glpnet05.obj \ +..\src\glpnpp01.obj \ +..\src\glpnpp02.obj \ +..\src\glpnpp03.obj \ +..\src\glpnpp04.obj \ +..\src\glpnpp05.obj \ +..\src\glpnpp06.obj \ +..\src\glprgr.obj \ +..\src\glpscl.obj \ +..\src\glpsdf.obj \ +..\src\glpspm.obj \ +..\src\glpspx01.obj \ +..\src\glpspx02.obj \ +..\src\glpsql.obj \ +..\src\glpssx01.obj \ +..\src\glpssx02.obj \ +..\src\glptsp.obj \ +..\src\lux.obj \ +..\src\amd\amd_1.obj \ +..\src\amd\amd_2.obj \ +..\src\amd\amd_aat.obj \ +..\src\amd\amd_control.obj \ +..\src\amd\amd_defaults.obj \ +..\src\amd\amd_dump.obj \ +..\src\amd\amd_info.obj \ +..\src\amd\amd_order.obj \ +..\src\amd\amd_post_tree.obj \ +..\src\amd\amd_postorder.obj \ +..\src\amd\amd_preprocess.obj \ +..\src\amd\amd_valid.obj \ +..\src\bflib\fhv.obj \ +..\src\bflib\fhvint.obj \ +..\src\bflib\ifu.obj \ +..\src\bflib\luf.obj \ +..\src\bflib\lufint.obj \ +..\src\bflib\sgf.obj \ +..\src\bflib\sva.obj \ +..\src\cglib\cfg.obj \ +..\src\cglib\cfg1.obj \ +..\src\colamd\colamd.obj \ +..\src\env\alloc.obj \ +..\src\env\dlsup.obj \ +..\src\env\env.obj \ +..\src\env\error.obj \ +..\src\env\stdout.obj \ +..\src\env\stream.obj \ +..\src\env\time.obj \ +..\src\env\tls.obj \ +..\src\minisat\minisat.obj \ +..\src\misc\bignum.obj \ +..\src\misc\dmp.obj \ +..\src\misc\ffalg.obj \ +..\src\misc\fp2rat.obj \ +..\src\misc\gcd.obj \ +..\src\misc\jd.obj \ +..\src\misc\keller.obj \ +..\src\misc\mc13d.obj \ +..\src\misc\mc21a.obj \ +..\src\misc\okalg.obj \ +..\src\misc\qmd.obj \ +..\src\misc\relax4.obj \ +..\src\misc\rng.obj \ +..\src\misc\rng1.obj \ +..\src\misc\round2n.obj \ +..\src\misc\str2int.obj \ +..\src\misc\str2num.obj \ +..\src\misc\strspx.obj \ +..\src\misc\strtrim.obj \ +..\src\misc\triang.obj \ +..\src\misc\wclique.obj \ +..\src\misc\wclique1.obj \ +..\src\proxy\proxy.obj \ +..\src\proxy\proxy1.obj \ +..\src\zlib\adler32.obj \ +..\src\zlib\compress.obj \ +..\src\zlib\crc32.obj \ +..\src\zlib\deflate.obj \ +..\src\zlib\gzclose.obj \ +..\src\zlib\gzlib.obj \ +..\src\zlib\gzread.obj \ +..\src\zlib\gzwrite.obj \ +..\src\zlib\inffast.obj \ +..\src\zlib\inflate.obj \ +..\src\zlib\inftrees.obj \ +..\src\zlib\trees.obj \ +..\src\zlib\uncompr.obj \ +..\src\zlib\zio.obj \ +..\src\zlib\zutil.obj + +.c.obj: + cl.exe $(CFLAGS) /Fo$*.obj /c $*.c + +all: glpk.lib glpsol.exe + +glpk.lib: $(OBJSET) + lib.exe /out:glpk.lib \ + ..\src\*.obj \ + ..\src\amd\*.obj \ + ..\src\bflib\*.obj \ + ..\src\cglib\*.obj \ + ..\src\colamd\*.obj \ + ..\src\env\*.obj \ + ..\src\minisat\*.obj \ + ..\src\misc\*.obj \ + ..\src\proxy\*.obj \ + ..\src\zlib\*.obj + +glpsol.exe: ..\examples\glpsol.obj glpk.lib + cl.exe $(CFLAGS) /Feglpsol.exe \ + ..\examples\glpsol.obj glpk.lib + +check: glpsol.exe + .\glpsol.exe --version + .\glpsol.exe --mps ..\examples\plan.mps + +## eof ## diff --git a/resources/3rdparty/glpk-4.53/w64/makefile_VC_DLL b/resources/3rdparty/glpk-4.53/w64/makefile_VC_DLL new file mode 100644 index 000000000..9eb7a6586 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w64/makefile_VC_DLL @@ -0,0 +1,192 @@ +## Build GLPK DLL with Microsoft Visual Studio Express ## + +CFLAGS = \ +/I. \ +/I..\src \ +/I..\src\amd \ +/I..\src\bflib \ +/I..\src\cglib \ +/I..\src\colamd \ +/I..\src\env \ +/I..\src\minisat \ +/I..\src\misc \ +/I..\src\proxy \ +/I..\src\zlib \ +/DHAVE_CONFIG_H=1 \ +/D_CRT_SECURE_NO_WARNINGS=1 \ +/nologo \ +/W3 \ +/O2 + +OBJSET = \ +..\src\avl.obj \ +..\src\bfd.obj \ +..\src\bfx.obj \ +..\src\glpapi01.obj \ +..\src\glpapi02.obj \ +..\src\glpapi03.obj \ +..\src\glpapi04.obj \ +..\src\glpapi05.obj \ +..\src\glpapi06.obj \ +..\src\glpapi07.obj \ +..\src\glpapi08.obj \ +..\src\glpapi09.obj \ +..\src\glpapi10.obj \ +..\src\glpapi11.obj \ +..\src\glpapi12.obj \ +..\src\glpapi13.obj \ +..\src\glpapi14.obj \ +..\src\glpapi15.obj \ +..\src\glpapi16.obj \ +..\src\glpapi17.obj \ +..\src\glpapi18.obj \ +..\src\glpapi19.obj \ +..\src\glpapi20.obj \ +..\src\glpapi21.obj \ +..\src\glpcpx.obj \ +..\src\glpdmx.obj \ +..\src\glpgmp.obj \ +..\src\glphbm.obj \ +..\src\glpini01.obj \ +..\src\glpini02.obj \ +..\src\glpios01.obj \ +..\src\glpios02.obj \ +..\src\glpios03.obj \ +..\src\glpios04.obj \ +..\src\glpios05.obj \ +..\src\glpios06.obj \ +..\src\glpios07.obj \ +..\src\glpios08.obj \ +..\src\glpios09.obj \ +..\src\glpios10.obj \ +..\src\glpios11.obj \ +..\src\glpios12.obj \ +..\src\glpipm.obj \ +..\src\glplpf.obj \ +..\src\glpmat.obj \ +..\src\glpmpl01.obj \ +..\src\glpmpl02.obj \ +..\src\glpmpl03.obj \ +..\src\glpmpl04.obj \ +..\src\glpmpl05.obj \ +..\src\glpmpl06.obj \ +..\src\glpmps.obj \ +..\src\glpnet03.obj \ +..\src\glpnet04.obj \ +..\src\glpnet05.obj \ +..\src\glpnpp01.obj \ +..\src\glpnpp02.obj \ +..\src\glpnpp03.obj \ +..\src\glpnpp04.obj \ +..\src\glpnpp05.obj \ +..\src\glpnpp06.obj \ +..\src\glprgr.obj \ +..\src\glpscl.obj \ +..\src\glpsdf.obj \ +..\src\glpspm.obj \ +..\src\glpspx01.obj \ +..\src\glpspx02.obj \ +..\src\glpsql.obj \ +..\src\glpssx01.obj \ +..\src\glpssx02.obj \ +..\src\glptsp.obj \ +..\src\lux.obj \ +..\src\amd\amd_1.obj \ +..\src\amd\amd_2.obj \ +..\src\amd\amd_aat.obj \ +..\src\amd\amd_control.obj \ +..\src\amd\amd_defaults.obj \ +..\src\amd\amd_dump.obj \ +..\src\amd\amd_info.obj \ +..\src\amd\amd_order.obj \ +..\src\amd\amd_post_tree.obj \ +..\src\amd\amd_postorder.obj \ +..\src\amd\amd_preprocess.obj \ +..\src\amd\amd_valid.obj \ +..\src\bflib\fhv.obj \ +..\src\bflib\fhvint.obj \ +..\src\bflib\ifu.obj \ +..\src\bflib\luf.obj \ +..\src\bflib\lufint.obj \ +..\src\bflib\sgf.obj \ +..\src\bflib\sva.obj \ +..\src\cglib\cfg.obj \ +..\src\cglib\cfg1.obj \ +..\src\colamd\colamd.obj \ +..\src\env\alloc.obj \ +..\src\env\dlsup.obj \ +..\src\env\env.obj \ +..\src\env\error.obj \ +..\src\env\stdout.obj \ +..\src\env\stream.obj \ +..\src\env\time.obj \ +..\src\env\tls.obj \ +..\src\minisat\minisat.obj \ +..\src\misc\bignum.obj \ +..\src\misc\dmp.obj \ +..\src\misc\ffalg.obj \ +..\src\misc\fp2rat.obj \ +..\src\misc\gcd.obj \ +..\src\misc\jd.obj \ +..\src\misc\keller.obj \ +..\src\misc\mc13d.obj \ +..\src\misc\mc21a.obj \ +..\src\misc\okalg.obj \ +..\src\misc\qmd.obj \ +..\src\misc\relax4.obj \ +..\src\misc\rng.obj \ +..\src\misc\rng1.obj \ +..\src\misc\round2n.obj \ +..\src\misc\str2int.obj \ +..\src\misc\str2num.obj \ +..\src\misc\strspx.obj \ +..\src\misc\strtrim.obj \ +..\src\misc\triang.obj \ +..\src\misc\wclique.obj \ +..\src\misc\wclique1.obj \ +..\src\proxy\proxy.obj \ +..\src\proxy\proxy1.obj \ +..\src\zlib\adler32.obj \ +..\src\zlib\compress.obj \ +..\src\zlib\crc32.obj \ +..\src\zlib\deflate.obj \ +..\src\zlib\gzclose.obj \ +..\src\zlib\gzlib.obj \ +..\src\zlib\gzread.obj \ +..\src\zlib\gzwrite.obj \ +..\src\zlib\inffast.obj \ +..\src\zlib\inflate.obj \ +..\src\zlib\inftrees.obj \ +..\src\zlib\trees.obj \ +..\src\zlib\uncompr.obj \ +..\src\zlib\zio.obj \ +..\src\zlib\zutil.obj + +.c.obj: + cl.exe $(CFLAGS) /Fo$*.obj /c $*.c + +all: glpk_4_53.dll glpsol.exe + +glpk_4_53.dll: $(OBJSET) + cl.exe $(CFLAGS) /LD /Feglpk_4_53.dll \ + ..\src\*.obj \ + ..\src\amd\*.obj \ + ..\src\bflib\*.obj \ + ..\src\cglib\*.obj \ + ..\src\colamd\*.obj \ + ..\src\env\*.obj \ + ..\src\minisat\*.obj \ + ..\src\misc\*.obj \ + ..\src\proxy\*.obj \ + ..\src\zlib\*.obj \ + glpk_4_53.def + +glpsol.exe: ..\examples\glpsol.obj glpk_4_53.dll + cl.exe $(CFLAGS) /Feglpsol.exe \ + ..\examples\glpsol.obj glpk_4_53.lib + +check: glpsol.exe + .\glpsol.exe --version + .\glpsol.exe --mps ..\examples\plan.mps + +## eof ## diff --git a/resources/3rdparty/glpk-4.53/w64/readme.txt b/resources/3rdparty/glpk-4.53/w64/readme.txt new file mode 100644 index 000000000..d5742d964 --- /dev/null +++ b/resources/3rdparty/glpk-4.53/w64/readme.txt @@ -0,0 +1,24 @@ +This directory contains batch files and other stuff which you can use +to build GLPK for 64-bit Windows with the native C/C++ compilers. + +Before running the batch file do the following: + +1. Make sure that you have installed the compiler you are going to use + to build GLPK. + +2. Look into corresponding batch file (just right-click it and choose + 'Edit' in the popup menu; DO NOT choose 'Open'). Make sure that HOME + variable specifies correct path to the compiler directory; if not, + make necessary changes. + +To run the batch file just double-click it and wait a bit while the +Make utility does its job. The message 'OPTIMAL SOLUTION FOUND' in the +MS-DOS window means that all is OK. If you do not see it, something is +wrong. + +Once GLPK has been successfully built, there must appear two files in +this directory: + +glpk.lib, which is the GLPK object library, and + +glpsol.exe, which is the stand-alone GLPK LP/MIP solver. From a6e7e6b4e0556ff97960cdc4c5b7c687216870d5 Mon Sep 17 00:00:00 2001 From: PBerger <philipp.berger@rwth-aachen.de> Date: Thu, 27 Feb 2014 18:57:16 +0100 Subject: [PATCH 4/5] Edited GurobiLpSolver.cpp, added the error code to the messages. Former-commit-id: d14dc05cda1c5ca4aed9e559c7ef16ec32aaf057 --- src/solver/GurobiLpSolver.cpp | 92 +++++++++++++++++------------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/solver/GurobiLpSolver.cpp b/src/solver/GurobiLpSolver.cpp index a471781a8..378a3e583 100644 --- a/src/solver/GurobiLpSolver.cpp +++ b/src/solver/GurobiLpSolver.cpp @@ -27,8 +27,8 @@ namespace storm { // Create the environment. int error = GRBloadenv(&env, ""); if (error || env == nullptr) { - LOG4CPLUS_ERROR(logger, "Could not initialize Gurobi (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Could not initialize Gurobi environment (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Could not initialize Gurobi (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Could not initialize Gurobi environment (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } // Set some general properties of the environment. @@ -37,8 +37,8 @@ namespace storm { // Create the model. error = GRBnewmodel(env, &model, name.c_str(), 0, nullptr, nullptr, nullptr, nullptr, nullptr); if (error) { - LOG4CPLUS_ERROR(logger, "Could not initialize Gurobi model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Could not initialize Gurobi model (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Could not initialize Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Could not initialize Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } } @@ -74,8 +74,8 @@ namespace storm { void GurobiLpSolver::update() const { int error = GRBupdatemodel(model); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to update Gurobi model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to update Gurobi model (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to update Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to update Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } // Since the model changed, we erase the optimality flag. @@ -100,8 +100,8 @@ namespace storm { } if (error) { - LOG4CPLUS_ERROR(logger, "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } ++nextVariableIndex; return nextVariableIndex - 1; @@ -125,8 +125,8 @@ namespace storm { } if (error) { - LOG4CPLUS_ERROR(logger, "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } ++nextVariableIndex; return nextVariableIndex - 1; @@ -135,8 +135,8 @@ namespace storm { uint_fast64_t GurobiLpSolver::createBinaryVariable(std::string const& name, double objectiveFunctionCoefficient) { int error = GRBaddvar(model, 0, nullptr, nullptr, objectiveFunctionCoefficient, 0.0, 1.0, GRB_BINARY, name.c_str()); if (error) { - LOG4CPLUS_ERROR(logger, "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Could not create binary Gurobi variable (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } ++nextVariableIndex; return nextVariableIndex - 1; @@ -170,8 +170,8 @@ namespace storm { int error = GRBaddconstr(model, variablesCopy.size(), variablesCopy.data(), coefficientsCopy.data(), sense, rightHandSideValue, name == "" ? nullptr : name.c_str()); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to assert Gurobi constraint (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to assert Gurobi constraint (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to assert Gurobi constraint (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to assert Gurobi constraint (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } } @@ -182,15 +182,15 @@ namespace storm { // Set the most recently set model sense. int error = GRBsetintattr(model, "ModelSense", this->getModelSense() == MINIMIZE ? 1 : -1); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi model sense (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi model sense (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to set Gurobi model sense (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi model sense (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } // Then we actually optimize the model. error = GRBoptimize(model); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to optimize Gurobi model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to optimize Gurobi model (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to optimize Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to optimize Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } this->currentModelHasBeenOptimized = true; @@ -205,8 +205,8 @@ namespace storm { int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } // By default, Gurobi may tell us only that the model is either infeasible or unbounded. To decide which one @@ -215,22 +215,22 @@ namespace storm { std::cout << "here" << std::endl; error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 0); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } this->optimize(); error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 1); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } } @@ -246,8 +246,8 @@ namespace storm { int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } // By default, Gurobi may tell us only that the model is either infeasible or unbounded. To decide which one @@ -255,22 +255,22 @@ namespace storm { if (optimalityStatus == GRB_INF_OR_UNBD) { error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 0); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } this->optimize(); error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } error = GRBsetintparam(GRBgetenv(model), GRB_INT_PAR_DUALREDUCTIONS, 1); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi parameter (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } } @@ -285,8 +285,8 @@ namespace storm { int error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimalityStatus); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to retrieve optimization status of Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } return optimalityStatus == GRB_OPTIMAL; @@ -309,8 +309,8 @@ namespace storm { double value = 0; int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, variableIndex, &value); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } if (std::abs(value - static_cast<int>(value)) <= storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble()) { @@ -340,8 +340,8 @@ namespace storm { double value = 0; int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, variableIndex, &value); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } if (std::abs(value - 1) <= storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble()) { @@ -371,8 +371,8 @@ namespace storm { double value = 0; int error = GRBgetdblattrelement(model, GRB_DBL_ATTR_X, variableIndex, &value); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } return value; @@ -395,8 +395,8 @@ namespace storm { double value = 0; int error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &value); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ")."); - throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ")."; + LOG4CPLUS_ERROR(logger, "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to get Gurobi solution (" << GRBgeterrormsg(env) << ", error code " << error << ")."; } return value; @@ -405,8 +405,8 @@ namespace storm { void GurobiLpSolver::writeModelToFile(std::string const& filename) const { int error = GRBwrite(model, filename.c_str()); if (error) { - LOG4CPLUS_ERROR(logger, "Unable to write Gurobi model (" << GRBgeterrormsg(env) << ") to file."); - throw storm::exceptions::InvalidStateException() << "Unable to write Gurobi model (" << GRBgeterrormsg(env) << ") to file."; + LOG4CPLUS_ERROR(logger, "Unable to write Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ") to file."); + throw storm::exceptions::InvalidStateException() << "Unable to write Gurobi model (" << GRBgeterrormsg(env) << ", error code " << error << ") to file."; } } } From 68a6e533be89875abee500bdb2b7f009f41b5a8c Mon Sep 17 00:00:00 2001 From: PBerger <philipp.berger@rwth-aachen.de> Date: Fri, 28 Feb 2014 23:40:31 +0100 Subject: [PATCH 5/5] Added error handling in GurobiLpSolver.cpp Fixed a bug related to commit 486e99d6ae3af914cf37f693a673dd2036939fd8 [formerly 1300d77ae8f7ed518adc139c596f4d5a03fa3a51] where updateModel was not called before adding constraints in the GurobiLpSolverTest.cpp Former-commit-id: 9f619e50396275829eebd9ecb097dc071dcaf43f --- src/solver/GurobiLpSolver.cpp | 20 ++++++++++++++--- test/functional/solver/GurobiLpSolverTest.cpp | 22 ++++++++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/solver/GurobiLpSolver.cpp b/src/solver/GurobiLpSolver.cpp index 378a3e583..c06233942 100644 --- a/src/solver/GurobiLpSolver.cpp +++ b/src/solver/GurobiLpSolver.cpp @@ -61,14 +61,28 @@ namespace storm { } void GurobiLpSolver::setGurobiEnvironmentProperties() const { - // Enable the following line to only print the output of Gurobi if the debug flag is set. - int error = error = GRBsetintparam(env, "OutputFlag", storm::settings::Settings::getInstance()->isSet("debug") || storm::settings::Settings::getInstance()->isSet("gurobioutput") ? 1 : 0); + int error = 0; + + // Enable the following line to only print the output of Gurobi if the debug flag is set. + error = GRBsetintparam(env, "OutputFlag", storm::settings::Settings::getInstance()->isSet("debug") || storm::settings::Settings::getInstance()->isSet("gurobioutput") ? 1 : 0); + if (error) { + LOG4CPLUS_ERROR(logger, "Unable to set Gurobi Parameter OutputFlag (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi Parameter OutputFlag (" << GRBgeterrormsg(env) << ", error code " << error << ")."; + } // Enable the following line to restrict Gurobi to one thread only. error = GRBsetintparam(env, "Threads", storm::settings::Settings::getInstance()->getOptionByLongName("gurobithreads").getArgument(0).getValueAsUnsignedInteger()); - + if (error) { + LOG4CPLUS_ERROR(logger, "Unable to set Gurobi Parameter Threads (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi Parameter Threads (" << GRBgeterrormsg(env) << ", error code " << error << ")."; + } + // Enable the following line to force Gurobi to be as precise about the binary variables as required by the given precision option. error = GRBsetdblparam(env, "IntFeasTol", storm::settings::Settings::getInstance()->getOptionByLongName("gurobiinttol").getArgument(0).getValueAsDouble()); + if (error) { + LOG4CPLUS_ERROR(logger, "Unable to set Gurobi Parameter IntFeasTol (" << GRBgeterrormsg(env) << ", error code " << error << ")."); + throw storm::exceptions::InvalidStateException() << "Unable to set Gurobi Parameter IntFeasTol (" << GRBgeterrormsg(env) << ", error code " << error << ")."; + } } void GurobiLpSolver::update() const { diff --git a/test/functional/solver/GurobiLpSolverTest.cpp b/test/functional/solver/GurobiLpSolverTest.cpp index b8c7fe885..ce9f0a2bc 100644 --- a/test/functional/solver/GurobiLpSolverTest.cpp +++ b/test/functional/solver/GurobiLpSolverTest.cpp @@ -15,9 +15,11 @@ TEST(GurobiLpSolver, LPOptimizeMax) { uint_fast64_t zIndex; ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); - ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); - ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); + ASSERT_NO_THROW(solver.update()); + + ASSERT_NO_THROW(solver.addConstraint("a", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); + ASSERT_NO_THROW(solver.addConstraint("b", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); + ASSERT_NO_THROW(solver.addConstraint("c", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); ASSERT_NO_THROW(solver.optimize()); ASSERT_TRUE(solver.isOptimal()); @@ -50,6 +52,8 @@ TEST(GurobiLpSolver, LPOptimizeMin) { uint_fast64_t zIndex; ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::BOUNDED, 1, 5.7, -1)); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); @@ -85,6 +89,8 @@ TEST(GurobiLpSolver, MILPOptimizeMax) { uint_fast64_t zIndex; ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); @@ -120,6 +126,8 @@ TEST(GurobiLpSolver, MILPOptimizeMin) { uint_fast64_t zIndex; ASSERT_NO_THROW(zIndex = solver.createIntegerVariable("z", storm::solver::LpSolver::VariableType::BOUNDED, 0, 5.7, -1)); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); @@ -155,6 +163,8 @@ TEST(GurobiLpSolver, LPInfeasible) { uint_fast64_t zIndex; ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); @@ -187,6 +197,8 @@ TEST(GurobiLpSolver, MILPInfeasible) { uint_fast64_t zIndex; ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, 1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, zIndex, xIndex}, {0.5, 1, -1}, storm::solver::LpSolver::BoundType::EQUAL, 5)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); @@ -219,6 +231,8 @@ TEST(GurobiLpSolver, LPUnbounded) { uint_fast64_t zIndex; ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5)); @@ -249,6 +263,8 @@ TEST(GurobiLpSolver, MILPUnbounded) { uint_fast64_t zIndex; ASSERT_NO_THROW(zIndex = solver.createContinuousVariable("z", storm::solver::LpSolver::VariableType::LOWER_BOUND, 0, 0, 1)); + ASSERT_NO_THROW(solver.update()); + ASSERT_NO_THROW(solver.addConstraint("", {xIndex, yIndex, zIndex}, {1, 1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 12)); ASSERT_NO_THROW(solver.addConstraint("", {yIndex, xIndex}, {1, -1}, storm::solver::LpSolver::BoundType::LESS_EQUAL, 5.5));